当我像这样运行 Centos 7 Docker 镜像时
docker run -it centos:7 bash
运行一些正在使用的东西流程替代没问题(正如预期的那样,Bash 从一开始就支持进程替换 - 实际上是 Bash 1.4.x)。
例如:
while IFS= read -r test; do echo $test; done < <(cat anaconda-post.log)
但是当我切换到/bin/sh相同的代码不再起作用
/bin/sh
while IFS= read -r test; do echo $test; done < <(cat anaconda-post.log)
sh: syntax error near unexpected token `<'
虽然/bin/sh似乎是巴什
/bin/sh --version
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
但为什么流程替代不再有效呢?不过,其他非 POSIX 功能似乎也可以工作
echo ${PATH//:/ }
/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin
答案1
是的,bash
当被称为 时sh
,会在 POSIX 模式下运行,禁用所有仅适用于 bash 的功能。从手册中 -使用名称 sh 调用
如果使用 sh 名称调用 Bash,它会尝试尽可能模仿 sh 历史版本的启动行为,同时也符合 POSIX 标准
$ ls -lrth /bin/sh
lrwxrwxrwx. 1 root root 4 Aug 26 2018 /bin/sh -> bash
$ /bin/bash -c 'set -o | grep posix'
posix off
$ /bin/sh -c 'set -o | grep posix'
posix on
启用posix
模式后,将不会启用进程替换等非标准功能。看Bash POSIX 模式查看其在该模式下运行的完整行为。
从 shell 版本 5.1 开始,可以在 POSIX 模式下进行进程替换。
答案2
某些选项在 bash 的 POSIX 模式下被禁用。当bash
被称为 as时,它会被激活sh
。从 bash 手册页:
当作为 sh 调用时,bash 在读取启动文件后进入 posix 模式。
因此,对于当前版本(您正在使用现在已删除的自我答案中的 4.2),即使bash
称为 as ,过程替换也可以工作sh
。
答案3
什么是/bin/sh
?我们正在谈论Unix 遗产这里!一些历史:
sh
是 Bourne Shell,它于 1979 年在 Unix 版本 7 中发布。它因 Brian Kernighan 和 Rob Pike 出版的《Unix 编程环境》而广受欢迎,这是第一本商业出版的书籍,介绍了 Unix 编程环境。壳作为教程形式的编程语言。
ksh
Korn shell 最初由 David Korn 编写,基于原始的 Bourne Shell 源代码,是 Bourne shell 和csh
C shell 之间的中间道路。它的语法主要取自 Bourne shell,而其作业控制功能类似于 C shell。原始 Korn Shell 的功能被用作 POSIX shell 标准的基础。
bash
是“Bourne Again SHell”。 Bash 语法是 Bourne shell 语法的超集。 Bash 语法包括从 Korn Shell 和 C shell 汲取的思想,例如命令行编辑、命令history
、目录堆栈、$RANDOM 和 $PPID 变量以及 POSIX 命令替换语法 $(...)。
dash
是“Debian Almquist shell”。它的首要任务是 POSIX 兼容性。
使用 bash 或 dash 的硬链接将sh
其行为限制为 POSIX 标准。
答案4
另外一点 - 在 Centos 7 上,sh
是bash
.没有单独的二进制文件sh
。
[root@work ~]# ls -la `which sh`
lrwxrwxrwx. 1 root root 4 Jun 16 2020 /usr/bin/sh -> bash
[root@work ~]# ls -la /bin/sh
lrwxrwxrwx. 1 root root 4 Jun 16 2020 /bin/sh -> bash
[root@work ~]# rpm -qf /usr/bin/sh /bin/sh
bash-4.2.46-34.el7.x86_64
bash
、dash
和busybox
可能的其他 shell 可以检查它们启动时使用的命令行,并且会假装成其他东西,比如普通的(sh
如果它们是这样调用的)。这个符号链接可以实现这一点。
你总是可以期待/bin/sh
在那里,并且成为一个基本的外壳。