POSIX仕様のシェルコマンド言語ページから:
シェルコマンドのファイルの最初の行が文字「#!」で始まる場合、結果は不定です。
#!
POSIXで動作が指定されていないのはなぜですか?移植性が高く、広く使用されているものが不特定の動作をすることには困惑させられます。
exec()
関数を実装するライブラリによって解釈されます。したがって、複数のシェルをチェックしても、それがどれほど移植性があるかはわかりません。
POSIX仕様のシェルコマンド言語ページから:
シェルコマンドのファイルの最初の行が文字「#!」で始まる場合、結果は不定です。
#!
POSIXで動作が指定されていないのはなぜですか?移植性が高く、広く使用されているものが不特定の動作をすることには困惑させられます。
exec()
関数を実装するライブラリによって解釈されます。したがって、複数のシェルをチェックしても、それがどれほど移植性があるかはわかりません。
回答:
主な理由は次のとおりです。
動作は実装によって大きく異なります。詳細については、https://www.in-ulm.de/~mascheck/various/shebang/を参照してください。
ただし、ほとんどのUnixライクな実装の最小サブセットを指定できるよう#! *[^ ]+( +[^ ]+)?\n
になりました。最初の単語がネイティブ実行可能ファイルへの絶対パスであるような(ポータブルなファイル名文字セットの文字のみを含む)など実行可能ファイルがsetuid / setgidである場合、動作が指定されず、動作が長すぎ、インタープリターパスまたはスクリプトパスがargv[0]
インタープリターに渡されるかどうかが実装によって定義されます。
とにかくPOSIXは実行可能ファイルのパスを指定しません。いくつかのシステムには、/bin
/にPOSIX以前のユーティリティ/usr/bin
があり、POSIXユーティリティが他のどこかにあります(Solaris 10で/bin/sh
Bourneシェルがあり、POSIX /usr/xpg4/bin
がある場合など)。ツール/bin
はまだ古代の非POSIXのものです)。一部のシステムはPOSIXシステムではありませんが、POSIXモード/エミュレーションを備えています。POSIXが必要とするのは、システムがPOSIXlyで動作する文書化された環境があることです。
たとえば、Windows + Cygwinを参照してください。実際、Windows + Cygwinでは、ネイティブWindowsアプリケーションではなく、cygwinアプリケーションによってスクリプトが呼び出されたときにシェバンが尊重されます。
したがって、POSIXがshebangメカニズムを指定したとしても、POSIX sh
/ sed
/ awk
...スクリプトの記述には使用できません(また、オプションの終わりを渡すことができないため、shebangメカニズムを使用して信頼性の高いsed
/ awk
スクリプトを記述できないことに注意してください)マーカー)。
今、それが指定されていないという事実は、あなたがそれを使用できないことを意味しません(まあ、それはあなたがそれが#!
通常のコメントであり、シバンではないことを期待するなら、あなたは最初の行を始めてはいけないと言います)が、そのPOSIXを使用しても、保証はありません。
私の経験では、shebangsを使用すると、あなたのシェルスクリプトを書くのPOSIXの方法を使用するよりも、移植の多くの保証を与える:彼女-強打オフ休暇、POSIXのにスクリプトを記述しsh
たスクリプトは、POSIXに準拠呼び出す呼び出すどんなこと構文と希望sh
している、その上に適切なツールによって適切な環境でスクリプトが呼び出されることがわかっている場合は問題ありませんが、そうでない場合は問題ありません。
あなたは次のようなことをしなければならないかもしれません:
#! /bin/sh -
if : ^ false; then : fine, POSIX system by default
else
# cover Solaris 10 or older. ": ^ false" returns false
# in the Bourne shell as ^ is an alias for | there for
# compatibility with the Thomson shell.
PATH=`getconf PATH`:$PATH; export PATH
exec /usr/xpg4/bin/sh - "$0" ${1+"$@"}
fi
# rest of script
あなたは、Windows + Cygwinのに移植できるようにしたい場合は、あなたがあなたのファイルに名前を付ける必要がありあり.bat
または.ps1
拡張とするために、いくつかの同様のトリックを使用するcmd.exe
か、powershell.exe
Cygwinを起動するにはsh
、同じファイルに。
sh
で実行されている場合、POSIXによって実行されるので、hashbang行は必要ありませんsh
。
execlp
またはexecvp
、右に使用されましたか?を使用するとexecve
、ENOEXECになりますか?
[T]この動作は、すべてのPOSIX苦情シェル間で一貫しているようです。私はここで小刻みに動く部屋の必要性を知りません。
あなたは十分に深く見ていません。
1980年代には、このメカニズムは事実上標準化されていませんでした。デニスリッチーはそれを実装しましたが、その実装は宇宙のAT&T側では一般に届きませんでした。事実上、公開されており、BSDでのみ知られていました。AT&T Unixでは利用できない実行可能シェルスクリプトを使用します。したがって、標準化することは合理的ではありませんでした。現状は、この現代のドコによって実証されています。
BSDでは、で始まるファイルを— Stephen Frede(1988)。「System XリリースYでのプログラミング」。オーストラリアUnixシステムユーザーグループニュースレター。9巻。番号4。111。#! interpreter
直接実行できますが、SysVではa.outファイルのみを直接実行できます。これはexec…()
、BSDプログラムのいずれかのルーチンのインスタンスをSysVで変更し/bin/sh
て、代わりにそのプログラムのインタープリターを(典型的に)実行する必要があることを意味します。
ここで重要な点は、シェルを見ているということです。一方、実行可能なシェルスクリプトの存在は、実際にはexec…()
関数の問題です。シェルには、実行可能なスクリプトメカニズムの前駆体が含まれていますが、今日でも一部のシェルに含まれており(また、今日exec…p()
では機能のサブセットに対して義務付けられています)、やや誤解を招きます。この点で標準が対処する必要があるのはexec…()
、解釈されたスクリプトがどのように動作するかであり、POSIXが最初に作成された時点では、ターゲットオペレーティングシステムのスペクトルの大部分でそもそも動作しませんでした。
これは、以来、標準化されていない理由を下位問題は、スクリプトインタプリタのためのマジックナンバーメカニズムは、特にとして、あるいた宇宙のAT&T側に公衆に達したとするために文書化されていたexec…()
中で、システム5のインタフェース定義、1990年代のターンで、 :
インタプリタファイルは次の形式の行で始まります—#!パス名[引数]ここで、pathnameはインタープリターのパスであり、argはオプションの引数です。ときにあなたのexec
インタプリタファイル、システムexec
の指定されたインタプリタを。
exec
。 システムVインターフェース定義。巻1. 1991。
残念ながら、今日の動作は1980年代とほぼ同じ程度に広く、標準化する真の一般的な動作はありません。一部のユニックス(たとえば、有名なHP-UXやFreeBSD)は、スクリプトのインタープリターとしてスクリプトをサポートしていません。最初の行が空白で区切られた1つ、2つ、または多くの要素のいずれであるかは、MacOS(および2005年以前のFreeBSDのバージョン)とその他の間で異なります。サポートされる最大パス長は異なります。 ␀
また、POSIXポータブルファイル名文字セット以外の文字は、先頭および末尾の空白と同様に注意が必要です。0番目、1番目、および2番目の引数が最終的にどうなるかは、システム間で大きなばらつきがあるため、注意が必要です。現在POSIXに準拠しているが非-Unixシステムはまだそのようなメカニズムをサポートしておらず、それを義務付けると、もはやPOSIX準拠ではなくなります。
script
。 NetBSDその他の情報マニュアル。2005-05-06。他の回答のいくつかで述べたように、実装はさまざまです。これにより、既存のスクリプトとの後方互換性を標準化して維持することが難しくなります。これは、最新のPOSIXシステムにも当てはまります。たとえば、Linuxはシェバン行をスペースで完全にトークン化するわけではありません。macOSでは、スクリプトインタープリターを別のスクリプトにすることはできません。
http://en.wikipedia.org/wiki/Shebang_(Unix)#Portabilityも参照してください