为什么此软链接无法按预期工作?


11
bash4.3 # pwd
/bin
bash4.3 # ll sh
lrwxrwxrwx. 1   root    root    4   May 17 22:22 sh -> bash
bash4.3 # ll bash
-rwxr-xr-x. 1   root    root    1072056 May 17 22:22 bash
bash4.3 # bash
bash4.3 # sh
sh-4.3#

我的操作系统是fedora 24(默认GNOME版本)。

从示例中我们可以知道:在之下/binbash是一个二进制可执行文件;在之下,是一个二进制可执行文件。sh是的软链接bash

因此,据我所知,type bash and press enter应产生与完全相同的结果type sh and press enter

当我type bash and press enter得到我的[root@localhost bin]#期望时。

但是,如果我愿意type sh and press enter,我会惊讶地得到sh-4.3#

是什么原因


可以很容易地复制粘贴到SE编辑器中的文本作为图像非常烦人,因此请不要这样做。而是在终端中选择文本,然后按CTRL-SHIFT-C。

Answers:


25

这是一个已记录的功能。

如果您通过名为的符号链接运行bash sh,bash将以sh兼容模式启动。

来自man bash

如果使用名称sh调用bash,则它会尝试尽可能接近于sh的历史版本的启动行为,同时也要符合POSIX标准。当作为交互式登录外壳程序或带有--login选项的非交互式外壳程序调用时,它首先尝试按该顺序从/ etc / profile和〜/ .profile中读取和执行命令。--noprofile选项可用于禁止此行为。当bash作为名称为sh的交互式shell调用时,bash查找变量ENV,如果定义了变量,则扩展其值,并将扩展后的值用作要读取和执行的文件的名称。由于以sh调用的shell不会尝试从任何其他启动文件读取和执行命令,因此--rcfile选项无效。使用名称sh调用的非交互式外壳程序不会尝试读取任何其他启动文件。当作为sh调用时,bash在读取启动文件后进入posix模式。

程序如何知道用来启动它的名称?

如果是交流程序,则可以检查argv[0]。如果它是Shell或Perl脚本,则可以检查$0

作为示例,让我们考虑以下简单的shell脚本:

$ cat utc
#!/bin/sh
case "${0##*/}" in
        utc) date -u ;;
        et) TZ=US/Eastern date ;;
esac

$0是调用脚本的名称。 ${0##*/}是已删除任何目录名称的脚本调用名称。

让我们创建这个符号链接:

ln -s utc et

所以,utcet这两种运行相同的可执行文件,但它们提供了不同的结果。当以方式运行时utc,它输出通用时间。当运行et为时,输出美国东部时间。例如:

$ utc
Wed Jul 20 18:14:18 UTC 2016
$ et
Wed Jul 20 14:14:20 EDT 2016

4
可能想补充一下如何做到这一点,因为OP希望调用是相同的。(argv[0],obvs)
绕行轨道赛

@LightnessRacesinOrbit好主意。我加了一个例子。
John1024 '16

现在完美。:)
轻轨赛将于
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.