“sh 兼容”是什么意思?

“sh 兼容”是什么意思?

我见过短语“sh兼容”通常用于指shell。我不确定它是否也适用于可能在 shell 内运行的程序。

shell 或其他程序“sh 兼容”意味着什么? “sh 不兼容”意味着什么?

编辑:这个询问 bash 和 sh 之间区别的问题非常相关: sh 和 bash 的区别

我仍然想直接回答“sh 兼容”的含义。一个合理的期望可能是“sh 兼容”意味着“实现 Shell 命令语言”,但是为什么有这么多“sh 兼容”shell 以及它们为什么不同呢?

答案1

为什么有这么多“sh 兼容”shell?

伯恩外壳于 1979 年首次公开发布,作为Unix V7。因为几乎所有 Unix 和类 Unix 系统源自 V7 Unix- 即使只是在精神上 - Bourne shell 已经“永远”伴随着我们。

Bourne shell 实际上取代了早期的 shell,重新命名为汤普森壳,但它在 Unix 历史上发生得太早了,以至于今天几乎被遗忘了。Bourne shell 是 Thompson shell 的超集

伯恩炮弹和汤普森炮弹都被称为sh。这POSIX 指定的 shell也称为sh。因此,当有人说sh“兼容”时,他们指的是这一系列的 shell。如果他们想具体一点,他们会说“POSIX shell”或“Bourne shell”。

POSIX shell 基于 1988 版本康壳公司,这反过来又旨在取代 AT&T Unix 上的 Bourne shell,超越了BSD C 外壳⁴ 就 POSIX shell 的祖先而言ksh,大多数 Unix 和类 Unix 系统都包含 Korn shell 的某些变体。例外情况通常是小型嵌入式系统,它们无法承担完整的 POSIX shell 所占用的空间。

也就是说,Korn shell——作为与 POSIX shell 不同的东西——从未在商业 Unix 世界之外真正流行起来。这是因为它的兴起恰逢 Unix 商业化的初期,所以它陷入了Unix 战争。BSD Unixes 放弃了它而倾向于使用 C shell,而且它的源代码在 Linux 刚开始时并不是免费提供的。⁵ 因此,当早期的 Linux 发行商寻找与他们的 Linux 内核配合使用的命令 shell 时,他们通常会选择GNU 重击sh,您正在谈论的那些兼容之一。虽然 GNU Bash 在很多方面确实超越了 POSIX,但您可以要求它以更纯粹的 POSIX 模式运行

Linux 和 Bash 之间的早期联系决定了许多其他 shell 的命运,包括kshcshtcsh。今天仍有顽固分子使用这些贝壳,但他们只是少数。⁶

所有这些历史解释了为什么相对后来者的创造者喜欢bashzsh, 和yash选择使它们sh兼容:Bourne/POSIX 兼容性是类 Unix 系统的 shell 必须提供的最低限度才能获得广泛采用。

在许多系统中,默认的交互式命令 shell/bin/sh是不同的东西。/bin/sh或许:

  • 原始的 Bourne shell。这在较旧的 UNIX® 系统中很常见,例如 Solaris 10(2005 年发布)及其前身。⁸

  • POSIX 认证的 shell。这在较新的 UNIX® 系统中很常见,例如 Solaris 11 (2010)。

  • 阿尔姆奎斯特壳。这是一个开源 Bourne/POSIX shell 克隆最初于 1989 年在 Usenet 上发布,然后贡献给伯克利中国南方研究集团包含在不包含 AT&T 源代码的第一个 BSD 版本中,4.4BSD-精简版.⁷ Almquist shell 经常被调用ash,即使安装为/bin/sh.

    ashBSD 世界之外有两个重要的分支:

    1. dash,被 Debian 和 Ubuntu 广泛采用2006 年作为默认/bin/sh实施。 (Bash 仍然是默认值交互的Debian 衍生品中的命令 shell。)

    2. ash命令忙碌盒,在嵌入式Linux中经常使用,可以用来实现/bin/sh。由于它已过时dash并且它源自 Debian 的旧ash软件包,我选择将其视为dash而不是的派生ash,尽管它的命令名称在 BusyBox 中。

      (BusyBox 还包括一个功能较少的替代方案,ash称为hush。通常,任何给定的 BusyBox 二进制文件中只会内置两者之一:ash默认情况下,但当hush空间非常紧张时。因此,/bin/sh在基于 BusyBox 的系统上并不总是dash类似。)

  • GNU 重击, 哪个当调用时禁用其大部分非 POSIX 扩展sh

    这种选择在 Linux 的桌面和服务器变体上很常见,Debian 及其衍生版本除外。

    Apple 在 2003 年的 10.3 版 (Panther) 中将 Mac OS X 中的默认设置从tcshBash 更改为 Bash,然后一直保留到 2018 年发布的 10.14 (Mojave)。直到第二年的版本 — 10.15 (Catalina) —他们从 Bash 转向了zsh,这在很多方面都有所不同,但并不广泛兼容 POSIX。

  • ksh93具有POSIX 扩展的shell, 作为在 OpenBSD 中。尽管 OpenBSD shell 会更改行为以避免在调用 as 时与 Bourne 和 POSIX shell 发生语法和语义不兼容sh,但它不会禁用其任何纯扩展,即那些不与旧 shell 冲突的扩展。

    这种情况并不常见;您不应该ksh93期望/bin/sh.

我在上面使用“shell 脚本”作为通用术语,意思是 Bourne/POSIX shell 脚本。这是由于伯恩家族的炮弹无处不在。要谈论其他 shell 上的脚本编写,您需要给出一个限定符,例如“C shell script”。即使在 C 系列 shell 是默认交互式 shell 的系统上,它也是如此更好的使用 Bourne shell 编写脚本。

很明显,当维基百科对 Unix shell 进行分类时,他们将它们分为 Bourne shell 兼容、C shell 兼容和“其他”。

此图可能有帮助:

Unix Shell:Bourne、Korn、POSIX、C 和 rc Shell 系列

(点击查看 SVG 版本,30 kiB,或查看全尺寸 PNG 版本,213 kB。)

“sh 不兼容”意味着什么?

有人谈论sh不兼容的事情通常意味着以下三种情况之一:

  1. 他们指的是那些“其他”贝壳之一。⁹

  2. 他们对 Bourne 和 C shell 系列进行了区分。

  3. 他们正在讨论一个 Bourne 系列 shell 中的某些特定功能,而所有其他 Bourne 系列 shell 中都没有这些功能。ksh93bashzsh特别是具有许多旧“标准”shell 中不存在的功能。一旦超越了共享的 POSIX/ksh88基础,这三者在很多方面也是相互不兼容的。

使用以下命令编写 shell 脚本是一个典型的错误#!/bin/sh 舍邦线位于顶部,但要在其中使用 Bash 或 Korn shell 扩展。由于/bin/sh是上面 Korn/POSIX 系列图中的 shell 之一,现在在许多系统上运行,因此此类脚本将在编写它们的系统上运行,但在来自/bin/sh更广泛的 Bourne 系列 shell 的系统上会失败。如果脚本使用此类扩展,最佳实践是使用#!/bin/bash或shebang 行。#!/bin/ksh

有很多方法可以检查给定的 Bourne 系列 shell 脚本是否可移植:

  • 穿过便携式外壳编程中的章节GNU Autoconf 手册。您可能会认识到它在您的脚本中谈到的一些有问题的构造。

  • 跑步checkbashisms其上有一个来自 Debian 项目的工具,用于检查脚本“巴什主义”。

  • 在下面运行它posh,Debian 软件包存储库中的一个 shell,专门实现仅由SUS3,加上其他一些小功能

  • obosh从下面运行它希利工具项目是 Bourne shell 的改进版本,由 Sun 在 2005 年作为 OpenSolaris 的一部分开源,使其成为在现代计算机上获取 1979 风格的 Bourne shell 的最简单方法之一。

    Schily Tools 发行版还包括boshPOSIX 类型的 shell许多非标准功能,但这对于测试旨在在所有 POSIX 系列 shell 上运行的 shell 脚本的兼容性可能很有用。它的功能集往往比bashzsh的增强版本更加保守ksh93

    Schily Tools 还包括一个名为 的 shell bsh,但那是历史上的怪事这根本不是伯恩家族的外壳。

为什么它们不同?

出于同样的原因,所有“新的和改进的!”事情有所不同:

  • 改进后的版本只能通过破坏向后兼容性来改进。

  • 有人想到了一种不同的工作方式,他们更喜欢这种方式,但这与旧的工作方式不同。

  • 有人试图在不完全理解的情况下重新实现旧标准,导致他们搞砸并造成无意的差异。


脚注和旁白:

  1. BSD Unix 的早期版本只是 V6 Unix 的附加软件集合。由于 Bourne shell 直到 V7 才被添加到 AT&T Unix,因此 BSD 从技术上来说并没有开始拥有 Bourne shell。 BSD 对 Thompson shell 原始性质的回答是C壳

    尽管如此,因为 BSD 的第一个独立版本(2.9BSD 和 3BSD)是基于 V7 或其可移植后继版本UNIX/32V, 他们做过包括 Bourne shell。

    (2BSD 线变成了 BSD 的并行分支,用于 Digital 的等离子小型机而 3BSD 和 4BSD 系列则利用了较新的计算机类型,例如瓦克森Unix工作站。 2.9BSD本质上是4.1cBSD的PDP版本;他们是同时代的,并且共享代码。因为当 VAX 到达时 PDP 并没有立即消失,所以 2BSD 线路是仍然 步履蹒跚 沿着.)

    可以肯定地说,到 1983 年,Bourne shell 在 Unix 世界中已经无处不在。这在计算行业中是“永远”的一个很好的近似。那年 MS-DOS 有了分层文件系统(哇哦,多可爱啊!)第一个24 位麦金塔电脑其 9 英寸黑白屏幕——字面意思不是灰度黑色的白色的- 直到明年初才会问世。

  2. 汤普森炮弹是相当原始按照今天的标准。它只是一个交互式命令外壳,而不是我们今天期望的脚本编程环境。它确实有管道和 I/O 重定向等功能,我们认为它们是“Unix shell”的原型部分,因此我们认为MS-DOS 命令外壳就像从 Unix 获取它们一样。

    Bourne shell 也被替换了电路板外壳,它向 Thompson shell 添加了重要的内容,例如可编程性(ifswitchwhile)和早期形式的环境变量。 PWB shell 比 Thompson shell 更不被人记住,因为它并不是每个 Unix 版本的一部分。

  3. 当有人不是具体到 POSIX 与 Bourne shell 兼容性,它们可能意味着一系列的事情。

    在一种极端情况下,他们可能会使用 1979 年的 Bourne shell 作为基准。从这个意义上说,“sh兼容脚本”意味着它可以在真正的 Bourne shell 或其任何后继者和克隆:ashbashkshzsh等上完美运行。

    另一个极端的人则假设 POSIX 指定的 shell 作为基线。如今,我们将许多 POSIX shell 功能视为“标准”,以至于我们经常忘记它们实际上并不存在于 Bourne shell 中:内置算术、作业控制、命令历史记录、别名、命令行编辑、$()命令形式替换等

  4. 尽管 Korn shell 的历史可以追溯到 20 世纪 80 年代初,但 AT&T 直到 2017 年才将其移植到 Unix 中系统 V 版本 41988 年。由于如此多的商业 Unix 都是基于 SVR4 的,因此ksh从 20 世纪 80 年代末开始,几乎所有相关的商业 Unix 都采用了 SVR4。

    (一些奇怪的 Unix 风格基于SVR3并在 SVR4 发布后更早地占据了部分市场,但它们是首先靠墙什么时候革命来了。)

    1988年也是第一年POSIX标准推出了基于 Korn shell 的“POSIX shell”。后来,在 1993 年,Korn shell 的改进版本问世了。由于 POSIX 有效地将原始版本固定到位,ksh因此分为两个主要版本:ksh88ksh93,以它们分裂的年份命名。

    ksh88虽然差异很小,但并不完全兼容 POSIX,因此某些版本的ksh88shell 被修补为兼容 POSIX。 (这来自一个Slashdot 上对 David G. Korn 博士的有趣采访。是的,就是写 shell 的人。)

    ksh93完全兼容的 POSIX shell 超集。发展ksh93零星的自从主要源存储库从 AT&T 移出以来到 GitHub当我写这篇文章时,最新版本 ksh93v 已经发布了大约 3 年。 (该项目的基本名称仍然保留,ksh93并添加后缀以表示 1993 年之后的发行版本。)

    包含 Korn shell 作为独立于 POSIX shell 的系统通常将其作为 提供/bin/ksh,尽管有时它隐藏在其他地方。

    当我们谈论kshKorn shell 的名称时,我们谈论的是ksh93它与其向后兼容的 Bourne 和 POSIX shell 子集的区别特征。ksh88今天你很少遇到纯粹的人了。

  5. AT&T 保留 Korn shell 源代码的专有性直到2000年3月。到那时,Linux 与 GNU Bash 的联系就非常紧密了。重击和ksh93 每个人都比另一个人有优势,但此时惯性使 Linux 与 Bash 紧密联系在一起。

    至于为什么早期的 Linux 供应商最常选择 GNU Bash 而不是pdksh, 哪个曾是在 Linux 刚刚起步时可用,我猜这是因为用户空间的其余大部分也来自GNU 计划。 Bash 也比 更先进pdksh,因为 Bash 开发人员并不局限于复制 Korn shell 功能。

    pdksh当 AT&T 发布真正的 Korn shell 源代码时,相关工作就停止了。然而,仍有两个主要的分支仍在维护:OpenBSDpdkshMirBSD 科恩外壳,mksh

    我发现有趣的是,这mksh是当前为 Cygwin 打包的唯一 Korn shell 实现。

  6. csh在 20 世纪 90 年代初期, /tcsh通常是 BSD Unix 上的默认交互式 shell。

    作为 BSD 变种,Mac OS X 的早期版本是这样的,通过 Mac OS X10.2 “美洲虎”。 OS X 将默认 shell 从tcshBash 切换为OS X 10.3“黑豹”。此更改不会影响从 10.2 或更早版本升级的系统。这些转换后的系统上的现有用户保留了他们的tcsh外壳。

    FreeBSDtcsh用作默认 root shell直到版本 14,但它现在是 POSIX 兼容的之一Almquist 外壳变体。在 NetBSD 上也是如此。

    OpenBSD 使用 的 forkpdksh作为默认 shell。

    Linux 和 OS X 的日益普及使得一些人希望 FreeBSD 也能转向 Bash,但他们不会很快这样做,因为哲学原因。这是轻松切换,如果这让您烦恼。

  7. 4.4BSD-Lite 反过来成为所有现代 BSD 衍生品的基础,/bin/sh其中大多数仍然作为 Almquist 衍生品,除了下面提到的一个主要例外。您可以在源代码存储库中看到这种直接后代网络BSD自由BSD:他们从第一天起就开始运输 Almquist shell 衍生品。

  8. /bin/sh如今,很少能找到具有真正香草 Bourne shell 的系统了。您必须不遗余力地找到足够接近它的东西来进行兼容性测试。

    我知道只有一种方法可以在现代计算机上运行真正的 1979 年老式 Bourne shell:使用古老的 Unix V7磁盘映像与SIMH PDP-11 模拟器来自计算机历史模拟项目。 SIMH 运行于几乎每台现代计算机,不仅仅是类 Unix 的。

    开放Solaris,太阳首次开源 Bourne shell 的 SVR4 版本。在此之前,V7 之后版本的 Bourne shell 的源代码仅适用于那些拥有 Unix 源代码许可证的人。

    该代码现在可以从几个不同的来源与已解散的 OpenSolaris 项目的其余部分分开获得。

    最直接的来源是Heirloom Bourne shell 项目。它在 2005 年最初发布 OpenSolaris 后不久就可用了。在接下来的几个月里完成了一些可移植性和错误修复工作,但随后该项目的开发停止了。

    Jörg Schilling 在维护此代码的一个版本方面做得更好,如obosh他的Schily 工具包裹。有关这方面的更多信息,请参阅上文。

    请记住,这些源自 2005 年源代码版本的 shell 包含多字节字符集支持、工作控制、外壳函数,以及 1979 年原始 Bourne shell 中不存在的其他功能。

    判断您是否使用原始 Bourne shell 的一种方法是查看它是否支持为简化从 Thompson shell 的转换而添加的未记录的功能:^作为|.也就是说,类似的命令ls ^ more在 Korn 或 POSIX 类型的 shell 上会给出错误,但它的行为就像ls | more在真正的 Bourne shell 上一样。

  9. 偶尔你会遇到一个fish,scsh或者rc/es忠实拥护者,但他们比 C shell 粉丝还要稀有。

    shell系列rc在 Unix/Linux 系统上并不常用,但该系列在历史上很重要,这就是它在上图中赢得一席之地的原因。rc是标准外壳贝尔实验室的 Plan 9操作系统,一种继承者第十版 Unix,作为贝尔实验室对操作系统设计的持续研究的一部分而创建。它在编程层面上与 Bourne 和 C shell 都不兼容;里面有一个教训。

答案2

“sh 兼容”是指POSIXsh,所有兼容系统上都需要存在的基本 shell。 sh 兼容的脚本应该可以在任何 POSIX 兼容的机器上运行。

有必要这样说的原因是,通常/bin/sh是 的符号链接/bin/bash,这让一些 Bashisms 溜进了声明自己与sh一起使用的脚本中#!/bin/sh。这些脚本无法在不使用bashas 的系统上运行/bin/sh,包括一些商业 Unices,并且德班衍生品最近。

特别是有一种趋势使用dashDebian Almquish Shellsh最近成为默认设置,因为它更小并且速度更快。这种趋势凸显了许多所谓sh剧本中的羞辱。将某些东西描述为“sh 兼容”表明它明确打算通过完全保持在这些系统内来与这些系统一起工作。POSIX 指定语言— 所有 shell 都将实现该功能的超集,因此保证它可以在任何地方工作,但它们的扩展彼此不兼容。

不同的 shell 都有自己的发展历史,并且随着时间的推移朝着不同的方向发展,因为它们添加了帮助用户交互使用的功能,或者编写了关联数组等脚本扩展。 “sh 不兼容”脚本将使用其中一些非标准扩展功能,例如 Bash 的[[条件。

bashtcsh以及zsh所有其他当前 shell中的非 POSIX 功能有用的,并且在很多情况下您可能需要它们。它们只是不应该在声明自己可以使用的脚本中使用/bin/sh,因为您不能依赖sh正在运行的系统上的基本实现中的这些功能。

确实需要使用关联数组的脚本应确保其运行bash而不是sh

#!/bin/bash
declare -A array

这将适用于任何地方bash。不需要扩展功能且可移植的脚本应声明它们使用sh并坚持基本 shell 命令语言。

相关内容