为什么 /bin/sh 的行为与 /bin/bash 不同,即使一个指向另一个?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26717870/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does /bin/sh behave differently to /bin/bash even if one points to the other?
提问by Squirrel
While I was playing around in my shell investigating the answer to this question, I noticed that, even though /bin/sh
was pointing to /bin/bash
on my system, the two commands behave differently. First of all, the output of
当我在 shell 中研究这个问题的答案时,我注意到,即使/bin/sh
指向/bin/bash
我的系统,这两个命令的行为也不同。首先,输出
ls -lh /bin/sh
is:
是:
lrwxrwxrwx 1 root root 4 Apr 22 2013 /bin/sh -> bash*
However, invoking the following command through /bin/sh
:
但是,通过调用以下命令/bin/sh
:
/bin/sh -c "script.sh 2> >( grep -v FILTER 2>&1 )"
returns this error:
返回此错误:
/bin/sh: -c: line 0: syntax error near unexpected token '>'
/bin/sh: -c: line 0: 'script.sh 2> >( grep -v FILTER 2>&1 )'
While running the same command through /bin/bash
:
通过/bin/bash
以下方式运行相同的命令时:
/bin/bash -c "script.sh 2> >( grep -v FILTER 2>&1 )"
executes successfully, here is the output:
执行成功,输出如下:
This should be on stderr
For reference, here is the contents of script.sh
:
供参考,以下是内容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
Why do the two invocations behave differently?
为什么这两个调用的行为不同?
回答by Keith Thompson
bash
looks at the value of $argv[0]
(bash is implemented in C) to determine how it was invoked.
bash
查看$argv[0]
(bash 在 C 中实现)的值以确定它是如何被调用的。
Its behavior when invoked as sh
is documented in the manual:
当作为调用它的行为sh
被记录在手册中:
If Bash is invoked with the name
sh
, it tries to mimic the startup behavior of historical versions ofsh
as closely as possible, while conforming to the POSIX standard as well.When invoked as an interactive login shell, or as a non-interactive shell with the
-login
option, it first attempts to read and execute commands from/etc/profile
and~/.profile
, in that order. The--noprofile
option may be used to inhibit this behavior. When invoked as an interactive shell with the namesh
, Bash looks for the variableENV
, expands its value if it is defined, and uses the expanded value as the name of a file to read and execute. Since a shell invoked assh
does not attempt to read and execute commands from any other startup files, the--rcfile
option has no effect. A non-interactive shell invoked with the namesh
does not attempt to read any other startup files.When invoked as
sh
, Bash enters POSIX mode after the startup files are read
如果使用名称调用 Bash
sh
,它会尝试尽可能模仿历史版本的启动行为sh
,同时也符合 POSIX 标准。当作为交互式登录 shell 或作为带有
-login
选项的非交互式 shell 调用时,它首先尝试从/etc/profile
和 中读取和执行命令~/.profile
,按照该顺序。该--noprofile
选项可用于禁止此行为。当作为具有 name 的交互式 shell 调用时sh
,Bash 查找变量ENV
,如果定义了则扩展它的值,并使用扩展的值作为要读取和执行的文件的名称。由于调用 as 的 shellsh
不会尝试从任何其他启动文件读取和执行命令,因此该--rcfile
选项无效。使用该名称调用的非交互式 shellsh
不会尝试读取任何其他启动文件。调用 as 时
sh
,Bash 在读取启动文件后进入 POSIX 模式
There's a long list (currently 46 items) of things that change when bash
is in POSIX mode, documented here.
有很长的列表(目前有 46 项)bash
在 POSIX 模式下会发生变化,记录在这里。
(POSIX mode is probably useful mostly as a way to test scripts for portability to non-bash
shells.)
(POSIX 模式可能主要用作测试脚本对非bash
shell 的可移植性的一种方式。)
Incidentally, programs that change their behavior depending on the name under which they were invoked are fairly common. Some versions of grep
, fgrep
, and egrep
are implemented as a single executable (though GNU grep
doesn't do this). view
is typically a symbolic link to vi
or vim
; invoking it as view
causes to open in read-only mode. The Busyboxsystem includes a number of individual commands that are all symlinks to the master busybox
executable.
顺便说一下,根据调用它们的名称来改变其行为的程序是相当普遍的。有些版本grep
,fgrep
以及egrep
作为一个可执行实现(虽然GNUgrep
并没有这样做)。view
通常是指向vi
或的符号链接vim
;调用它view
会导致以只读模式打开。所述Busybox的系统包括许多与所有符号链接到主各个命令的busybox
可执行文件。
回答by kojiro
Invoking bash as sh
causes it to enter posix modeafter reading the startup files it would normally read (as opposed to the startup files a POSIX sh would read.) Bash has many different invocation modes. You can find out about these modes from the INVOCATION
section of the manual. Here is some detail about the POSIX mode.
调用 bash assh
会导致它在读取它通常读取的启动文件后进入posix 模式(与 POSIX sh 将读取的启动文件相反)。Bash 有许多不同的调用模式。您可以从INVOCATION
手册部分了解这些模式。以下是有关 POSIX 模式的一些详细信息。
POSIX mode
POSIX 模式
This mode means bash will try, in various degrees, to conform to POSIX expectations. As explained here, bash has a few different invocations for this mode, with slightly different implications:
这种模式意味着 bash 将在不同程度上尝试符合 POSIX 的期望。正如此处所解释的,bash 对此模式有一些不同的调用,其含义略有不同:
sh
: Bash enters POSIX mode after reading startup files.bash --posix
: Bash enters POSIX mode beforereading startup files.set -o posix
: Bash switches to POSIX mode.POSIXLY_CORRECT
: If this variable is in the environment when bash starts, the shell enters posix mode beforereading the startup files, likebash --posix
. If it is set while bash is running, likeset -o posix
.
sh
: Bash 读取启动文件后进入 POSIX 模式。bash --posix
: Bash在读取启动文件之前进入 POSIX 模式。set -o posix
: Bash 切换到 POSIX 模式。POSIXLY_CORRECT
: 如果bash启动时环境中有这个变量,shell在读取启动文件之前进入posix模式,比如bash --posix
. 如果它是在 bash 运行时设置的,比如set -o posix
.
回答by Etan Reisner
From the Bash Reference Manual:
来自Bash 参考手册:
If Bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well.
如果使用名称 sh 调用 Bash,它会尝试尽可能模仿 sh 历史版本的启动行为,同时也符合 POSIX 标准。
回答by Carl Norum
Because the bash
binary checks how it was invoked (via argv[0]
) and enters a compatibility mode if it's being run as sh
.
因为bash
二进制文件会检查它是如何被调用的(通过argv[0]
),如果它作为sh
.