シェルスクリプトヘッダー(#!/ bin / shと#!/ bin / csh)


93

すべてのスクリプトファイルがで始まるのはなぜですか

#!/bin/sh

またはと

#!/bin/csh

それは必要ですか?これの目的は何ですか?そして、2つの違いは何ですか?


1
cshスクリプトの場合#!/bin/csh -f、;を使用する必要があります。-fユーザーのソースしていないシェルを告げる.loginと、.cshrcより高速なスクリプトの実行を行い、ユーザーの設定に依存関係を回避し、。(または、さらに良いことに、cshスクリプトを記述しないでください。)-fshまたはbashスクリプトには使用しないでください。同じ意味ではありません。
キーストンプソン

回答:


100

これはShebang:として知られています

http://en.wikipedia.org/wiki/Shebang_(Unix)

#!インタプリタ[オプション-引数]

シバンは、スクリプトに実行権限がある場合にのみ関係します(chmod u + x script.shなど)。

シェルがスクリプトを実行すると、指定されたインタープリターが使用されます。

例:

#!/bin/bash
# file: foo.sh
echo 1

$ chmod u+x foo.sh
$ ./foo.sh
  1

@Kolob Canyonは必要ありませんが、構文の強調表示で一部の編集者を支援できます(通常、同じことを実現する他の方法があります):unix.stackexchange.com/a/88730/193985
Braham Snyder

42

この#!行は、execveこのプログラムがインタープリター型言語で記述されていることをカーネル(具体的にはシステムコールの実装)に伝えます。次の絶対パス名は、インタプリタを識別します。マシンコードにコンパイルされたプログラムは、異なるバイトシーケンスで始まります。最近のほとんどのUnixでは、7f 45 4c 46^?ELF)はそれらをそのように識別します。

プログラム自体がスクリプトでない限り、の後に任意のプログラムへの絶対パスを設定できます。カーネルはの呼び出しを書き換えます#!#!

./script arg1 arg2 arg3 ...

ここ./scriptで、たとえば、#! /usr/bin/perlコマンドラインが実際に

/usr/bin/perl ./script arg1 arg2 arg3

または、これまで見てきたように、を使用#! /bin/shして、によって解釈されることを目的としたスクリプトを作成できますsh

この#!行は、(コマンドラインで)スクリプトを直接呼び出した場合にのみ処理されます./script。ファイルも実行可能である必要があります(chmod +x script)。実行する場合sh ./script、その#!行は不要であり(存在する場合は無視されます)、ファイルは実行可能である必要はありません。この機能のポイントは、インタープリター言語プログラムがどの言語で書かれているかを知らなくても、直接呼び出すことができるようにすることです(grep '^#!' /usr/bin/*実際、非常に多くのストックプログラムがこの機能を使用していることがわかります)。

この機能を使用するためのいくつかのルールは次のとおりです。

  • #!非常に最初の二つでなければならないバイトのファイルインチ 特に、ファイルASCII互換のエンコーディングである必要あり(たとえば、UTF-8は機能しますが、UTF-16は機能しません)、「バイト順マーク」で始まらないようにする必要があります。そうしないと、カーネルはファイルを#!脚本。
  • 後のパス#!は絶対パスである必要があります(で始まる/)。スペース、タブ、または改行文字を含めることはできません。
  • それは良いスタイルではなく、間にスペースを入れて、必要#!/。そこに複数のスペースを置かないでください。
  • シェル変数を#!行に配置することはできません。それらは展開されません。
  • あなたは置くことができます1つのスペースで区切ら、絶対パスの後にコマンドライン引数を。絶対パスと同様に、この引数にスペース、タブ、または改行文字を含めることはできません。これは、物事を機能させるために必要な#! /usr/bin/awk -f場合もあれば()、単に役立つ場合もあります(#! /usr/bin/perl -Tw)。残念ながら、絶対パスの後に2つ以上の引数を置くことはできません。
  • #! /usr/bin/env interpreter代わりに使用するように指示する人もいます#! /absolute/path/to/interpreterこれはほとんどの場合間違いです。これにより、プログラムの動作$PATHは、スクリプトを呼び出すユーザーの変数に依存します。そして、そもそもすべてのシステムが持っているわけではありませんenv
  • setuidまたはsetgid特権を必要とするプログラムは使用できません#!; それらはマシンコードにコンパイルする必要があります。(何であるかわからない場合setuidは、これについて心配しないでください。)

に関してはcshshNutrimat Advanced TeaSubstituteがお茶に行うのとほぼ同じです。インタラクティブな使用法shに比べて多くの利点があります(またはむしろ持っていました;現代の実装は追いついてきました)が、スクリプトにshそれ(またはその子孫tcsh)を使用することはほとんどの場合間違いです。一般的にシェルスクリプトを初めて使用する場合は、それを無視してに焦点を当てることを強くお勧めしますshcshログインシェルとして親戚を使用している場合は、bashまたはに切り替えzshて、対話型コマンド言語が学習しているスクリプト言語と同じになるようにします。


Linuxの最近のバージョンでは、指定されたインタープリターをスクリプトにすることができます。#!;の後のスペースを省略するのが一般的な方法です。それが良いスタイルかどうかについてのコメントはありません。ハックの長所と短所の議論については、この質問私の答えを参照してください#!/usr/bin/env
キーストンプソン2013年

@KeithThompson Linuxは、インタプリタをスクリプトにすることができる唯一の一般的なUnixバリアントであるという印象を受けているので、それでも信頼できるものではありません。私がこれを書いたとき、私自身が#!/usr/bin/env正しいことである状況に遭遇しました、しかしそれはほとんど常に悪い考えであるという私の意見のままです。
zwol 2013年

4

これは、スクリプトの解釈/実行に使用するシェル(コマンドインタープリター)を定義します。各シェルは、ユーザーとの対話方法やスクリプト(プログラム)の実行方法が少し異なります。

Unixプロンプトでコマンドを入力すると、シェルを操作していることになります。

たとえば、#!/bin/cshCシェル、/bin/tcshTシェル、/bin/bashbashシェルなどを指します。

使用しているインタラクティブシェルがわかります

 echo $SHELL

コマンド、または代わりに

 env | grep -i shell

コマンドを使用してコマンドシェルを変更できますchsh

それぞれにわずかに異なるコマンドセットと変数の割り当て方法、および独自のプログラミング構造のセットがあります。たとえば、bashを使用したif-elseステートメントは、Cシェルのステートメントとは異なって見えます。

このページは、bashコマンドとtcshコマンド/構文の間で「変換」されるため、興味深いかもしれません。

シェルスクリプトでディレクティブを使用すると、別のシェルを使用してプログラムを実行できます。たとえば、私はtcshシェルをインタラクティブに使用しますが、スクリプトファイルで/ bin / bashを使用してbashスクリプトを実行することがよくあります。

余談:

この概念は他のスクリプトにも適用されます。たとえば、Pythonでプログラムする場合は、

 #!/usr/bin/python

Pythonプログラムの上部に


それでそれは必要ですか?実際に使用しているシェルを知るにはどうすればよいですか?
1 2 3

したがって、誰かが自分のマシンで使用するスクリプトを書いていて、その人がどのシェルを使用しているかわからない場合。(残念ながら、この人はこのことについて無知なので、彼にできることは、何も変更せずにスクリプトを実行することだけです)。私は次のようなことをすることができます#! $SHELLか?これはShebangに正しいシェルを配置しますか?
1 2 3

1
@ OneTwoThreeほとんどのシステムには標準のシェルがあります。bashまたはcshスクリプトを記述すれば、問題ありません。彼らがインタラクティブに使用しているシェル重要ではありません。それは、例えば、!#/bin/bashディレクティブの美しさです。シェルスクリプトの実行に使用するシェルをシステムに指示します。
Levon

の値は$SHELL、現在実行しているシェルを必ずしも示しているわけではありません。通常、デフォルトのシェルが表示されます。tcshセット$version$tcsh; バッシュセット$BASH_VERSION。すべてのシェルが必ずしも同様のメカニズムを備えているわけではありません。
キーストンプソン

1
@OneTwoThree:#!行は、スクリプトを実行している人が使用する対話型シェルではなく、スクリプトの構文と一致する必要があります。
キーストンプソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.