1

Someone told me that it's possible to group machines you want to shutdown together, and that you can turn them off using the standard shutdown command in bash.

How would one go about setting this up?

4
0

Assuming you have ssh access set up on all computers in question something like

while read host; do
    ssh "root@$host" shutdown -h now &
done < host-list 

should work. If you need it configurable just put the host list into a config-like file.

2
  • This is obviously assuming root login over SSH is not prohibited, and that public SSH keys have been distributed to the root accounts on all hosts for the local user. – Kusalananda Jul 14 '18 at 12:14
  • 1
    @kusalananda Yes :-) Can be done with another user account and sudo as well of course. But any attempt to remotely shutdown a system will require a local login of some kind. – nohillside Jul 14 '18 at 12:27
0

First of all, to answer your question, shutdown on its own is a local function. It has no concept of a cluster. It doesn't know how to send a message over your network. What can be a bit confusing is that it uses the wall command to tell all the users that the computer is going to be shutdown. But this is only the users currently connected to that computer. Not all users on your network (again, wall is a local command).

On my end, I'm using an embedded software on a LAN where the system has one controller and N service computers (9 in my test). The controller needs to have a Shutdown function which turns off the entire system and ssh or shutdown are not really that great in such an environment.

Instead, what I do is create a command that can run shutdown on its own. This is very simple with a very small C binary:

int main()
{
    setuid(0);
    system("shutdown -t now");  // adapt the command to what you like
}

You compile that with:

gcc -o my-shutdown my-shutdown.c

Then you install it somewhere such as /usr/sbin

cp my-shutdown /usr/sbin
chown root:root /usr/sbin/my-shutdown
chmod 4755 /usr/sbin/my-shutdown

Now you have a command you can run from any user and that will shutdown your remote computers.

Important Note: This is, of course, not so safe on a public system. It works for me because I have a form of embedded system. At the same time, a shutdown won't destroy your computer. It may destroy the functionality, though.

Next, we want to be able to trigger that command from another computer. That requires us to have a server which runs on each of the service computer and listens for a connection. If you already have such a program running on your system, it should be easy to just add support for a message and run that C binary above. It will then run the shutdown command.


Below I have a very simple TCP server written in NodeJS, which may not be practical in your situation, but it gives you the basic idea if you don't already have such a service running on your service computers.

Actually, if you could write it in C, then it could be included in the tool I showed above (i.e. change that command line into a server running as root, then you don't even need the setuid() function call).

#!/usr/bin/env node

var net = require('net')
var runner = require('child_process')

var server = net.createServer((c) => {
    console.log('client connected')
    c.on('end', () => {
        console.log('client disconnected')
    });
    c.write('SHUTTING DOWN\r\n')

    // this could also directly be the `shutdown -t now` command
    // (assuming we run this service as root)
    runner.exec("/usr/sbin/my-shutdown")

    c.destroy()
})

server.on('error', (err) => {
    throw err
})

server.listen(2001, '10.0.2.10', (err) => {
    if(err) {
        console.log(`can not start listening on port: 1234, ${err}`)
        return
    }

    console.log('server listening on 10.0.2.10:2001');
})

Finally, you can start this NodeJS process with systemd. Say you call it /usr/sbin/my-shutdown-server then you'd write a configuration file such as:

[Unit]
Description=My Shutdown Daemon

[Service]
Type=simple
ExecStart=/usr/sbin/my-shutdown-server
ExecStop=/bin/kill "$MAINPID"
Restart=on-failure

[Install]
WantedBy=multi-user.target

Note: with the default, the service runs as root. The User= and Group= can be used to change that to another user.

Save this file under /lib/systemd/system/ with a name such as my-shutdown-server and now you can enable & start it:

sudo systemctl enable my-shutdown-server
sudo systemctl start my-shutdown-server

From your controller, you can test sending the message (in this example, the mere connection is enough to trigger the shutdown!) with nc such as:

nc 10.0.2.10 2001

You should get a reply message: "SHUTTING DOWN" and the computer should shutdown. The reply message may never make it unless you have at least a small pause before the shutdown happens (i.e. 5 seconds instead of "now" would do).

Again, the security here is non-existent. Anyone who can access those computers will be able to shut them down. By enhancing the server you could send any type of command, not just do a shutdown (i.e. reboot, restart your app. without a reboot, etc.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.