あなたはそれを後方に持っています。/bin/sh最近ではほとんどボーンシェルではありません。シバンを使用するときに問題が発生するのは¹です#! /bin/sh。
Bourneシェルは70年代後半に書かれたシェルで、以前のThompsonシェル(別名: sh)。80年代前半、David KornはBourneシェルのいくつかの拡張機能を作成し、いくつかのバグと設計の不便さを修正し(さらにいくつかを導入し)、Kornシェルと呼びました。
90年代前半、POSIXは言語を指定しましたsh はKornシェルのサブセットに基づいをほとんどのシステムが/bin/shKornシェルまたはその仕様に準拠したシェルに変更されました。BSDの場合/bin/sh、最初に(ライセンス上の理由でBourneシェルを使用できなくなった後)、Almquistシェル(ksh拡張機能を備えたBourneシェルのクローン)を徐々に変更し、POSIX準拠になりました。
現在、すべてのPOSIXシステムには、shほとんどの場合POSIXに準拠しているシェル(ほとんどの場合、必ずしもそうで/binはありませんが、POSIXは指定したユーティリティのパスを指定しません)があります。通常、ksh88、ksh93、pdksh、bash、ash、zsh²のいずれかに基づいていますが、BourneシェルはPOSIX準拠ではないため、Bourneシェルには基づいていません³。これらのシェル(の数bash、zsh、yashおよびいくつかのpdksh誘導体は、として呼び出されたときにPOSIX準拠モードを有効にshしています以下別段準拠)。
bash(Kornシェルに対するGNUの回答)は実際には唯一のオープンソースシェルです(他のシェルは一般的に90年代以降新しい機能を取得していないksh88に基づいているため、現在維持されていると言えます)。 POSIX準拠sh(macOS認定の一部として)。
#! /bin/sh -she-bangを使用してスクリプトを作成するときは、標準sh構文を使用する必要があります(また、移植性が必要な場合は、そのスクリプトで使用されるユーティリティの標準構文も使用する必要があります。シェルの解釈に関与するのはシェルだけではありません)スクリプト)、その後、その標準sh構文インタープリターの実装が使用されているかどうかは関係ありません(ksh、bash...)。
それらを使用しない限り、それらのシェルが標準を超える拡張機能を持っていることは問題ではありません。標準のCコードを記述し、一方のコンパイラ(などgcc)の拡張機能を使用しない限り、Cコードを記述するようなものです。コンパイラが準拠していれば、コンパイラの実装に関係なくコードをコンパイルできます。
ここで#! /bin/sh、あなたの主な問題/bin/shは、Bourneシェルが存在するシステムです。たとえば$((1+1))、$(cmd)などの標準機能をサポートしていない${var#pattern}場合、次のような回避策が必要になる場合があります。
#! /bin/sh -
if false ^ true; then
# in the Bourne shell, ^ is an alias for |, so false ^ true returns
# true in the Bourne shell and the Bourne shell only.
# Assume the system is Solaris 10 (older versions are no longer maintained)
# You would need to adapt if you need to support some other system
# where /bin/sh is the Bourne shell.
# We also need to fix $PATH as the other utilities in /bin are
# also ancient and not POSIX compatible.
PATH=`/usr/xpg6/bin/getconf PATH`${PATH:+:}$PATH || exit
export PATH
exec /usr/xpg4/bin/sh "$0" "$@"
# that should give us an environment that is mostly compliant
# to the Single UNIX Specification version 3 (POSIX.2004), the
# latest supported by Solaris 10.
fi
# rest of the script
ところで、Ubuntu /bin/shはbashデフォルトではありません。それはだdash、これらの日、NetBSDのに基づいており、シェルsh、主にそれがマルチバイト文字をサポートしていないことを除いて、POSIX準拠のAlmquistシェルに基づいて、自分自身。Ubuntuと他のDebianベースのシステムでは、から選択することができますbashし、dashために/bin/shとdpkg-reconfigure dash)4。shDebianに付属のスクリプトは、Debianポリシー標準(POSIX標準のスーパーセット)に記述されているため、両方のシェルで同じように動作するはずです。おそらく、それらはzshのshエミュレーションでも正常に動作しますbosh(おそらくそうではなく、組み込みksh93もyashありませんlocal(Debianポリシーで必要ですがPOSIXでは必要ありません))。
unix.stackexchange.comのスコープ内のすべてのシステムには、POSIXがsh どこかにあります。それらのほとんどは/bin/sh(/binディレクトリを持たない非常にまれなものを見つけるかもしれませんが、おそらくそれを気にしないでしょう)、そしてそれは一般にPOSIXですshインタープリターです(そしてまれに(代わりに(非標準)Bourneシェルです) )。
しかしsh、システム上で確実に見つけることができる唯一のシェルインタープリタ実行可能ファイルです。他のシェルについては、macOS、Cygwin、およびほとんどのGNU / Linuxディストリビューションにが確実に含まれますbash。SYSVから派生したOS(Solaris、AIX ...)には通常、ksh88、場合によってはksh93が含まれます。OpenBSD、MirOSにはpdksh派生物があります。macOSにはがありzshます。しかし、それ以外では、保証はありません。bashこれらの他のシェルがインストールされるかどうかの保証はありません/bin(通常は/usr/local/binたとえば、インストール時にBSDでられます)。そしてもちろん、インストールされるシェルのバージョンの保証はありません。
#! /path/to/executableこれは慣習ではなく、すべてのUnixライクカーネルの機能であることに注意してください(80年代初期にデニスリッチーによって導入されました)の機能であり、で始まる最初の行でインタープリターのパスを指定することで任意のファイルを実行できることに#!。任意の実行可能ファイルにすることができます。
最初の行がで始まるファイルを#! /some/file some-optional-arg実行する/some/fileとsome-optional-arg、カーネルはスクリプトのパスと元の引数を引数として実行されます。その最初の行#! /bin/echo testを作成して、何が起こっているのかを確認できます。
$ ./myscript foo
test ./myscript foo
あなたが使用する場合/bin/sh -の代わりに/bin/echo test、カーネルの実行は/bin/sh - ./myscript foo、shコンテンツに格納されたコードを解釈myscriptし、無視し、それはコメント(開始とだとして、最初の行のことを#)。
¹おそらく、/bin/shBourneシェルをベースにした私たちが遭遇する唯一のシステムは、Solaris 10です。Solarisは、後方互換性のためにBourneシェルを保持することを決めた数少ないUnixの1つです(POSIX sh言語は完全ではありませんBourneシェルとの下位互換性)および(少なくともデスクトップおよびサーバー全体の展開の場合)POSIXはsh他の場所(/usr/xpg4/bin/shksh88に基づいて)にありますが、Solaris 11では/bin/shksh93に変更されました。他のものはほとんど機能していません。
² にするために使用のMacOS / Xのが、後に変更します。POSIX 実装として使用されるのは、主な焦点ではありません。そのモードは、主にPOSIX コードを埋め込みまたは呼び出すことができるようにすることです/bin/shzshbashzshshshsourceshzshスクリプト
³最近、@ schilyはOpenSolarisシェル(BourneシェルをベースにしたSVR4シェルのベース)をPOSIX準拠にまで拡張し、呼び出されましたboshが、まだどのシステムでも使用されていることを知りません。それに加えksh88て、Bourneシェルのコードに基づく2番目のPOSIX準拠のシェルになります
4古いバージョンでは、mkshPOSIXのより多くのlkshインカネーションを使用することもできます。それは、Fordkthシェル(Bourneシェルの別の再実装)に基づくpdkshに基づくMirOS(以前のMirBSD)シェルです)