为什么/ bin/sh与/ bin/bash的行为不同,即使一个指向另一个?

Squ*_*rel 64 linux bash shell sh

当我在我的shell中调查这个问题的答案时,我注意到,即使/bin/sh指向/bin/bash我的系统,这两个命令的行为也不同.首先,输出

ls -lh /bin/sh
Run Code Online (Sandbox Code Playgroud)

是:

lrwxrwxrwx 1 root root 4 Apr 22  2013 /bin/sh -> bash*
Run Code Online (Sandbox Code Playgroud)

但是,通过以下方式调用以下命令/bin/sh:

/bin/sh -c "script.sh 2> >( grep -v FILTER 2>&1 )"
Run Code Online (Sandbox Code Playgroud)

返回此错误:

/bin/sh: -c: line 0: syntax error near unexpected token '>'
/bin/sh: -c: line 0: 'script.sh 2> >( grep -v FILTER 2>&1 )'
Run Code Online (Sandbox Code Playgroud)

通过/bin/bash以下命令运行相同的命令:

/bin/bash -c "script.sh 2> >( grep -v FILTER 2>&1 )"
Run Code Online (Sandbox Code Playgroud)

执行成功,这是输出:

This should be on stderr
Run Code Online (Sandbox Code Playgroud)

供参考,以下是以下内容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
Run Code Online (Sandbox Code Playgroud)

为什么两个调用的行为不同?

Kei*_*son 79

bash查看$argv[0](bash在C中实现)的值以确定它是如何被调用的.

其行为时援引为sh被记录在手册中:

如果使用名称调用Bash sh,它会尽可能地模仿历史版本的启动行为sh,同时也符合POSIX标准.

当作为交互式登录shell或具有该-login选项的非交互式shell调用时,它首先尝试以该顺序从/etc/profile和读取和执行命令~/.profile.该 --noprofile选项可用于抑制此行为.当作为具有名称的交互式shell调用时sh,Bash查找变量 ENV,如果已定义则展开其值,并使用展开的值作为要读取和执行的文件的名称.由于调用的shell sh 不会尝试从任何其他启动文件读取和执行命令,因此该--rcfile选项无效.使用该名称调用的非交互式shell sh不会尝试读取任何其他启动文件.

调用时sh,Bash在读取启动文件后进入POSIX模式

有一个很长的列表(目前有46个项目)bash在POSIX模式下会发生变化,在此处记录.

(POSIX模式可能主要用作测试脚本以便可移植到非bashshell的方法.)

顺便提一下,根据调用它们的名称改变其行为的程序是相当普遍的.某些版本的grep,, fgrepegrep实现为单个可执行文件(尽管GNU grep不这样做).view通常是vi或的象征性链接vim; 调用它作为view以只读模式打开的原因.所述Busybox的系统包括许多与所有符号链接到主各个命令的busybox可执行文件.

  • 这也是busybox工具确定要做什么的方式.在内部查看$ argv [0]是一种很好的方法,可以使一个二进制表现为几个单独的工具. (9认同)
  • @ pierce.jason:在某些实现中,`grep`,`fgrep`和`egrep`以这种方式工作.(我刚刚发现GNU grep没有这样做;它们是三个独立的可执行文件.)同样,`view`通常与`vi`或`vim`是相同的可执行文件.将它作为`view`调用相当于使用`-R`(readonly)选项. (4认同)
  • `view通常是vi或vim的符号链接.在许多系统中,vi实际上是在vi兼容模式下运行的vim. (3认同)

koj*_*iro 20

调用bash sh会导致它在读取通常读取的启动文件后进入posix模式(与POSIX sh读取的启动文件相反).Bash有许多不同的调用模式.您可以从INVOCATION手册部分了解这些模式.以下是有关POSIX模式的一些细节.

POSIX模式

这种模式意味着bash将在不同程度上尝试符合POSIX期望.正如这里所解释的那样,bash对这种模式有几种不同的调用,其含义略有不同:

  1. sh:Bash在读取启动文件后进入POSIX模式.
  2. bash --posix:Bash 读取启动文件之前进入POSIX模式.
  3. set -o posix:Bash切换到POSIX模式.
  4. POSIXLY_CORRECT:如果此变量在bash启动时处于环境中,则shell会读取启动文件之前进入posix模式,例如bash --posix.如果在bash运行时设置,就像set -o posix.


Eta*_*ner 16

Bash参考手册:

如果使用名称sh调用Bash,它会尝试尽可能接近地模仿sh的历史版本的启动行为,同时也符合POSIX标准.


Car*_*rum 10

因为bash二进制文件检查它是如何被调用的(通过argv[0])并且如果它被运行则进入兼容模式sh.