web-dev-qa-db-ja.com

UbuntuとOSXの互換性と使いやすさ、POSIXには#!/ bin / shまたは#!/ bin / bashを使用してください

目的のシェルを呼び出すためのスクリプトの最初の行として、どちらかを使用できることを知っています。

#!/bin/shすべてのUNIXシステムとの互換性が絶対要件である場合に推奨されますか?

私の場合、私が気にする唯一のOSはUbuntu(Debian)とOSXです。それを踏まえて、#!/bin/bashそして、それが両方のシステムで機能することを確信していますか?
これにより、コマンドの構文がよりモダンで明確なスクリプトを使用しやすくなりますか? #!/bin/shはまた、POSIXの使用に関連していますか?

18
Michael Durrant

手始めに、Bashがプレインストールされていると想定できる場合(これは、私の知る限り、リストしたすべてのシステムに当てはまります)、互換性を保つために次のハッシュバングを使用します。

_#!/usr/bin/env bash
_

これは、_/bin_であるか_/usr/local/bin_であるかに関係なく、設定されているbashを呼び出します。

広範囲にわたるほとんどのシステム(AIX、Solaris、いくつかのBSDフレーバーを含む)では、bashは異なる場所に行き着きましたが、envは常に_/usr/bin/env_に行き着きました。しかし、トリックは私のものではなく、Bash Cookbookの作者によるものです。

とにかく、はい、Bashを使用すると、生活を楽にする "モダンな"機能を使用できます。

例えば、二重括弧:

_[[ -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 ...)呼び出しのネスト機能は、さまざまなサブシェルレベルで多くのものをエスケープする必要がないため、はるかに便利です。

これらは、Bashが従来の一般的なPOSIX sh構文を介して提供するいくつかのものです。

ただし、(スクリプトだけでなく)シェルの機能を強化したい場合は、zshも参照してください。

15
0xC0000022L

DebianとUbuntuでは、/bin/shはPOSIX準拠のシェルであるdashです。 #!/bin/shを指定する場合は、スクリプト内のPOSIXステートメントに限定する必要があります。 (dashbashよりも速く起動するので、スクリプトはより短い時間でジョブを実行できます。)

他の多くの(ほとんど?)Linuxシステムでは、/bin/shbashです。そのため、多くのスクリプトは、bashを使用していても、シバン行として#!/bin/shを使用して記述されています。拡張子。

bash拡張を使用する場合、すべてのシステムで最も安全な方法は#!/bin/bashを指定することです。そうすれば、bashへの依存関係を明示的に述べることができます。 Debian(Ubuntu)でこれを行うには必要です。追加のボーナスとして、/bin/shbashとして開始すると、一部の拡張機能が非アクティブになります(詳細については、 bash POSIXモードの説明 を参照してください);したがって、bashを最大限に活用するには、#!/bin/bashを指定する必要があります。

OS Xでは/bin/bashも利用可能で、/bin/shbashです。 #!/bin/bashを指定しても、そこでうまく機能します。

11
Stephen Kitt

はい、OSXとLinuxの両方に/bin/bashが付属します。あなたは完全に安全でなければなりません。ただし、これはPOSIXではではありません。 POSIXシェルは、ほとんどの(すべての)システムで/bin/shにあります。これは、最も移植性の高いアプローチであり、POSIX互換にする唯一の方法です。

多くのシステムでは/bin/shbashを指しますが、他のシステムでは異なるシェルを指す可能性があることに注意してください。たとえば、DebianやUbuntuのdashへのシンボリックリンクです。また、/bin/shbashへのリンクである場合でも、shとして呼び出されると、シェルの動作が変更されます(man bashから、私の強調):

bashがshという名前で呼び出された場合、POSIX標準にも準拠しながら、shの履歴バージョンの起動動作をできるだけ模倣しようとします。対話型ログインとして呼び出された場合シェル、または--loginオプション付きの非対話型シェルは、最初に/ etc/profileおよび〜/ .profileからコマンドをこの順序で読み取って実行しようとします。 --noprofileオプションを使用すると、この動作を禁止できます。 shという名前のインタラクティブシェルとして呼び出されると、bashは変数ENVを探し、その値を展開します。
定義され、展開された値を読み取り、実行するファイルの名前として使用します。 shとして呼び出されたシェルは、他の起動ファイルからコマンドを読み取って実行しようとしないため、-rcfileオプションは効果がありません。 shという名前で呼び出された非対話型シェルは、他の起動ファイルを読み取ろうとしません。shとして呼び出されると、bashは起動ファイルが読み取られた後にposixモードに入ります。

5
terdon

「すべてのUnixシステム」との互換性が絶対的な要件である場合-そうでない場合、なぜシェルスクリプトを記述しているのですか?-では、はい、#! /bin/shを使用する必要があります。Bashインストールは保証されていませんanywhereはもちろん、/binでも使用できます。

実際には、それよりもはるかに悪いです。 all Unixシステムへの互換性が必要な場合は、SolarisやAIXなどそれらのシェル環境を凍結 1995年頃のものを含みます。つまり、旧式のようなものを使用する必要がありますsort +N構文-そのnewerシステムが削除されました!また、シェル関数、配列、[[ ... ]]${foo#glob}、算術用の$(( ... ))がない、おそらく$( ... )スタイルのコマンド置換がない、サイズが大きく、文書化されていない上限があることも意味します入力を取得できます...

おそらくthatとの互換性をあまり気にせずに済むでしょうが、そもそもそれが問題である場合は、シェルほどひどくない言語を検討することを強くお勧めします。基本的なPerlインタプリタはmore Bashよりも利用可能である可能性があります。

2
zwol