Shell

“sh 兼容”是什麼意思?

  • April 7, 2020

我已經看到通常用於指代 shell 的片語“sh compatible”。我不確定它是否也適用於可能在 shell 中執行的程序。

shell 或其他程序“兼容 sh”是什麼意思?“sh不兼容”是什麼意思?

編輯:這個詢問 bash 和 sh 之間區別的問題非常相關: Difference between sh and bash

我仍然想直接回答“sh 兼容”的含義。一個合理的期望可能是“sh 兼容”意味著“實現 Shell 命令語言”,但是為什麼有這麼多“sh 兼容”shell,為什麼它們不同呢?

為什麼有這麼多“兼容 sh”的 shell?

Bourne shell作為Unix V7的一部分於 1979 年首次公開發布。由於幾乎所有 Unix 和類 Unix 系統都源自 V7 Unix——即使只是精神上的——Bourne shell 一直與我們“永遠”在一起。¹

Bourne shell 實際上取代了早期的 shell,將其改名為 Thompson shell,但它發生在 Unix 歷史的早期,以至於今天幾乎被遺忘了。Bourne shell 是 Thompson shell 的超集。²

Bourne 和 Thompson 砲彈都被稱為shPOSIX 指定的shell也稱為sh. 所以,當有人說sh-compatible 時,他們是在揮手指代這一系列的 shell。如果他們想具體一點,他們會說“POSIX shell”或“Bourne shell”。³

POSIX shell 基於 1988 年版本的KornShell,而 KornShell 又是為了取代 AT&T Unix 上的 Bourne shell,在功能方面超越了BSD C shell。⁴ksh就POSIX shell 的祖先而言,大多數Unix 和類 Unix 系統包括今天的 Korn shell 的一些變體。例外情況通常是微型嵌入式系統,它們無法承受完整的 POSIX shell 佔用的空間。

也就是說,Korn shell——作為與 POSIX shell 不同的東西——在商業 Unix 世界之外從未真正流行起來。這是因為它的崛起與 Unix 商業化的早期相對應,所以它被捲入了Unix 戰爭。BSD Unixes 避開了它,轉而使用 C shell,而且它的原始碼在它開始時不能在 Linux 中免費使用。⁵ 所以,當早期的 Linux 發行商尋找一個命令 shell 來配合他們的 Linux 核心時,他們通常選擇GNU Bashsh ,你說的那些兼容的之一。⁶

Linux 和 Bash 之間的早期聯繫幾乎注定了許多其他 shell的命運,ksh包括. 今天仍然有頑固分子使用這些砲彈,但他們非常少數。⁷cshtcsh

bash所有這些歷史都解釋了為什麼像, zsh, 等相對較晚的人的創建者yash選擇使它們sh兼容:Bourne/POSIX 兼容性是類 Unix 系統的外殼必須提供的最低要求才能獲得廣泛採用。

在許多系統中,預設的互動式命令 shell 和/bin/sh是不同的東西。/bin/sh或許:

  • **原始的 Bourne shell。**這在較舊的 UNIX® 系統中很常見,例如 Solaris 10(2005 年發布)及其前身。⁸
  • **一個 POSIX 認證的外殼。**這在較新的 UNIX® 系統中很常見,例如 Solaris 11 (2010)。
  • **Almquist外殼。**這是一個開源的 Bourne/POSIX shell 複製,最初於 1989 年在 Usenet 上發布,然後被貢獻給伯克利的CSRG,以包含在第一個不包含 AT&T 原始碼的 BSD 版本4.4BSD-Lite中。Almquist shell 經常被呼叫ash,即使安裝為/bin/sh.

4.4BSD-Lite 繼而成為所有現代 BSD 衍生產品的基礎,其中/bin/sh大部分仍然是 Almquist 衍生產品,以下是一個主要例外。您可以在NetBSDFreeBSD的原始碼儲存庫中看到這種直接後代:它們從第一天開始就發布了 Almquist shell 衍生產品。

ashBSD 世界之外有兩個重要的分支:

  1. dash著名的 Debian 和 Ubuntu在 2006 年採用作為預設/bin/sh實現。(Bash 仍然是 Debian 衍生產品中的預設互動式命令 shell。)
  2. BusyBox中的ash命令,在嵌入式Linux中經常使用,可以用來實現。由於它是後期的並且它是從 Debian 的舊派生的,我選擇認為它是而不是的派生,儘管它在 BusyBox 中的命令名稱。/bin/sh``dashashdash``ash

(BusyBox 還包括一個功能較少的替代方法ashcalled hush。通常情況下,任何給定的 BusyBox 二進製文件中只會內置兩者中的一個:ash預設情況下,hush但當空間非常緊張時。因此,/bin/sh在基於 BusyBox 的系統上並不總是像這樣dash。)

這種選擇在 Linux 的桌面和伺服器變體上很典型,除了 Debian 及其衍生版本。自 2003 年發布的 Panther 以來,Mac OS X 也做到了這一點。

  • 帶有ksh93POSIX 擴展的外殼,如OpenBSD 中的。儘管 OpenBSD shell 在呼叫 as 時會更改行為以避免與 Bourne 和 POSIX shell 的語法和語義不兼容sh,但它不會禁用其任何純擴展,即那些與舊 shell 不衝突的擴展。

這並不常見;您不應該ksh93期望/bin/sh.

我使用上面的“shell 腳本”作為通用術語,意思是 Bourne/POSIX shell 腳本。這是由於伯恩家族貝殼無處不在。要談論其他 shell 上的腳本,您需要給出一個限定詞,例如“C shell 腳本”。即使在 C 系列 shell 是預設互動式 shell 的系統上,最好使用 Bourne shell 編寫腳本。

很明顯,當Wikipedia 對 Unix shell 進行分類時,他們將它們分為 Bourne shell 兼容、C shell 兼容和“其他”。

此圖可能會有所幫助:

Unix Shell:Bourne、Korn、POSIX、C 和 rc Shell 家族

(點擊查看 SVG 版本,31 kB,或查看全尺寸 PNG 版本,218 kB。)

“sh不兼容”是什麼意思?

談論sh-incompatible 事物的人通常意味著以下三件事之一:

  1. 他們指的是那些“其他”貝殼之一。⁹
  2. 他們正在區分 Bourne 和 C shell 家族。
  3. 他們正在談論一個 Bourne 系列外殼中的某些特定功能,而其他所有 Bourne 系列外殼中都沒有。ksh93, bash,zsh尤其是具有許多舊“標準”外殼中不存在的功能。一旦你超越了共享的 POSIX/ksh88基礎,這三個在很多方面也是相互不兼容的。

編寫頂部帶有#!/bin/sh shebang 行的 shell 腳本但在其中使用 Bash 或 Korn shell 擴展是一個典型的錯誤。由於/bin/sh是當今許多系統上 Korn/POSIX 系列圖中的 shell 之一,因此此類腳本將在編寫它們的系統上執行,但隨後在/bin/sh來自更廣泛的 Bourne shell 系列的系統上失敗。如果腳本使用此類擴展,最佳做法是使用#!/bin/bash或shebang 行。#!/bin/ksh

有很多方法可以檢查給定的 Bourne 系列 shell 腳本是否可移植:

  • 在它上面執行checkbashisms,一個來自 Debian 項目的工具,用於檢查腳本中的“ bashisms ”。
  • posh在 Debian 軟體包儲存庫中的一個 shell下執行它,該 shell 特意只實現了SUS3指定的功能,以及一些其他次要功能
  • oboshSchily Tools 項目下執行它,這是 Bourne shell 的改進版本,由 Sun 在 2005 年作為 OpenSolaris 的一部分開源,使其成為在現代電腦上獲取 1979 年風格的 Bourne shell 的最簡單方法之一。

Schily Tools 發行版還包括一個具有許多非標準特性bosh的 POSIX 類型 shell ,但它可能有助於測試旨在在所有 POSIX 系列 shell 上執行的 shell 腳本的兼容性。它的功能集往往比.bash``zsh``ksh93

Schily Tools 還包括一個名為 的 shell bsh,但這是一個歷史上的怪事,根本不是 Bourne 家族的 shell。

為什麼它們不同?

出於同樣的原因,所有“新的和改進的!” 情況有所不同:

  • 改進後的版本只能通過打破向後兼容性來改進。
  • 有人想出了一種不同的工作方式,他們更喜歡這種方式,但這與舊方式的工作方式不同。
  • 有人試圖在沒有完全理解的情況下重新實現舊標準,所以他們搞砸了,無意中造成了差異。

腳註和旁白

  1. BSD Unix的早期版本只是 V6 Unix 的附加軟體集合。由於 Bourne shell 直到 V7 才被添加到 AT&T Unix,所以 BSD 在技術上並沒有開始擁有 Bourne shell。BSD 對 Thompson shell 的原始性質的回答是C shell

儘管如此,BSD 的第一個獨立版本(2.9BSD 和 3BSD)是基於 V7 或其可移植的後續版本UNIX/32V,因此它們確實包含 Bourne shell。

(2BSD 線變成了 BSD 的並行分支,用於 Digital 的PDP 小型電腦,而 3BSD 和 4BSD 線繼續利用更新的電腦類型,如VaxenUnix 工作站。2.9BSD 本質上是 4.1cBSD 的 PDP 版本;它們是同時代的和共享的程式碼。當 VAX 到達時,PDP 並沒有消失,所以 2BSD 線仍在蹣跚 行。)

可以肯定地說,到 1983 年,Bourne shell 在 Unix 世界中無處不在。這是計算行業中“永遠”的一個很好的近似值。那一年, MS-DOS 有了一個分層文件系統(哇,多麼可愛!),第一台24 位 Macintosh9 英寸黑白螢幕——不是灰度,實際上是黑白*——*要到明年年初才會問世。 2. 按照今天的標準,Thompson shell相當原始。它只是一個互動式命令外殼,而不是我們今天所期望的腳本程式環境。它確實有諸如管道和 I/O 重定向之類的東西,我們將其視為“Unix shell”的原型部分,因此我們將MS-DOS 命令 shell視為從 Unix 獲取它們。

Bourne shell 還取代了 PWB shell,它為 Thompson shell 添加了重要的東西,例如可程式性(ifswitchwhile和早期形式的環境變數。PWB shell 的記憶力甚至不如 Thompson shell,因為它不是每個 Unix 版本的一部分。 3. 當有人具體了解 POSIX 與 Bourne shell 的兼容性時,他們可能意味著很多事情。

在一個極端情況下,他們可能會使用 1979 年的 Bourne shell 作為他們的基準。從這個意義上說, “ sh-兼容腳本”意味著它有望在真正的 Bourne shell 或其任何繼承者和複製上完美執行:ash, bash, ksh,zsh等。

另一個極端的人將 POSIX 指定的外殼假定為基線。如今,我們將許多 POSIX shell 功能視為“標準”,以至於我們經常忘記它們實際上並不存在於 Bourne shell 中:內置算術、作業控制、命令歷史記錄、別名、命令行編輯、$()命令形式替代等 4. 儘管 Korn shell 的歷史可以追溯到 1980 年代初期,但 AT&T 直到1988 年的System V Release 4才在 Unix 中發布它。由於許多商業 Unix 都是基於 SVR4,這使得ksh幾乎所有相關的商業 Unix 從1980 年代後期開始。

(一些基於SVR3和更早版本的奇怪 Unix 風格在 SVR4 發布之後佔據了市場份額,但當革命來臨時,它們是第一個碰壁的。)

1988 年也是第一個POSIX 標準問世的一年,其基於 Korn shell 的“POSIX shell”。後來,在 1993 年,Korn shell 的改進版本問世。由於 POSIX 有效地將原始版本固定到位,因此ksh分為兩個主要版本:ksh88ksh93,以其分裂所涉及的年份命名。

ksh88雖然差異很小,但並不完全兼容 POSIX,因此某些版本的ksh88shell 被修補為與 POSIX 兼容。(這是在 Slashdot 上對 David G. Korn 博士的一次有趣採訪。是的,就是編寫 shell 的人。)

ksh93POSIX shell 的完全兼容的超集。自從主要源儲存庫從 AT&T轉移到 GitHub以來,開發ksh93一直是零星的,而在我寫這篇文章時,最新版本大約有 3 年曆史,ksh93v。(該項目的基本名稱仍然帶有後綴,以表示 1993 年以後的發布版本。)ksh93

將 Korn shell 作為與 POSIX shell 分開的東西的系統通常使其可用/bin/ksh,儘管有時它隱藏在其他地方。

當我們ksh按名稱談論 Korn shell 時,我們談論的ksh93是將其與向後兼容的 Bourne 和 POSIX shell 子集區分開來的特性。你今天很少遇到純淨ksh88的。 5. AT&T 將 Korn shell 原始碼保留到 2000 年 3 月。到那時,Linux 與 GNU Bash 的聯繫非常緊密。Bashksh93 各有優勢,但在這一點上,慣性使 Linux 與 Bash 緊密相關。

至於為什麼早期的 Linux 供應商最常選擇 GNU Bash 而不是 GNU Bash pdksh,它在 Linux 剛起步時可用,我猜這是因為使用者空間的其餘大部分也來自GNU項目。Bash 也比 更先進pdksh,因為 Bash 開發人員並不局限於複製 Korn shell 功能。

pdksh大約在 AT&T 將原始碼發佈到真正的 Korn shell 時,工作就停止了。然而,仍然維護著兩個主要的分支:OpenBSDpdkshMirBSD Korn Shellmksh,.

我覺得有趣的mksh是,這是目前為 Cygwin 打包的唯一 Korn shell 實現。 6. GNU Bash 在許多方面都超越了 POSIX,但您可以要求它以更純粹的 POSIX 模式執行。 7. csh/tcsh通常是 1990 年代早期 BSD Unix 上的預設互動式 shell。

作為 BSD 變體,Mac OS X 的早期版本就是這樣,通過 Mac OS X 10.2 “Jaguar”OS X 在OS X 10.3 “Panther”中將預設 shell 從切換tcsh到 Bash 。此更改不會影響從 10.2 或更早版本升級的系統。這些轉換後的系統上的現有使用者保留了他們的外殼。tcsh

FreeBSD聲稱仍tcsh用作預設 shell,但在我在這裡擁有的 FreeBSD 10 VM 上,預設 shell 似乎是與 POSIX 兼容的Almquist shell 變體之一。在 NetBSD 上也是如此。

OpenBSD 使用 forkpdksh作為預設 shell。

Linux 和 OS X 的更高流行度讓一些人希望 FreeBSD 也轉向 Bash,但出於哲學原因,他們不會很快這樣做。如果這讓您感到困擾,切換它很容易。 8. 像現在這樣,很難找到具有真正香草 Bourne shell 的系統/bin/sh。你必須不遺餘力地找到足夠接近它的東西來進行兼容性測試。

我知道只有一種方法可以在現代電腦上執行真正的 1979 年老式 Bourne shell:使用來自Computer History Simulation Project的Ancient Unix V7磁碟映像和SIMH PDP-11 模擬器。SIMH 幾乎可以在每台現代電腦上執行,而不僅僅是類 Unix 電腦。SIMH 甚至可以在 AndroidiOS 上執行。

通過OpenSolarisSun首次開源了 Bourne shell 的 SVR4 版本。在此之前,Bourne shell 的 V7 後版本的原始碼只提供給那些擁有 Unix 原始碼許可證的人。

現在,該程式碼與來自幾個不同來源的已失效 OpenSolaris 項目的其餘部分分開提供。

最直接的來源是Heirloom Bourne shell 項目。這在 OpenSolaris 最初的 2005 發行版之後不久就可用了。在接下來的幾個月中完成了一些可移植性和錯誤修復工作,但隨後項目的開發停止了。

Jörg Schilling 在維護此程式碼的版本方面做得更好,就像obosh在他的Schily 工具包中一樣。有關更多資訊,請參見上文。

請記住,這些源自 2005 年原始碼版本的 shell 包含多字節字元集支持、作業控制、shell 函式以及原始 1979 Bourne shell 中不存在的其他功能。

判斷您是否使用原始 Bourne shell 的一種方法是查看它是否支持添加的未記錄功能以簡化從 Thompson shell 的轉換:^作為|. 也就是說,like 命令ls ^ more在 Korn 或 POSIX 類型的 shell 上會出錯,但ls | more在真正的 Bourne shell 上會表現得像。 9. 偶爾你會遇到一個fish,scshrc/es追隨者,但他們甚至比 C shell 的粉絲還要少見。

shell 系列在 Unix/Linux 系統上並不常用,但該rc系列在歷史上很重要,這就是它在上圖中贏得一席之地的原因。是貝爾實驗室作業系統Plan 9rc的標準外殼,是第 10 版 Unix的繼承者,是貝爾實驗室對作業系統設計的持續研究的一部分。它在程式級別上與 Bourne 和 C shell 不兼容;那裡可能有一個教訓。

最活躍的變體rc似乎是由 Toby Goodwin 維護的變體,它基於rcByron Rakitzis 的 Unix 複製。

引用自:https://unix.stackexchange.com/questions/145522