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

xml*_*lmx 11 linux fedora bash shell sh

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#
Run Code Online (Sandbox Code Playgroud)

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

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

因此,据我所知,type bash and press enter应该产生与type sh and press enter.

当 I 时type bash and press enter,我得到[root@localhost bin]#了预期的结果。

但是,如果我type sh and press enter,我出人意料地得到sh-4.3#

原因是什么?

Joh*_*024 25

这是一个记录在案的功能。

如果您通过名为 的符号链接运行 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 模式。

程序如何知道启动它的名称是什么?

如果是ac程序,可以检查argv[0]。如果是 shell 或 perl 脚本,它可以检查$0.

例如,让我们考虑这个简单的 shell 脚本:

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

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

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

ln -s utc et
Run Code Online (Sandbox Code Playgroud)

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

$ utc
Wed Jul 20 18:14:18 UTC 2016
$ et
Wed Jul 20 14:14:20 EDT 2016
Run Code Online (Sandbox Code Playgroud)

  • 可能想要添加这是如何可能的,因为 OP 期望调用是相同的。(`argv[0]`, obvs) (4认同)