为什么这个软链接不能按预期工作?

为什么这个软链接不能按预期工作?
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#

原因何在?

答案1

这是一个有记录的特征。

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

man bash

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

程序如何知道使用什么名称来启动它?

如果是 c 程序,它可以检查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

相关内容