コンピューターでは、シェバンとは、スクリプトの先頭にある、数字記号(シャープまたはハッシュとも呼ばれる)と感嘆符(バンとも呼ばれる)の文字シーケンス#!のことです。シャープ感嘆符、シャバン[ 1 ] [ 2 ]ハッシュバン[ 3 ] [ 4 ]パウンドバン[ 5 ] [ 6 ]またはハッシュプリング[ 7 ]とも呼ばれます。
シェバンを含むテキストファイルがUnix ライクなオペレーティングシステムで実行可能ファイルとして使用されるとき、プログラム ローダー機構はファイルの先頭行の残りの部分をインタープリタ ディレクティブとして解析します。ローダーは指定されたインタープリタプログラムを実行し、スクリプトを実行しようとしたときに最初に使用されたパスを引数として渡します。これにより、プログラムはファイルを入力データとして使用できます。[ 8 ]例えば、スクリプトが path /to/script というパスで命名され、行 で始まる場合、プログラム ローダーはプログラム/bin/sh#!/bin/shを実行するように指示され、path/to/script を最初の引数として渡します。
シェバン行は通常、多くのスクリプト言語で「#」文字がコメントマーカーであるため、インタプリタによって無視されます。ハッシュマークを使用してコメントを開始しない言語インタプリタでも、その目的を認識してシェバン行を無視する場合があります。[ 9 ]
シェバン・インタープリタ・ディレクティブの形式は次のとおりです。[ 8 ]
#!インタープリタ[オプションの引数は1つだけ]
ここで、interpreter は実行可能プログラムへのパスです。 #!とinterpreterの間にスペースを入れるかどうかは任意です。interpreterの前後には、任意の数のスペースまたはタブを入れることができます。オプションの引数には、行末までの余分なスペースが含まれます。
Linuxでは、インタープリタによって指定されたファイルは、実行権限があり、かつ以下のいずれかに該当する場合に実行できます。
Linux およびMinixでは、インタープリタはスクリプトにもなり得ます。シェバンとラッパーのチェーンによって、遭遇したスクリプトを逆順でパラメータとして受け取る直接実行可能なファイルが生成されます。たとえば、ファイル/bin/AがELF形式の実行可能ファイルで、ファイル/bin/Bにシェバンが含まれ#!/bin/A optparam、ファイル/bin/Cにシェバンが含まれている場合、ファイル/bin/C#!/bin/Bを実行すると に解決され、最終的に に解決されます。/bin/B /bin/C/bin/A optparam /bin/B /bin/C
SolarisやDarwin由来のオペレーティングシステム( macOSなど)では、インタープリタによって指定されるファイルは実行可能なバイナリである必要があり、それ自体がスクリプトであってはならない。[ 10 ]
スクリプトが明示的にインタプリタを呼び出すことによって起動された場合、その#!行は参照されません。たとえば、script.shの最初の行が の場合#!/usr/games/nibbles、 を実行しても でスクリプトを開こうとはしませんsh script.shが、を実行すると開きます。nibbles./script.sh
典型的なシェバン行の例:
#!/bin/sh– Bourneシェル、または互換性のあるシェルを使用してファイルを実行します。ファイルは/binディレクトリにあるものとします。#!/bin/bash– Bashシェルを使用してファイルを実行します#!/usr/bin/pwshPowerShellを使用してファイルを実行する#!/usr/bin/env python3–環境変数で指定されたプログラム検索パスを使用して、Pythonインタープリタで実行します。#!/bin/false– 何も実行せず、失敗を示すゼロ以外の終了ステータス.を返します。これは、sh/bash、sourcecsh/tcsh のコマンド、または .profile、.cshrc、.login ファイルなど、特定のコンテキストでの実行を意図したスクリプト ファイルの単独実行を防止するために使用されます。シェバン行には、インタプリタに渡される特定のオプションを含めることができます。ただし、オプションの解析動作は実装によって異なります。移植性を確保するため、空白文字を含めずにオプションを 1 つだけ指定する必要があります。[ 11 ]移植性に関するその他のガイドラインは以下に記載されています。
インタプリタディレクティブを使用すると、スクリプトやデータファイルをコマンドとして使用でき、コマンドラインでスクリプトの前にインタプリタを付ける必要がなくなるため、ユーザーや他のプログラムから実装の詳細を隠蔽できます。
例えば、最初の行が であるスクリプトを考えてみましょう。これは、#!/bin/sh -xのようなファイルパス[ 12 ]と、やのようなパラメータを指定するだけで簡単に呼び出すことができます。some/path/to/foobarbaz
some/path/to/foo bar baz
この場合、元のコマンドが であったかのように、パラメータ、、、 および を/bin/sh指定して が代わりに呼び出されます。-xsome/path/to/foobarbaz
/bin/sh -x some/path/to/foo bar baz
ほとんどのインタプリタは、追加の引数をスクリプトに渡せるようにします。 がPOSIX 互換シェル/bin/shの場合、と は位置パラメータ配列 としてスクリプトに渡され、 と はそれぞれパラメータ と として個別に渡されます。barbaz"$@""$1""$2"
POSIXシェル言語(および他の多くのインタプリタが理解する言語)では、先頭の「#」はコメントを導入するために使用される文字であるため、インタプリタはシェバン行全体を無視します。ただし、シェバン行を無視するかどうかはインタプリタ次第であり、すべてのインタプリタが無視するわけではありません。したがって、次の2行からなるスクリプトを実行すると、両方の行がそのまま出力されます。
#!/bin/cat こんにちは世界!
ファイル拡張子と解釈アプリケーション間のグローバル関連付けリストを使用する方法と比較すると、インタプリタディレクティブ方式では、システム全体で認識されていないインタプリタを、管理者権限なしで使用できます。また、ファイル名拡張子の名前空間(1つのファイル拡張子が複数のファイルタイプを参照する)をオーバーロードすることなく、インタプリタを個別に選択でき、他のプログラムによる呼び出し構文を変更することなく、スクリプトの実装言語を変更できます。スクリプト自体が使用するインタプリタを指定するため、スクリプトの呼び出し側は実装言語を知る必要はありません。
シェバンでは、システム実行可能ファイルへの絶対パス(または現在の作業ディレクトリからの相対パス)を指定する必要があります。これは、ファイルシステムのレイアウトが標準的でないシステムでは問題を引き起こす可能性があります。システムが比較的標準的なパスを使用している場合でも、同じオペレーティングシステムのバリアントによって、目的のインタープリタの場所が異なることは十分にあり得ます。たとえば、Python は、 /usr/bin/python3、/usr/local/bin/python3、または一般ユーザーがインストールした場合は/home/username/bin/python3のような場所に存在する可能性があります。
POSIX シェルにも同様の問題があります。POSIX では名前がshであることのみを要求し、パスは義務付けていませんでした。一般的な値は/bin/shですが、Solaris などの一部のシステムでは、POSIX 互換シェルが/usr/xpg4/bin/shにあります。[ 13 ]多くのLinuxシステムでは、/bin/shはBourne Again シェル(BASH) である/bin/bashへのハード リンクまたはシンボリック リンクです。shを指す shebang を維持しながら bash 固有の構文を使用することも移植性がありません。[ 14 ]
このため、スクリプトに記述されたパスが、過去のインタープリタ配置の慣例の一貫性によっては新しいマシンに適用されない可能性があるため、スクリプトをあるコンピュータから別のコンピュータにコピーした後、シェバン行を編集する必要がある場合があります。この理由と、POSIX がパス名を標準化していないため、POSIXはこの機能を標準化していません。[ 15 ] GNU Autoconfツールは、 マクロ AC_SYS_INTERPRETER を使用してシステムサポートをテストできます。[ 16 ]
多くの場合、 /usr/bin/envプログラムを使用して間接参照を導入することで、この制限を回避できます。例のように、 /usr/bin/envの後に、フルパスを指定せずに目的のコマンドが続きます。#!
#!/usr/bin/env sh
これは、/usr/bin/envパスがenvユーティリティによく使用され、ユーザーの$PATHで最初に見つかったsh (通常は/bin/sh)が呼び出されるため、大抵はうまくいきます。
この特定の例(shを使用)は、用途が限られています。/bin/sh も/ usr /bin/envも普遍的ではなく、どちらも存在しないデバイスが同程度存在します。さらに広く言えば、#!/usr/bin/env を任意のスクリプトに使用すると、 /bin/envしかなく/usr/bin/envがないOpenServer 5.0.6 およびUnicos 9.0.2との間で移植性の問題がいくつか発生します。
#!/usr/bin/envを使用すると、実行時間接参照が発生し、システムセキュリティが低下する可能性があります。そのため、一部の評論家はパッケージソフトウェアでの使用を推奨せず[ 17 ]、「教育的な例」にのみ使用することを推奨しています。
コマンド引数はプラットフォームによって分割方法が異なります。一部のシステムでは引数が分割されません。たとえば、最初の行でスクリプトを実行すると、
#!/usr/bin/env python3 -c
最初のスペース以降のすべてのテキストは単一の引数として扱われ、つまり、2 つの引数ではなく、 1 つの引数として/usr/bin/envpython3 -cに渡されます。このようなシステムには、Linux [ 18 ] [ 19 ]やCygwinなどがあります。
別のアプローチとしては、ラッパーの使用があります。FreeBSD 6.0 (2005) では、シェバン読み取り動作を分割しないように変更したため、env に -S オプションが導入されました。このオプションは、env に文字列自体を分割するように指示します。 [ 20 ] coreutils 8.30 ( 2018 )以降のGNU envユーティリティにもこの機能が含まれています。[ 21 ]このオプションを使用すると、カーネル側での分割による移植性の問題が軽減されますが、env がこの特定の拡張機能をサポートしているという要件が追加されます。
もう1つの問題は、Microsoft WindowsなどのDOS改行を使用するシステムで編集された結果、シェバン行の直後にキャリッジリターン文字を含むスクリプトです。一部のシステムでは、キャリッジリターン文字をインタープリタコマンドの一部として解釈し、エラーメッセージを表示します。[ 22 ]
シェバンは実際には実行可能ファイル内のマジックナンバーの人間が読めるインスタンスであり、マジックバイト列は0x23 0x21で、 #!の2 文字のASCIIエンコードです。このマジックナンバーは、ファイルがスクリプトか実行可能バイナリかを判断する「 exec 」関数ファミリーによって検出されます。シェバンが存在すると、指定された実行可能ファイル(通常はスクリプトの言語のインタプリタ)が実行されます。古いバージョンの Unix では、通常のシェバンの後にスペースとスラッシュ ( ) が続くことが想定されているという主張[ 23 ]がありますが、これは正しくないようです。[ 11 ]むしろ、シェバンの後に空白が伝統的に許可されており、以下の1980 年の歴史的な電子メールで説明されているように、スペースで文書化されることもあります。#! /
シェバン文字は、現在の Unix ライクなシステムでスクリプトやその他のテキストファイルによく使用されるUTF-8を含む拡張 ASCIIエンコーディングでは同じ 2 バイトで表されます。ただし、UTF-8 ファイルはオプションのバイトオーダーマーク(BOM) で始まる場合があります。「exec」関数がバイト0x23と0x21を明示的に検出した場合、シェバンの前に BOM ( 0xEF 0xBB 0xBF ) が存在すると、スクリプト インタプリタの実行が妨げられます。この理由と、より広範な相互運用性および哲学的懸念から、一部の専門家はPOSIX (Unix ライク) スクリプトでバイトオーダーマークを使用しないことを推奨しています[ 24 ]。さらに、UTF-8 エンコーディングにはエンディアンの問題がないため、バイトオーダーマークは UTF-8 では不要です。バイトオーダーマークは、エンコーディングが UTF-8 であることを識別するためだけに使用されます[ 24 ] 。
インタプリタ ディレクティブで始まる実行可能ファイルは、単にスクリプトと呼ばれ、多くの場合、意図するインタプリタの名前または一般的な分類が前に付けられます。特徴的な 2 文字の「shebang」という名前は、それらの 2 つの典型的な Unix 名を指すSHArp bangまたはhaSH bangの不正確な短縮形から来ている可能性があります。shebangのshに関する別の説は、通常 shebang とともに呼び出されるデフォルト シェルshに由来するというものです。[ 25 ]この使用法は 1989 年 12 月までに普及しており、[ 26 ]おそらくそれ以前から使われていました。
シェバンは、ベル研究所の第7版と第8版の間でデニス・リッチーによって導入されました。また、バークレーのコンピュータ科学研究所のBSDリリースにも追加されました(2.8BSD [ 27 ]に存在し、4.2BSDではデフォルトで有効になっています)。AT&Tベル研究所の第8版Unixとその後の版は一般に公開されなかったため、この機能が広く知られるようになったのはBSDが最初でした。
1979 年のバージョン 7 Unixのドキュメント[ 28 ]には、インタプリタ ディレクティブがないものの、シェル スクリプトのサポートがあることが明記されており、代わりに、実行権限を持つファイルはシェルによって特別に処理され、(スクリプトの最初の文字 (":" や "#" など) によっては) ファイルに含まれるコマンドを解釈して実行するサブシェルが生成されるという Bourne シェルの機能について説明されています。このモデルでは、スクリプトは Bourne シェル内から呼び出された場合にのみ他のコマンドと同様に動作します。オペレーティングシステムのexec()システム コールを使用してそのようなファイルを直接実行しようとすると失敗し、スクリプトが通常のシステム コマンドと一律に動作することを妨げます。
Unix ライクなシステムの後のバージョンでは、この矛盾は解消されました。デニス・リッチーは1980 年 1 月に、 Unix バージョン 8向けにインタプリタ ディレクティブのカーネル サポートを導入し、次のように説明しました。[ 29 ]
uucp から 1980 年 1 月 10 日木曜日 01:37:58 >dmr から 1980 年 1 月 10 日 木 4:25:49 研究から離れた場所 実行中のファイルがある場合、システムが変更されました マジック文字「#!」で始まり、行の残りの部分は自動的に解釈されます。 実行されるファイルのインタプリタの名前となる。 以前は(そして実際今でも)、砲弾がこうした役割の多くを担っていた。 実行可能モードでテキストファイル上で自動的に実行されました テキストファイル名がコマンドとして入力されたとき。 施設をシステムに組み込むと、次のようになります。 利点。 1) シェルスクリプトを実際の実行可能ファイルに近づける、 なぜなら、それらは「exec」の対象となる可能性があるからです。 2) このようなコマンドの実行中に「ps」を実行すると、 「sh」の代わりに名前が表示されます。 同様に、会計処理も実名に基づいて行われる。 3) シェルスクリプトはset-user-IDで設定できます。[ a ] 4) 代替のシェルを用意しておく方が簡単である。 例えば、バークレーのcshが好きなら、 どのシェルがファイルを解釈するか。 5)これにより、他の通訳者もよりスムーズに業務に溶け込むことができる。 この素晴らしい機会を活用するために、 置く #! /bin/sh シェルスクリプトの最初の行の左端に記述してください。 ! の後に空白があっても構いません。完全なパス名を使用してください(検索は行われません)。 現時点では行全体が16文字に制限されていますが この制限は引き上げられる予定です。
しかし、この機能の作成者はそれに名前を付けませんでした。[ 31 ]
差出人: "Ritchie, Dennis M (Dennis)** CTR **" <dmr@[redacted]> 宛先: <[redacted]@ talisman.org > 日付: 2009 年 11 月 19 日(木) 18:37:37 -0600件名: RE: #!<something>行を何と呼びますか? 正式な名前をつけた記憶がない。 かなり遅い時間に入ってしまったと思う。 UCBのカンファレンスで誰かからそのアイデアを得た。 Berkeley Unix 上で、私はおそらく最初に 実際にインストールするわけではなく、私が思いついたアイデアだった 他の場所から。 名前については、おそらく説明的なものになるでしょう。 「ハッシュバン」は特にイギリス風だが、 いずれにしても、特に愛称を使った記憶はない。 建設のために。 インタプリタディレクティブのカーネルサポートは他のバージョンのUnixにも広がり、最新の実装の1つはLinuxカーネルソースのfs/binfmt_script.cで見ることができる。[ 32 ]
このメカニズムにより、スクリプトは、通常のコンパイル済みプログラムが使用できるほぼすべてのコンテキストで使用できます。これには、完全なシステムプログラムとして、さらには他のスクリプトのインタプリタとしての使用も含まれます。ただし、注意点として、カーネルサポートの初期バージョンでは、インタプリタディレクティブの長さが約32文字(最初の実装ではわずか16文字)に制限されていたり、ディレクティブ内のパラメータからインタプリタ名を分離できなかったり、その他の不具合があったりしました。さらに、一部の最新システムでは、セキュリティ上の理由から、このメカニズム全体を制限または無効にすることができます(たとえば、多くのシステムでスクリプトのset-user-idサポートが無効になっています)。
なお、カーネルがマジックナンバー「#!」を完全にサポートしているシステムであっても、インタプリタ ディレクティブを持たないスクリプト(通常は実行権限が必要)でも、Bourneシェルの従来のスクリプト処理機能(多くの後継シェルにも依然として搭載されている)のおかげで実行できる場合があります。その場合、スクリプトはユーザーのデフォルトシェルによって解釈されます。
{{cite book}}: CS1 maint: 複数の名前: 著者リスト (リンク)可能であれば、POSIX 準拠のシェルで直接スクリプトをテストする方がはるかに良いです。`bash --posix` オプションでは不十分です。なぜなら、一部の「bash 特有の表現」がまだ許容されるからです。
シェルコマンドファイルの1行目が「#!」で始まる場合、結果は未規定です。
マクロ: AC_SYS_INTERPRETER: システムが、スクリプトに使用するインタープリタを選択するために、'#!/bin/sh' の形式の行でスクリプトを開始することをサポートしているかどうかを確認します。
# define SCRMAG '#!'