reboot, shutdown, halt & systemctl

If you have been working on Linux for some time — longer than a few years, you probably has come from runlevel days which the services are managed by SysV init scripts. So you are familiar with the commands like shutdown, init, halt, reboot etc. which are used to start, stop or bring the system into different runlevels.

With SysV, services are managed at different runlevels while in systemd, targets are used to for different states that your system can boot into.

Nowdays, all popular Linux distributions have moved to systemd. But like me you may still use commands shutdown, reboot instead of systemctl to shutdown or restart a Linux server. Have you noticed that on a systemd system, those commands are just symbolic links to systemctl?

root@joetest:~# ls -lart /usr/sbin|grep systemctl
lrwxrwxrwx.  1 root root           16 Nov 10  2021 telinit -> ../bin/systemctl
lrwxrwxrwx.  1 root root           16 Nov 10  2021 shutdown -> ../bin/systemctl
lrwxrwxrwx.  1 root root           16 Nov 10  2021 runlevel -> ../bin/systemctl
lrwxrwxrwx.  1 root root           16 Nov 10  2021 reboot -> ../bin/systemctl
lrwxrwxrwx.  1 root root           16 Nov 10  2021 poweroff -> ../bin/systemctl
lrwxrwxrwx.  1 root root           16 Nov 10  2021 halt -> ../bin/systemctl

You may wonder how these things work because when you run systemctl directly without any arguments, you get a list of target units. But when you run those symbolic links like reboot or shutdown, they actually reboot or shutdown a system.

Basically those symbolic links are backward compatibility shims. The actual work is done by systemctl. And to provide different behaviour even they are pointed to the same program, systemctl has a code block to determine what action to perform based on how it was called/executed.

It is a popular technique where there is a single executable that changes its behaviour based on how it was executed. It’s the standard behaviour for all shells. For example, with BASH, you can easily display this behaviour with the following simple script:

#!/bin/bash

me=`basename "$0"`

echo $me

me="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"

echo $me

create a symbolic link to this script, then run the script directly vs run the symbolic link, you will see how it works. In a nutshell, in a systemd system, systemctl is responsible for shutdown or reboot the system. The shell (e.g BASH) tells systemctl what to do when you use SysV commands (symbolic links actually).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s