为什么/ bin / sh与/ bin / bash的行为不同,即使指向另一个也是如此?
当我在shell中调查这个问题的答案时,我注意到,即使/bin/sh
在我的系统上指向了/bin/bash
,这两个命令的行为也不一样。 首先,输出
ls -lh /bin/sh
是:
lrwxrwxrwx 1 root root 4 Apr 22 2013 /bin/sh -> bash*
但是,通过/bin/sh
调用以下命令:
/bin/sh -c "script.sh 2> >( grep -v FILTER 2>&1 )"
返回这个错误:
/bin/sh: -c: line 0: syntax error near unexpected token '>' /bin/sh: -c: line 0: 'script.sh 2> >( grep -v FILTER 2>&1 )'
当通过/bin/bash
运行相同的命令时:
/bin/bash -c "script.sh 2> >( grep -v FILTER 2>&1 )"
执行成功,这里是输出:
This should be on stderr
作为参考,这里是script.sh
的内容:
#!/bin/sh echo "FILTER: This should be filtered out" 1>&2 echo "This should be on stderr" 1>&2 echo "FILTER: This should be filtered out" 1>&2
为什么这两个调用行为有所不同?
bash
查看$argv[0]
的值(bash在C中实现)以确定它是如何被调用的。
其手动调用时的行为logging在手册中 :
如果以名称
sh
调用Bash,它将尽可能地模仿历史版本sh
的启动行为,同时也符合POSIX标准。当作为交互式loginshell或具有
-login
选项的非交互式shell进行调用时,它将首先尝试从/etc/profile
和~/.profile
中按顺序读取和执行命令。--noprofile
选项可以用来抑制这种行为。 当以名称sh
作为交互式shell进行调用时,Bash将查找variablesENV
,如果已定义,则展开其值,并使用展开的值作为要读取和执行的文件的名称。 由于作为sh
调用的shell不会尝试从任何其他启动文件读取和执行命令,因此--rcfile
选项不起作用。 使用名称sh
调用的非交互式shell不会尝试读取任何其他启动文件。当以
sh
调用时,Bash在读取启动文件后进入POSIX模式
当bash
处于POSIX模式时,有一长串的列表(当前有46个条目), 这里logging 。
(POSIX模式可能主要用作testing脚本以便移植到非bash
shell的方式。)
顺便提一下,根据调用它们的名称来改变其行为的程序是相当普遍的。 一些版本的grep
, fgrep
和egrep
被实现为一个单一的可执行文件(尽pipeGNU grep
不这样做)。 view
通常是vi
或vim
的象征性链接; 调用它作为view
原因以只读模式打开。 Busybox系统包含许多单独的命令,这些命令都是与主busybox
可执行文件的符号链接。
调用bash作为sh
会导致它在读取它通常会读取的启动文件后进入posix模式 (而不是POSIX sh将读取的启动文件)。Bash有许多不同的调用模式。 您可以从手册的“ INVOCATION
部分了解这些模式。 这里是关于POSIX模式的一些细节。
POSIX模式
这种模式意味着bash将在不同程度上尝试符合POSIX的期望。 正如这里所解释的那样,bash对这种模式有几个不同的调用,具有稍微不同的含义:
-
sh
:Bash在读取启动文件后进入POSIX模式。 -
bash --posix
:Bash 在读取启动文件之前进入POSIX模式。 -
set -o posix
:Bash切换到POSIX模式。 -
POSIXLY_CORRECT
:如果这个variables在bash启动时在环境中,shell 在读取启动文件之前进入posix模式,比如bash --posix
。 如果它在bash运行的时候被设置,像set -o posix
。
从Bash参考手册 :
如果Bash是以sh的名字被调用的,它会尽可能地模仿sh历史版本的启动行为,同时也符合POSIX标准。
因为bash
二进制文件检查它是如何被调用的(通过argv[0]
),如果以sh
的forms运行,则进入兼容模式。