从 shutdown 到 systemctl 的符号链接如何工作?

从 shutdown 到 systemctl 的符号链接如何工作?
which shutdown

返回

/usr/bin/shutdown

我也尝试过sudo which shutdown以防万一......但结果是一样的。

我理解了

lrwxrwxrwx 1 root root 9 Dec 13 03:38 /usr/bin/shutdown -> systemctl

我还可以做类似的事情(2 小时后关闭机器)

sudo shutdown -h +120

但如果我尝试一些像这样愚蠢的事情:

 sudo systemctl -h +120

我收到一个错误...

当我发出时,shutdown我是否实际上调用了/usr/bin/shutdown?如果是这样,那么从关机到 systemctl 的链接实际上是如何工作的?

答案1

简短回答

程序可以知道它被调用时的名称;它通过检查来学习自己的名称argv[0]。这允许相同的可执行文件在不同名称下表现不同(例子)或单个可执行文件,当通过不同命名的符号链接调用时,其行为会有所不同(例子)。

在你的情况下,实际的systemctl可执行文件知道它是否被调用为systemctlshutdown或其他。它会相应地调整其行为。


额外细节

参数数组由父进程设置。argv[0]名称是约定(不是严格要求)。父进程可能会也可能不会遵循约定。当您从 shell 运行systemctlshutdown时,shell 是父进程,它遵循约定;一般来说,shell 遵循约定。

不遵守惯例的一个例子是 的行为login(以及试图模仿它的工具):login在第零个参数中使用前导破折号来通知子 shell 它应该是登录 shell。假设登录 shell 是 Bash。在 shell 中将echo "$0"显示-bash,尽管可执行文件名为bash。这个前导破折号是其他习俗。

您可以systemctl使用任意名称运行。有些名称很特殊,它们会改变的行为systemctl,这是为了支持您观察到的符号链接。在我的 Debian 12 中,这些是(其中包括)shutdownrunlevel。您不需要创建符号链接或副本来将任意内容传递argv[0]systemctl,您可以使用exec -aBash。


使用任意示例argv[0]

systemctl(假设可以通过 到达示例$PATH。如果需要,请提供完整路径名。)

bash -c 'exec -a foo      systemctl'        # should behave like plain systemctl because foo is not a name that would change the behavior
bash -c 'exec -a shutdown systemctl --help' # should behave like shutdown --help
bash -c 'exec -a runlevel systemctl'        # should behave like runlevel

实际上,您可以使用符号链接systemctl(如您的shutdown)并传递任意的argv[0]。例如:

bash -c 'exec -a runlevel shutdown'         # should behave like runlevel

修复你的“愚蠢的命令”

你的“愚蠢命令”

sudo systemctl -h +120

可以像这样修复:

sudo bash -c 'exec -a shutdown systemctl -h +120'

shutdown这里根本没有使用命名的符号链接(它可能不存在),systemctl而是直接调用可执行文件;它仍然表现得像shutdown因为我们传递了正确的名称(shutdown)作为argv[0]

相关内容