我已经看到了通常在引用shell时使用的“ shcompatible”一词。我不确定它是否也适用于可能在Shell中运行的程序。
Shell或其他程序“与sh兼容”是什么意思?“ sh不兼容”是什么意思?
编辑:这个问题问bash和sh之间的区别非常相关: sh和bash之间的区别
我仍然想直接回答“与Windows兼容”的含义。一个合理的期望可能是“ sh兼容”的意思是“实现Shell命令语言”,但是为什么会有那么多的“ sh兼容” shell,又为什么又不同呢?
我已经看到了通常在引用shell时使用的“ shcompatible”一词。我不确定它是否也适用于可能在Shell中运行的程序。
Shell或其他程序“与sh兼容”是什么意思?“ sh不兼容”是什么意思?
编辑:这个问题问bash和sh之间的区别非常相关: sh和bash之间的区别
我仍然想直接回答“与Windows兼容”的含义。一个合理的期望可能是“ sh兼容”的意思是“实现Shell命令语言”,但是为什么会有那么多的“ sh兼容” shell,又为什么又不同呢?
Answers:
为什么有那么多“ sh兼容” shell?
在Bourne shell的首次公开于1979年发布了作为一部分的Unix V7。由于几乎每个Unix和类似Unix的系统都是从V7 Unix派生而来的 -即使只是在精神上也如此-Bourne外壳对我们来说是“永远的”。¹
Bourne shell实际上取代了Thompson shell的早期外壳,但是它在Unix历史上就这么早发生,以至于今天几乎被人们遗忘了。Bourne外壳是Thompson外壳的超集。²
伯恩(Bourne)和汤普森(Thompson)弹都被称为sh
。POSIX指定的外壳也称为sh
。因此,当有人说sh
-compatible时,他们是在手工提及这个系列的shell。如果要具体说明,可以说“ POSIX shell”或“ Bourne shell”。³
POSIX的壳是基于1988年版本的KornShell,而这又是为了更换伯恩上AT&T的Unix外壳,跨越式的BSD C外壳程序中features.⁴在一定程度上的术语,其ksh
是POSIX壳的祖先,最Unix和类似Unix的系统包括今天的Korn shell的某些变体。通常,例外情况是微型嵌入式系统,它们无法承受完整的POSIX shell占用的空间。
就是说,Korn Shell(与POSIX Shell有所不同)从未真正在商业Unix世界之外流行。这是因为它的兴起与Unix商业化的早期相对应,因此它陷入了Unix战争。BSD Unixes避开了它,转而使用C shell,并且它的源代码在启动时就无法在Linux中免费使用。⁵因此,当早期的Linux发行商开始寻找与Linux内核一起使用的命令shell时,他们通常选择GNU Bash,这是sh
您正在谈论的兼容产品之一。⁶
Linux和击之间,早期的关联几乎密封的其他许多炮弹,包括命运ksh
,csh
和tcsh
。如今仍有顽固分子使用这些弹药,但在少数人中却很。⁷
所有这些历史解释了为什么相对较晚的创建者喜欢bash
,zsh
并yash
选择使其sh
兼容:为什么Bourne / POSIX兼容性是类Unix系统要获得广泛采用所必须提供的最低外壳。
在许多系统中,默认的交互式命令外壳和/bin/sh
是不同的东西。/bin/sh
也许:
原始的伯恩贝壳。这在较早的UNIX®系统中很常见,例如Solaris 10(于2005年发行)及其前身。⁸
POSIX认证的外壳。这在较新的UNIX®系统中很常见,例如Solaris 11(2010)。
该Almquist外壳。这是最初于1989年在Usenet上发布的开源Bourne / POSIX shell克隆,然后被伯克利的CSRG贡献,使其包含在第一个不包含AT&T源代码4.4BSD-Lite的 BSD版本中。Almquist shell通常被称为ash
,即使安装为/bin/sh
。
4.4BSD-Lite继而成为所有现代BSD派生工具的基础,并且/bin/sh
在大多数情况下仍保留为Almquist派生工具,但以下是一个主要例外。您可以在NetBSD和FreeBSD的源代码存储库中看到这种直接下降的关系:它们从第一天开始就交付Almquist Shell衍生物。
ash
BSD世界之外有两个重要的分支:
dash
,在2006年被Debian和Ubuntu广泛采用为默认/bin/sh
实现。(Bash仍然是Debian衍生产品中的默认交互式命令外壳。)
BusyBox中的ash
命令,在嵌入式Linux中经常使用,可用于实现。由于晚于它,它是从Debian的老衍生包,我选择考虑它的衍生物,而不是,尽管内BusyBox的命令名。/bin/sh
dash
ash
dash
ash
(BusyBox的还包括一个不太多特征的替代ash
叫hush
。通常只有两个人会被内置到任何给定的BusyBox的二进制文件:ash
默认情况下,但是hush
,如果空间实在紧张。因此,/bin/sh
基于BusyBox的系统并不总是dash
。类似的)
GNU Bash,当称为时会禁用其大多数非POSIX扩展sh
。
除Debian及其衍生版本外,此选择通常在Linux的台式机和服务器版本上使用。自2003年发布Panther以来,Mac OS X也已做到这一点。
带有ksh93
POSIX扩展名的shell,例如OpenBSD。尽管OpenBSD Shell更改了行为以避免使用Bourne和POSIX Shell时语法和语义上的不兼容,当sh
它被称为时,它并不会禁用其任何纯扩展名,因为它们不会与旧版Shell发生冲突。
这是不常见的。您不应该期望中的ksh93
功能/bin/sh
。
我在上面使用“ shell脚本”作为通用术语,表示Bourne / POSIX shell脚本。这是由于伯恩家族的炮弹无处不在。要谈论其他shell上的脚本,您需要提供一个限定符,例如“ C shell脚本”。即使在C系列外壳为默认交互式外壳的系统上,最好使用Bourne外壳进行脚本编写。
它告诉我们,当Wikipedia对Unix Shell进行分类时,它们将它们分为Bourne Shell兼容,C Shell兼容和“其他”。
该图可能会有所帮助:
(单击以获取SVG版本31 kB,或查看完整尺寸的PNG版本 218 kB。)
“ sh不兼容”是什么意思?
谈论不sh
兼容的事物通常意味着以下三件事之一:
他们指的是那些“其他”外壳之一。
他们在Bourne和C shell系列之间进行区分。
他们谈论的是一个Bourne家族外壳中的某些特定功能,而不是所有其他Bourne家族外壳中的特定功能。ksh93
,bash
和zsh
,尤其是旧版“标准”外壳程序中不存在的许多功能。一旦您超出了共享的POSIX / ksh88
基础,这三者在许多方面也是相互不兼容的。
在shell脚本的顶部写上#!/bin/sh
shebang行,但在其中使用Bash或Korn shell扩展是一个经典的错误。由于这/bin/sh
是当今许多系统上上面的Korn / POSIX族图中的shell之一,因此此类脚本将在所编写的系统上工作,但随后/bin/sh
在更广泛的Bourne shell系列中起作用的系统上失败。最佳实践是使用#!/bin/bash
或#!/bin/ksh
扩展行(如果脚本使用此类扩展名)。
有很多方法可以检查给定的Bourne家族外壳脚本是否可移植:
checkbashisms
在Debian项目中运行该工具,该工具将检查脚本中的“ bashisms”。
posh
在Debian软件包库中的一个shell 下运行它,该shell有意仅实现SUS3指定的功能以及其他一些次要功能。
在Schily Tools项目中运行它osh
,该项目是Sun于2005年作为OpenSolaris的一部分开源的Bourne shell的改进版本,使其成为在现代计算机上获得1979年样式的Bourne shell的最简单方法之一。
Schily Tools发行版还包括bosh
POSIX类型的shell,具有许多非标准功能,但对于测试旨在在所有POSIX家族shell上运行的shell脚本的兼容性可能很有用。它往往是在其功能设置比更保守bash
,zsh
和的增强版本ksh93
。
Schily Tools还包含一个名为的外壳bsh
,但这是一个历史古怪的东西,根本不是Bourne家族的外壳。
仔细阅读GNU Autoconf手册中的“ 可移植外壳编程”一章。您可能会意识到它在脚本中讨论的一些有问题的构造。
他们为什么不同?
出于同样的原因,所有“新功能和改进功能!” 情况有所不同:
只能通过取消向后兼容性来改进改进的版本。
有人想到了一种更好的工作方式,这是他们更喜欢的,但是与旧的工作方式不同。
有人尝试在完全不了解旧标准的情况下重新实现旧标准,因此他们搞砸了,并造成了无意间的差异。
脚注和旁白:
BSD Unix的早期版本只是V6 Unix的附加软件集合。由于Bourne外壳直到V7才被添加到AT&T Unix中,因此BSD从技术上讲并没有Bourne外壳。BSD对Thompson shell原始特性的回答是C shell。
尽管如此,BSD的第一个独立版本(2.9BSD和3BSD)是基于V7或其可移植的后继UNIX / 32V的,因此它们确实包含了Bourne shell。
(该2BSD线变成BSD数字的的平行叉PDP小型机,而3BSD和4BSD线接着利用更新的计算机类型等的优点Vaxen和Unix工作站 2.9BSD基本上4.1cBSD的PDP版本; 他们同期,并共享代码。PDP的不只是消失在VAX到达,所以2BSD线仍然 步履蹒跚 一起。)
可以肯定地说,到1983年,Bourne外壳在Unix世界中无处不在。MS-DOS有一个分层文件系统,一年(噢,怎么cuuute!)和第24位的Macintosh及其9" B&W的屏幕-而不是灰度显示,从字面上黑色和白色 -不出来,直到年初明年。
从今天的标准来看,Thompson外壳非常原始。它只是一个交互式命令外壳,而不是我们今天期望的脚本编程环境。它确实具有诸如管道和I / O重定向之类的东西,我们通常将其视为“ Unix shell”的一部分,因此我们将MS-DOS命令shell视为从Unix获取它们。
伯恩壳也取代了PWB壳,它增加了重要的事情汤普森壳等可编程(if
,switch
和while
)和环境变量的早期形式。由于PWB shell不是Unix的每个版本的一部分,因此它的记忆力甚至不如Thompson shell。
当某人不确定 POSIX与Bourne外壳的兼容性时,可能会涉及很多方面。
在一个极端情况下,他们可能会使用1979年的Bourne贝壳作为基线。一个“ sh
兼容脚本”在这个意义上就意味着它有望在真正Bourne shell或任何其继承人和克隆的完美运行:ash
,bash
,ksh
,zsh
,等。
另一个极端是,有人以POSIX指定的外壳作为基准。如今,我们将POSIX shell的众多功能视为“标准”,以至于我们常常忘记它们实际上并没有出现在Bourne shell中:内置算术,作业控制,命令历史,别名,命令行编辑,$()
命令形式替代等
尽管Korn shell的历史可以追溯到1980年代初期,但AT&T直到1988 年System V Release 4才将它运用于Unix。由于有如此多的商业Unix基于SVR4,因此ksh
几乎将所有相关的商业Unix引入了该版本。从1980年代后期开始。
(基于SVR3的一些怪异的Unix风格在SVR4发行之后就一直占据着市场,但是当革命来临时,它们是第一个碰壁的。)
1988年也是第一个POSIX标准问世的一年,它的Korn外壳基于“ POSIX外壳”。后来,在1993年,出现了Korn shell的改进版本。由于POSIX有效地将原版钉牢,因此ksh
分叉成两个主要版本:ksh88
和ksh93
,以参与拆分的年份命名。
ksh88
尽管差异很小,但并不完全与POSIX兼容,因此某些ksh88
外壳程序版本已打补丁为与POSIX兼容。(这是在Slashdot上与David G. Korn博士进行的一次有趣的访谈。是的,是写壳的那个人。)
ksh93
是POSIX shell的完全兼容的超集。自从主要源代码存储库从AT&T 移至GitHub以来,其开发工作ksh93
一直是零星的,而在我撰写本文时,最新版本大约是3年以前,即ksh93v。(项目的基本名称保留有后缀,以表示1993年以后的发行版本。)ksh93
包含Korn外壳作为与POSIX外壳分开的对象的系统通常使它作为可用/bin/ksh
,尽管有时它隐藏在其他地方。
当谈及ksh
Korn shell的名称时,我们所谈论的ksh93
功能是将其与向后兼容的Bourne和POSIX shell子集区分开来。您很少遇到纯洁的ksh88
今天。
AT&T保留Korn shell源代码专有,直到2000年3月。到那时,Linux与GNU Bash的联系非常牢固。Bash和Bash ksh93
相互之间有优势,但是在这一点上,惯性使Linux与Bash紧密相关。
至于为什么早期的Linux厂商最常选择GNU猛砸了pdksh
,这是可以在Linux的起步的时候,我想这是因为有那么多的用户空间的其余部分也来到了GNU项目。Bash也比先进一些pdksh
,因为Bash开发人员并不局限于复制Korn shell功能。
在pdksh
AT&T将源代码发布到真正的Korn shell时,停止了工作。但是,仍然有两个主要的分支:OpenBSD pdksh
和MirBSD Korn Shell ,mksh
。
我发现有趣的mksh
是,这是目前为Cygwin打包的唯一Korn shell实现。
GNU Bash在很多方面都超越了POSIX,但是您可以要求它以更纯净的POSIX模式运行。
csh
/ tcsh
通常是1990年代初期BSD Unix上的默认交互式shell。
作为BSD的一种变体,Mac OS X的早期版本就是通过Mac OS X 10.2“ Jaguar”实现的。OS X tcsh
在OS X 10.3“ Panther”中将默认Shell从Bash 切换为Bash 。此更改不会影响从10.2或更早版本升级的系统。这些转换后的系统上的现有用户保留了他们的tcsh
外壳。
FreeBSD 声称仍将tcsh
用作默认外壳程序,但是在我在这里的FreeBSD 10 VM上,默认外壳程序似乎是POSIX兼容的Almquist外壳程序变体之一。在NetBSD上也是如此。
OpenBSD使用fork pdksh
作为默认外壳。
Linux和OS X的日益普及使某些人希望FreeBSD也可以切换到Bash,但是出于哲学原因,他们不会很快这样做。如果麻烦的话,切换起来很容易。
如今,很少有系统具有真正的香草伯恩壳/bin/sh
。您必须竭尽所能找到足够接近它的东西以进行兼容性测试。
我所知道的唯一一个运行一个现代化的计算机上一个真正的1979年的老式Bourne shell的方式:用古代的Unix V7与磁盘映像SIMH PDP-11模拟器从计算机历史仿真项目。SIMH几乎可以在每台现代计算机上运行,而不仅仅是Unix类计算机。SIMH甚至可以在Android和iOS上运行。
借助OpenSolaris,Sun首次开源了Bourne Shell的SVR4版本。在此之前,仅具有Unix源代码许可证的用户才能使用Bourne Shell的V7后版本的源代码。
现在,可以从几个不同的来源分别从已终止的OpenSolaris项目中获得该代码。
最直接的资源是Heirloom Bourne shell项目。在最初的OpenSolaris 2005发行之后不久,该功能就可用了。在接下来的几个月中完成了一些可移植性和错误修复工作,但随后该项目的开发暂停了。
JörgSchilling的Schily Tools软件包中osh
在维护此代码的版本方面做得更好。有关更多信息,请参见上文。
请记住,这些衍生自2005年源代码发行版的shell包含多字节字符集支持,作业控制,shell函数以及其他原始1979 Bourne shell中不存在的功能。
判断您是否在原始Bourne外壳上的一种方法是查看它是否支持添加的未记录功能以简化从Thompson外壳的过渡:^
作为的别名|
。就是说,类似的命令ls ^ more
将在Korn或POSIX类型的shell上给出错误,但ls | more
在真正的Bourne shell 上将表现出错误。
有时你会遇到一个fish
,scsh
或rc/es
贴壁,但他们不是C壳球迷甚至罕见。
该rc
弹的家庭不常用的Unix / Linux系统,但家庭是具有重要历史意义,这是怎么赚上面的图中的位置。rc
是Bell Labs操作系统的Plan 9的标准外壳,它是10版Unix的后继版本,它是Bell Labs对操作系统设计进行持续研究的一部分。在编程级别上它与Bourne和C shell不兼容;那里可能有一个教训。
最活跃的变体rc
似乎是Toby Goodwin维护的变体,它基于rc
Byron Rakitzis 的Unix 克隆。
“ sh兼容”是指POSIXsh
,它是所有兼容系统上必须存在的基本shell。一个与sh兼容的脚本应该在任何与POSIX兼容的机器上都可以工作。
之所以必须这样说,是因为通常/bin/sh
是的符号链接/bin/bash
,它使某些Bashism陷入了声明自己要sh
与with 一起使用的脚本中#!/bin/sh
。这些脚本无法在不用bash
作as的系统上运行/bin/sh
,包括永远的一些商业Unices 以及最近的Debian及其衍生产品。
特别是最近有一种趋势,即使用dash
Debian Almquish Shell作为默认值sh
,因为它更小且速度更快。这种趋势突显了许多原本应为sh
脚本的Bashism 。将其描述为“与sh兼容”表示它明确地打算通过完全保持在POSIX指定的语言之内而与这些系统一起工作—所有shell都将实现该功能的超集,因此可以保证在任何地方都可以使用,但是它们的扩展名不是彼此兼容。
不同的Shell具有各自的开发历史,并且随着时间的推移在不同的方向上有所不同,因为它们添加了功能来帮助用户进行交互使用或编写脚本扩展(如关联数组)。“ sh不兼容”脚本将使用其中的一些非标准扩展功能,例如Bash的[[
条件语句。
bash
和tcsh
和zsh
以及所有其他当前Shell 中的非POSIX功能非常有用,并且在很多情况下您可能需要或需要它们。只是不应该在声明自己可以使用的脚本中使用它们/bin/sh
,因为您不能依赖sh
运行于系统上的基本实现中的那些功能。
确实需要使用关联数组的脚本应确保它与bash
而不是一起运行sh
:
#!/bin/bash
declare -A array
可以在任何地方使用bash
。不需要扩展功能并且打算可移植的脚本应声明它们使用sh
并坚持使用基本的shell命令语言。
sh
)兼容(可运行)的语法。对于其他Shell,它是指该Shell是否可以运行Bourne Shell脚本。