为何符号链接的/bin/sh仍呈现与bash不同的解释器行为?
为什么/bin/sh指向bash但脚本行为不同?
核心原因在于bash会根据启动时的调用名称切换运行模式:
- 当通过
bash(或实际路径/bin/bash)启动时,bash运行在完整特性模式,支持所有独有的扩展语法(比如进程替换<())。 - 当通过
sh(哪怕是指向bash的符号链接)启动时,bash会自动切换到POSIX兼容模式,禁用绝大多数bash扩展特性,仅遵循POSIX标准的shell规范。
实例验证
1. 使用#!/bin/bash的脚本
#!/bin/bash echo ${BASH_VERSION} diff <(echo -e "1\n2") <(echo -e "2\n2")
执行结果:
4.2.46(2)-release 1c1 < 1 --- > 2
此时bash以完整模式运行,支持进程替换特性,脚本正常执行。
2. 使用#!/bin/sh的脚本
#!/bin/sh echo ${BASH_VERSION} diff <(echo -e "1\n2") <(echo -e "2\n2")
执行结果:
4.2.46(2)-release test.sh: line 3: syntax error near unexpected token `(' test.sh: line 3: `diff <(echo -e "1\n2") <(echo -e "2\n2")'
bash以sh名称启动,进入POSIX兼容模式,进程替换属于bash扩展特性被禁用,因此触发语法错误。
关于realpath /bin/sh test.sh能正常运行的原因
realpath /bin/sh会解析符号链接,输出bash的实际路径/bin/bash,这相当于直接用/bin/bash test.sh启动脚本,bash以完整特性模式运行,自然支持进程替换。
为什么BASH_VERSION始终一致?
即使在POSIX兼容模式下,运行的进程本质还是bash,所以BASH_VERSION会显示bash的真实版本号,但这并不代表它启用了所有bash扩展特性。
内容的提问来源于stack exchange,提问作者Aviram Tal
相关产品推荐
相关产品推荐

