/sbin/reboot 是什么样的 /bin/systemctl 链接?

/sbin/reboot 是什么样的 /bin/systemctl 链接?

这个问题很蠢。我看这/sbin/reboot似乎是 的链接/bin/systemctl。但是它并不像“简单”链接那样运行,因为调用/bin/systemctl和 不一样/sbin/reboot

此外,虽然/bin/systemctl确实有一个reboot选项,但/sbin/reboot似乎并不是的简单别名/bin/systemctl reboot,因为例如reboot --help打印无法通过/bin/systemctl reboot --help(或/bin/systemctl --help reboot)获得的特定帮助。

那么这个链接是什么以及如何查看它的定义?

答案1

好问题,我发现回答, 由...提供@slm ♦,关于 Unix 和 Linux 的问答:

许多程序都使用了这种技术,其中有一个可执行文件,它会根据执行方式改变其行为。

程序内部通常有一个称为 case/switch 语句的结构,该结构确定调用可执行文件的名称,然后调用该可执行文件名称的相应功能。该名称通常是程序接收的第一个参数。

看一看例子...

虽然原始答案提供了两个使用 C 和 Perl 的示例,但这里是一个使用 Bash 的示例。在 Bash 中,位置参数$0包含要执行的脚本的名称。因此,让我们创建一个名为的简单脚本program.sh并使其可执行:

cat << EOF > program.sh && chmod +x program.sh
#!/bin/bash
echo "I was called as \"\${0##*/}\""
EOF
  • \$将在脚本创建过程中逃避$within的特殊含义。cat

  • ${0##*/}脚本执行时将只输出可执行文件的名称,而不输出路径。

接下来让我们创建该脚本的三个符号链接:

for link in call-{1..3}; do ln -s program.sh $link; done

现在,根据我们调用的方式program.sh(直接调用或者通过我们创建的任何符号链接调用),输出将会有所不同:

$ ./program.sh 
I was called as "program.sh"

$ ./call-1 
I was called as "call-1"

$ ./call-2
I was called as "call-2"

$ ./call-3
I was called as "call-3"

答案2

作为pa4080说,这只是一个正常的符号链接, 和systemctl本身就是检查它以什么名称运行,以便决定执行什么操作。这种事情可以通过任何导致同一可执行文件以多个名称运行的机制来实现;实际上,它是通过使用符号链接或者硬链接. 在 GNU/Linux 系统(例如 Ubuntu)上,最常见的是使用符号链接来实现此目的。

在 Ubuntu 版本中systemd(目前包括所有支持的发布除了14.04 LTS,使用暴发户),不仅仅是命令reboot,还有haltpoweroffrunlevelshutdown, 和telinit命令都是指向的符号链接/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

根据您运行它时使用的名称执行的精确操作systemctl,以及您可以指定这些操作的其他方式,将在这个优秀的答案经过杰德BP这些用于关闭 Linux 服务器的命令有什么区别?Unix操作系统. 正如它所解释的,这些命令(除了)作为命令runlevel的简写,被不同的目标所取代。systemctl isolate ......

如果你感兴趣的话,C 代码会考虑你调用哪个名字systemctl来决定执行什么操作,它parse_argv位于systemctl.c,当前从该文件的第 6972 行开始。要找到它,您可以搜索:

static int parse_argv(int argc, char *argv[]) {

相关部分涵盖了该函数的大部分内容,但所有部分都大致类似于它的这个片段,继续类似但每个字符串都有不同的代码,并且还有一些其他检查和分支逻辑:

                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")) {

其他检查命令如何被调用以(有时)采取不同行动的示例包括vim,其在作为vim、、、、、和其他几个运行时表现不同;exviewgvimgviewip, 看这个问题gksu, 看那个问题less, 哪个如果命名则改变外观more(但仍然允许双向滚动,与 Ubuntu 的more(英文):busybox;而且大多数伯恩风格的贝壳, 例如bashzsh,其行为自动更兼容POSIX 要求sh如果运行为sh

相关内容