当sh是bash或破折号的符号链接时,bash会将其自身限制为POSIX兼容,因此它应该与sh 100%兼容吗?


8

bash和sh之间的区别

ABck的问题:如果你有/bin/sh一个链接的bash,那么bash将不会调用时为具有相同的行为/bin/sh,因为它不会在调用时/bin/bash。当称为时sh,它将限制自己为大多数POSIX兼容以及一组有限的扩展。

这是否意味着每当我在Linux中遇到带有shebang的shell脚本时#!/bin/sh,即使在该发行版上,它bin/sh都是到另一个shell(例如破折号或bash)的符号链接,它应该与bourne shell 100%兼容,因为是否将自身限制为一组有限的扩展名?这样我可以在FreeBSD中执行它们吗?有例外吗?还是我应该确定它会起作用?

因此,如果在发行版上bin/sh是的符号链接bin/bash,并且使用了脚本#!/bin/sh并且该脚本包含bashism,则该脚本将不会运行,因为bash会喜欢处于sh模式?

Answers:


16

不,如果/bin/sh是bash的符号链接,bash只能进入posix模式-来自man bash

当作为sh调用时,bash在读取启动文件后进入posix模式。

如果现在在bash联机帮助页上搜索posix模式,您会看到一些内置的shell就像timesource表现不同。就这些。像function在声明函数之前编写代码或使用source代替的bashishms .仍然可以工作,但是命令的行为可能有所不同。

因此,如果/bin/sh/bin/bash所有典型bashishms 的符号链接仍然有效。

有关Posix模式中差异的详细列表,请参阅bash参考手册


因此,我认为最好的方法是测试checkbashism工具中的所有脚本。我听说有些发行版,例如Debian和Ubuntu(需要对此进行确认)现在将bin / sh符号链接到破折号。破折号与bourn shell兼容吗?如果是的话,那么在FreeBSD下至少所有Debian和Ubuntu shell脚本都应该可以。
user1115057'8

@ user1115057仅/bin/sh作为shebang的shell脚本。Shell脚本仍然可以显式使用/bin/bash。无论如何,大多数shell脚本可能都可以在/ bin / sh下正常运行,但是问题出在用户工具上,例如,大多数shell脚本期望GNU用户态,这可能不仅仅是一个语法错误,而是更多的问题。我还向bash参考添加了一个链接,该链接列出了posix模式下的不同行为
Ulrich Dangel 2012年

好吧,根据我的阅读,BSD使用ash作为bin / sh,而Debian和Ubuntu使用破折号。如果这些shell兼容,则意味着shebang#!/ bin / sh将不再有问题。但是,正如您所说,还会有其他与userland相关的问题...
user1115057

@ user1115057破折号也不是完美的,例如wiki.ubuntu.com/DashAsBinSh/#echo不管怎么说,大多数shell脚本都很简单,可以很容易地移植……祝您好运
Ulrich Dangel 2012年

但是破折号和灰烬兼容吗?
user1115057'8

8

伯恩贝壳周围似乎有些混乱。Bourne外壳是几十年前的POSIX之前的Unix外壳。如今,“ sh”是实现POSIX规范的shell的一种实现或另一种实现,其中包括bash,pdksh,AT&T ksh,较新的Almquist shell及其派生类,这些壳已使其与POSIX兼容(包括某些BSD的“ sh”) ,其他BSD则基于pdksh和Debian ash(破折号)。甚至zsh都具有与POSIX一致的模式。

Bourne shell不兼容POSIX,并且如今在许多系统上都找不到。在找到或未找到Bourne shell的地方,总会有一个“ POS”(与POSIX兼容)(并且不是Bourne Shell),通常在/binSolaris中是一个(令人讨厌的)例外。

请注意,在伯恩(Bourne)外壳(以及我们30多年前)之前,“ sh”是汤普森(Thompson)外壳。我们不再编写与Thompson Shell兼容的脚本。同样,我们应该停止将“ sh”视为伯恩壳。

现在,“ sh”是一个规范,实现中有时并不兼容。这使得编写可移植脚本变得容易得多。只需遵循规格即可

适用于“ sh”和所有标准实用程序(sed,cut,tr ...)


+1表示“写入规范”。但是可悲的是,这通常不足以实现可移植性。例如,如果要在sed中使用egrep样式的模式怎么办?规范没有为此提供。在具有基于Gnu的实用程序(或BusyBox)的系统上,请使用sed -r。在具有基于BSD的实用程序的系统上,请使用sed -E。FreeBSD的sed都接受,但是Mac OS X的仅接受-E。等等等等。
dubiousjim 2012年

那不是重点。该规范未提供它,因此您不能便携式/ POSIXly使用它。如果使用BRE,它将在所有符合POSIX的系统上运行,这是POSIX提供的保证,因此很有用。正如您所说,在POSIX之外没有希望,因为seds不支持ERE或使用其他选项或不同的ERE语法支持它。请注意,ERE的功能不如BRE(只有在ERE中扩展了语法才能为您节省键入内容。ERE可以翻译为BRE,事实并非如此(BRE \(...\)\1在标准ERE中没有翻译)。)
StéphaneChazelas

1
我意识到(POSIX)ERE缺少反向引用;实际上,我参与了该标准的这一部分的编辑。POSIX ERE的功能严格小于BRE是不正确的,因为在当前标准中,没有为BRE定义替代。但是,我不知道任何不\|适合BRE的正则表达式引擎。我全力以赴以尽可能地便携。我只是做出(我认为得到广泛认可的)观察结果,这可能很痛苦,并且有时根本不可能写POSIX。某个地方的链接表现出很多这样的变态。会寻找他们。
dubiousjim 2012年

关于轮换的好点,我忘记了,并保持纠正。使用sed,虽然您可以使用多个表达式来匹配备用正则表达式,但不太可能被阻塞。如果需要ERE,可以在标准工具箱中使用awk。我很少能用标准的工具找到自己,而当我这样做时,通常情况下,诸如perl之类的另一种语言更合适,但我确实明白了你的意思(尽管我仍然认为这与编写可移植脚本无关)
斯特凡Chazelas

我想到的一个例子:POSIX中未指定shebang行(在每个shell脚本的顶部)。另外,我不确定我是否曾经使用过100%兼容POSIX的系统。例如,POSIX说您可以在其中包含换行符,${VAR:=stuff...here}但是许多shell不允许您这样做,您必须在引号周围加上引号stuff...here
dubiousjim 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.