當前位置: 首頁>>技術教程>>正文


使用#!/bin/sh或#!/bin/bash以獲得Ubuntu-OSX的兼容性並易於使用& POSIX

, , , ,

問題描述

我知道我可以用作第一行腳本來調用所需的shell。

如果絕對需要與所有unix係統兼容,那麽會建議使用#!/bin/sh嗎?

就我而言,我唯一關心的OS是Ubuntu(Debian)和OSX。鑒於此,我可以使用#!/bin/bash並確保它在兩個係統上都可以工作嗎?這還會使使用具有更現代和更清晰語法的命令腳本更加容易嗎?使用#!/bin/sh是否也與使用POSIX有關?

最佳方法

對於初學者,如果您可以假設已預先安裝Bash(據我所知,您列出的所有係統都是這種情況),請使用以下hashbang進行兼容:

#!/usr/bin/env bash

無論是/bin還是/usr/local/bin,這都會調用恰好要配置的bash

在範圍廣泛的大多數係統(包括AIX,Solaris和幾種BSD版本)上,bash最終出現在不同的位置,而env總是最終出現在/usr/bin/env。但是,訣竅不是我的,而是Bash Cookbook的作者。

無論如何,是的,Bash允許您使用一些”modern”功能,使您的生活更輕鬆。

例如,雙括號:

[[ -f "/etc/debian_version" ]] && echo "This is a Debian flavor"

而在傳統的殼方言中,您必須求助於:

test -f "/etc/debian_version" && echo "This is a Debian flavor"

但是關於雙括號的最好之處在於它們允許使用正則表達式進行匹配。 Bash Hackers Wiki將為您提供許多朝此方向的技巧。

您還可以使用非常方便的表達式,如$((2**10))或其他符合$((expression))語法的算術表達式。

對子殼使用反引號也可以,盡管有些過時了。但是$(command ...)調用的嵌套功能更加方便,因為您不必在不同的子Shell級別上轉義許多內容。

這些隻是Bash在傳統的通用PO​​SIX sh語法之上為您提供的一些內容。

但是,如果您想在shell上擁有更多功能(不僅是在腳本中),還可以看看zsh

次佳方法

在Debian和Ubuntu中,/bin/shdash,它是POSIX-compliant shell 。如果指定#!/bin/sh,則必須將自己限製為腳本中的POSIX語句。 (優點是dash的啟動速度比bash快,因此您的腳本可以在更短的時間內完成其工作。)

在許多(大多數?)其他Linux係統上,/bin/shbash,這就是為什麽許多腳本都使用#!/bin/sh作為它們的shebang行編寫的原因,即使它們使用了bash擴展名。

如果要使用bash擴展名,則在所有係統上最安全的方法是指定#!/bin/bash;這樣,您將明確聲明對bash的依賴性。您需要在Debian和Ubuntu上執行此操作。另外,在以/bin/sh bash de-activates身份啟動時,有一些擴展(有關詳細信息,請參見bash POSIX模式的描述);因此必須指定#!/bin/bash才能獲得bash的全部好處。

在OS X上,/bin/bash也可用,而/bin/shbash。指定#!/bin/bash在那裏也可以正常工作。

第三種方法

是的,OSX和Linux都將隨附/bin/bash。您應該完全安全。但是,那不是POSIX。 POSIX shell 在大多數(所有)係統上的位置為/bin/sh,這是最可移植的方法,也是唯一兼容POSIX的方法。

請注意,盡管在許多係統上/bin/sh指向bash,但在其他係統上它卻可以指向不同的 shell 。例如,這是在Debian和Ubuntu上與dash的符號鏈接。同樣,即使/bin/sh是到bash的鏈接,當它被稱為sh(來自man bash,重點是我的)時,shell的行為也會改變:

If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well. When invoked as an interac‐ tive login shell, or a non-interactive shell with the –login option, it first attempts to read and execute commands from /etc/profile and ~/.profile, in that order. The –noprofile option may be used to inhibit this behavior. When invoked as an interactive shell with the name sh, bash looks for the variable ENV, expands its value if it is
defined, and uses the expanded value as the name of a file to read and execute. Since a shell invoked as sh does not attempt to read and execute commands from any other startup files, the –rcfile option has no effect. A non-interactive shell invoked with the name sh does not attempt to read any other startup files. When invoked as sh, bash enters posix mode after the startup files are read.

參考資料

本文由Ubuntu問答整理, 博文地址: https://ubuntuqa.com/zh-tw/article/11514.html,未經允許,請勿轉載。