As pa4080 says, it's just a normal symbolic link, and systemctl
itself is what checks what name it has been run as, in order to decide what action to perform. This sort of thing can be achieved with any mechanism that causes the same executable file to be run under multiple names; in practice, it is achieved through the use of symlinks or hard links. On GNU/Linux systems, like Ubuntu, it's most common to use symlinks for this purpose.
In Ubuntu releases with systemd (which currently includes all supported releases except 14.04 LTS, which uses Upstart), not just the reboot
command but also the halt
, poweroff
, runlevel
, shutdown
, and telinit
commands are all symlinks to /bin/systemctl
:
$ file /sbin/{halt,poweroff,reboot,runlevel,shutdown,telinit}
/sbin/halt: symbolic link to /bin/systemctl
/sbin/poweroff: symbolic link to /bin/systemctl
/sbin/reboot: symbolic link to /bin/systemctl
/sbin/runlevel: symbolic link to /bin/systemctl
/sbin/shutdown: symbolic link to /bin/systemctl
/sbin/telinit: symbolic link to /bin/systemctl
The precise actions systemctl
undertakes based on the name you use to run it, as well as other ways you can specify those actions, are explained in detail in this excellent answer by JdeBP to What is the difference between these commands for bringing down a Linux server? on Unix.SE. As it explains, these commands (except runlevel
) operate as shorthand for systemctl isolate ...
commands with ...
replaced by different targets.
In case you're interested, the C code that considers what name you used to invoke systemctl
in deciding what action to perform is located in the parse_argv
function defined in systemctl.c
, which currently starts on line 6972 of that file. To find it you can search for:
static int parse_argv(int argc, char *argv[]) {
The relevant parts span most of that function, but it all roughly resembles this fragment of it, continuing similarly but with different code for each string, and with some other checks and branching logic:
if (strstr(program_invocation_short_name, "halt")) {
arg_action = ACTION_HALT;
return halt_parse_argv(argc, argv);
} else if (strstr(program_invocation_short_name, "poweroff")) {
arg_action = ACTION_POWEROFF;
return halt_parse_argv(argc, argv);
} else if (strstr(program_invocation_short_name, "reboot")) {
Other examples of commands that examine how they were invoked to (sometimes) act differently include vim
, which behaves differently when run as vim
, ex
, view
, gvim
, gview
, and several others; ip
, see this question; gksu
, see that question; less
, which changes its appearance if named more
(but still lets you scroll bidirectionally, unlike Ubuntu's more
); busybox
; and most Bourne-style shells, such as bash
and zsh
, which automatically behave more compatibly with POSIX requirements for sh
if run as sh
.