題 什麼時候我必須使用#!/ bin / bash和#!/ bin / sh?


什麼時候 #!/bin/bash 比比較合適 #!/bin/sh 在shell腳本中?


97
2017-10-10 07:02


起源


當你使用 bash 功能和語法而不是 sh 功能和語法。 - Mokubai♦
看到 stackoverflow.com/questions/5725296/... - SPRBRN
如果它對任何人都有幫助,我已經註意到了 vim 將突出顯示 bash - 如果你的腳本有的話 #!/bin/sh 家當。我只改變它 bash 如果事情變得毛茸茸,開始需要bash功能。 - SeldomNeedy
@SeldomNeedy默認情況下它突出顯示的一些東西在任何POSIX shell中都可以正常工作。 $(...) 特別令人討厭。而且,其中一些是微妙的[<(...) 和 cmd >& file 沒有任何錯誤突出顯示,例如,他們只是沒有特別突出顯示他們的意思,有或沒有 g:is_bash] - Random832
@ Random832最近在這個主題上看起來有一些活動 vim的問題跟踪器。 - SeldomNeedy


答案:


簡而言之:

  • 有幾個shell實現了超集 POSIX sh規範。在不同的系統上, /bin/sh 可能是ash,bash,dash,ksh,zsh和c的鏈接。 (它總是與sh兼容 - 從不csh或fish。)

  • 只要你堅持下去 sh 只有功能,你可以(甚至可能)使用 #!/bin/sh 並且腳本應該工作正常,無論它是哪個shell。

  • 如果你開始使用特定於bash的功能(例如數組),你應該專門請求bash - 因為,即使 /bin/sh 已經調用了bash 您的 系統,它可能不會 其他人的 系統,你的腳本不會在那裡運行。 (當然同樣適用於zsh和ksh。)你可以使用 shellcheck 識別基礎。

  • 即使腳本僅供個人使用,您可能會注意到某些操作系統會發生變化 /bin/sh 升級期間 - 例如在Debian上它曾經是bash,但後來被非常小的破折號所取代。使用bashisms但有的腳本 #!/bin/sh 突然間爆了。

然而:

  • 甚至 #!/bin/bash 是不是很正確。在不同的系統上,bash可能會存在 /usr/bin 要么 /usr/pkg/bin 要么 /usr/local/bin

  • 更可靠的選擇是 #!/usr/bin/env bash,它使用$ PATH。 (雖然 env 工具本身也沒有嚴格保證, /usr/bin/env 仍然適用於更多系統而不是 /bin/bash 確實。)


143
2017-10-10 14:03



很好的答案。你的意思是CW嗎? - Mokubai♦
如果bash運行,請注意 /bin/sh 然後它會試圖模仿 sh 功能(見 手冊頁),不確定bash特定功能在此模式下是否可用。 env 工具是一個posix工具 它應該在大多數發行版中找到,但我不確定,因為有些人可能不尊重posix。 - Brice
不,實際上是POSIX 特別聲明 它不能被認為是在 /bin:“應用程序應注意,shell的標準PATH不能假定為/ bin / sh或/ usr / bin / sh,並且應通過詢問getconf PATH返回的PATH來確定,確保返回的路徑名是絕對的pathname而不是內置的shell“。另見 這個問題 而且,具體而言 這個答案。 - terdon
嗯,好吧,這意味著POSIX實際上沒有定義可移植的方式 #! 腳本工作? - grawity
POSIX sh是 不 Bourne:它更像是早期ksh的衍生物,而不是Bourne的直接後裔。區分它們很容易: echo foo ^ cat 發射 foo ^ cat 在POSIX sh中,僅發出 foo 在伯恩(作為 ^ 是一個管道角色)。 - Charles Duffy


使用與您實際用於開發和調試腳本的shell相對應的shebang。即如果您的登錄shell是 bash,並在終端中將腳本作為可執行文件運行,使用 #!/bin/bash。不要只是假設你沒有使用數組(或其他任何東西) bash 您知道的功能),您可以安全地選擇您喜歡的任何外殼。貝殼之間有許多細微的差別(echo,函數,循環,你的名字),沒有適當的測試就無法發現。

考慮一下:如果你離開 #!/bin/bash 並且您的用戶沒有它,他們會看到明確的錯誤消息,例如

Error: /bin/bash not found

大多數用戶可以通過安裝適當的軟件包在一分鐘內修復此問題。另一方面,如果你更換shebang #!/bin/sh 並在一個系統上測試它 /bin/sh 是一個符號鏈接 /bin/bash,你的用戶沒有 bash 會遇到麻煩。他們很可能會看到一個神秘的錯誤消息,如:

Error in script.sh line 123: error parsing token xyz

這可能需要幾個小時來修復,並且不知道他們應該使用哪個shell。

你想要在shebang中使用不同的shell的原因並不多。一個原因是你使用的外殼並不普遍。另一個是獲得表現 sh 這在某些系統上要快得多,而且你的腳本將成為性能瓶頸。在這種情況下,使用目標shell徹底測試您的腳本,然後更改shebang。


18
2017-10-14 13:55



@Hastur我沒有收到您的評論。 shebang肯定會定義用於運行腳本的shell,你認為我的回答意味著什麼嗎? - Dmitry Grigoryev
算了吧。我誤解了這一部分 “你為什麼要用”... - Hastur


你應該只使用 #! /bin/sh

您不應該在shell腳本中使用bash(或zsh,或fish或.....)擴展。

您應該只編寫可以使用的shell腳本 任何 shell語言的實現(包括與shell本身一起使用的所有“實用程序”程序)。這些天你可以 大概 採取 POSIX.1-2001 ( -2008)作為shell和實用程序能夠具有權威性的權威,但請注意,有一天您可能需要將腳本移植到遺留系統(例如Solaris或AIX),其shell和實用程序大約在1992年被凍結。

什麼,認真的?!

是的,認真的。

事情就是這樣:殼牌是一個 可怕 編程語言。它唯一能做的就是 /bin/sh 是唯一的腳本解釋器 一切 Unix安裝保證有。

這是另一回事:核心Perl 5解釋器的一些迭代(/usr/bin/perl)是 更多 可能在隨機選擇的Unix安裝上可用 (/(usr|opt)(/(local|sfw|pkg)?)?/bin/bash 是。其他優秀的腳本語言(Python,Ruby,node.js等 - 在與shell比較時我甚至在該類別中包含PHP和Tcl)也大致與bash和其他擴展shell一樣可用。

因此,如果您可以選擇編寫bash腳本, 你可以選擇使用一種並不可怕的編程語言。

現在, 簡單 shell腳本,只是從cron作業或其他東西按順序運行一些程序的那種,將它們留作shell腳本沒有任何問題。但是簡單的shell腳本不需要數組或函數或 [[ 甚至。你應該只寫 複雜 當你沒有任何其他選擇時,shell腳本。例如,Autoconf腳本仍然是shell腳本。但是那些腳本必須繼續運行 一切 化身 /bin/sh 這與正在配置的程序有關。這意味著他們不能使用任何擴展。這些天你可能不必關心舊的專有Unix,但你可能 應該 關心當前的開源BSD,其中一些不安裝 bash 默認情況下,嵌入式環境只提供最小的shell和 busybox

總之,你發現自己的那一刻 希望 便攜式shell語言中沒有的功能,這表明腳本變得太複雜而無法保留shell腳本。用更好的語言改寫它。


5
2017-10-11 06:30



對不起,但這有點傻。是的,如果您正在撰寫將要分發的內容和ii)在不同的環境中編寫的內容,您應該堅持使用基本內容 sh。然而,這與說明你應該的相去甚遠 決不 使用其他貝殼。每天都有數千個(可能更多)腳本編寫,絕大多數腳本只能在一台機器上運行。您的建議對生產代碼有意義,但不適用於大多數腳本編寫的日常“sysdaminy”作業。如果我知道我的腳本只會被我和Linux機器使用,那麼bash就可以了。 - terdon
@terdon關鍵是,如果您可以選擇編寫bash腳本,那麼您還可以選擇編寫perl(或其他)腳本,這是 總是 更好的選擇。 - zwol
@terdon答案肯定不是傻,你的評論反而簡直太天真了。與Perl相比,Shell腳本的調試非常糟糕,因此可以輕鬆地使用完整的IDE進行圖形化調試。此外,每天為一些小事做的大部分腳本往往會被改變並重新改變,增長,作為例子被複製到同事或網絡等。很可能沒有理由承​​擔這樣的風險。 - Thorsten Schöning
@ThorstenSchöning我說 一點 愚蠢。如果是這樣的話 Unix和Linux 甚至 堆棧溢出 我甚至可能同意。如果我們談論的是一般最佳實踐或專業程序員,當然最好堅持基本的POSIX sh。但是,這是 超級用戶在我看來,一個針對最終用戶並告訴人們在編寫shell腳本時從不使用bash或zsh的網站是極端的。 - terdon
@terdon實際上是 更多 在我看來,重要的是阻止最終用戶編寫複雜的shell腳本。專業人員平均擁有更高的技能水平(因此他們更有可能能夠應對複雜的shell腳本的陷阱),應該知道他們需要移植到哪些環境,並且付出的不是放棄沮喪。 - zwol


通常,如果時間比功能更重要,您將使用更快的shell。 sh經常混淆為破折號,並且傾向於用於root的cron任務或批處理操作,其中每(納秒)計數。


3
2017-10-11 20:36



從文件系統加載一個額外的shell解釋器可以否定這樣的優勢,並且納秒(與實際機器週期處於同一數量級)的任何東西都是C和彙編語言程序員的領域。 - rackandboneman
如果你有數十億個,那麼納秒只會對cron作業產生影響,而cron無論如何都無法處理這麼多。 - Dmitry Grigoryev
即使mckenzm誇大了一點,也無可否認,擁有更多性能更好!不要掛在“納米”部分。 (納秒甚至不計入C,除非它是實時系統上的內環等等!) - jpaugh
@jpaugh除非您正在使用(遺留)系統,該系統假定某些操作至少需要一段特定的時間。它發生了! - JAB


更簡單,使用 sh 如果大多數係統的可移植性是最重要的 bash 如果你想使用它的一些特定功能,比如數組,如果bash的版本支持它。


2
2017-11-24 18:41





  • sh(對於大多數情況),bash如果特別需要(或ksh,或其他)

最安全的道路。硬編碼時,將是/ usr / bin /shellOfChoice 但是我現在總是試圖使用一個新的約定 - 因為改變PATH的“默認位置”可能會改變:

#!/ usr / bin / env sh 要么
 #!/ usr / bin / env bash
或者例如,perl腳本
 #!/ usr / bin / env perl -w

當然,當你有理由讓腳本永遠不會自動獲取新的PATH然後繼續硬編碼 - 然後/ usr / bin / something應該是最有可能使用的路徑。


1