すべてのスクリプトファイルがで始まるのはなぜですか
#!/bin/sh
またはと
#!/bin/csh
それは必要ですか?これの目的は何ですか?そして、2つの違いは何ですか?
回答:
これは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
この#!
行は、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は機能しません)、「バイト順マーク」で始まらないようにする必要があります。そうしないと、カーネルはファイルを#!
脚本。#!
は絶対パスである必要があります(で始まる/
)。スペース、タブ、または改行文字を含めることはできません。#!
と/
。そこに複数のスペースを置かないでください。#!
行に配置することはできません。それらは展開されません。#! /usr/bin/awk -f
場合もあれば()、単に役立つ場合もあります(#! /usr/bin/perl -Tw
)。残念ながら、絶対パスの後に2つ以上の引数を置くことはできません。#! /usr/bin/env interpreter
代わりに使用するように指示する人もいます#! /absolute/path/to/interpreter
。これはほとんどの場合間違いです。これにより、プログラムの動作$PATH
は、スクリプトを呼び出すユーザーの変数に依存します。そして、そもそもすべてのシステムが持っているわけではありませんenv
。setuid
またはsetgid
特権を必要とするプログラムは使用できません#!
; それらはマシンコードにコンパイルする必要があります。(何であるかわからない場合setuid
は、これについて心配しないでください。)に関してはcsh
、sh
Nutrimat Advanced TeaSubstituteがお茶に行うのとほぼ同じです。インタラクティブな使用法sh
に比べて多くの利点があります(またはむしろ持っていました;現代の実装は追いついてきました)が、スクリプトにsh
それ(またはその子孫tcsh
)を使用することはほとんどの場合間違いです。一般的にシェルスクリプトを初めて使用する場合は、それを無視してに焦点を当てることを強くお勧めしますsh
。csh
ログインシェルとして親戚を使用している場合は、bash
またはに切り替えzsh
て、対話型コマンド言語が学習しているスクリプト言語と同じになるようにします。
#!
;の後のスペースを省略するのが一般的な方法です。それが良いスタイルかどうかについてのコメントはありません。ハックの長所と短所の議論については、この質問と私の答えを参照してください#!/usr/bin/env
。
#!/usr/bin/env
正しいことである状況に遭遇しました、しかしそれはほとんど常に悪い考えであるという私の意見のままです。
これは、スクリプトの解釈/実行に使用するシェル(コマンドインタープリター)を定義します。各シェルは、ユーザーとの対話方法やスクリプト(プログラム)の実行方法が少し異なります。
Unixプロンプトでコマンドを入力すると、シェルを操作していることになります。
たとえば、#!/bin/csh
Cシェル、/bin/tcsh
Tシェル、/bin/bash
bashシェルなどを指します。
使用しているインタラクティブシェルがわかります
echo $SHELL
コマンド、または代わりに
env | grep -i shell
コマンドを使用してコマンドシェルを変更できますchsh
。
それぞれにわずかに異なるコマンドセットと変数の割り当て方法、および独自のプログラミング構造のセットがあります。たとえば、bashを使用したif-elseステートメントは、Cシェルのステートメントとは異なって見えます。
このページは、bashコマンドとtcshコマンド/構文の間で「変換」されるため、興味深いかもしれません。
シェルスクリプトでディレクティブを使用すると、別のシェルを使用してプログラムを実行できます。たとえば、私はtcsh
シェルをインタラクティブに使用しますが、スクリプトファイルで/ bin / bashを使用してbashスクリプトを実行することがよくあります。
余談:
この概念は他のスクリプトにも適用されます。たとえば、Pythonでプログラムする場合は、
#!/usr/bin/python
Pythonプログラムの上部に
#! $SHELL
か?これはShebangに正しいシェルを配置しますか?
!#/bin/bash
ディレクティブの美しさです。シェルスクリプトの実行に使用するシェルをシステムに指示します。
$SHELL
、現在実行しているシェルを必ずしも示しているわけではありません。通常、デフォルトのシェルが表示されます。tcshセット$version
と$tcsh
; バッシュセット$BASH_VERSION
。すべてのシェルが必ずしも同様のメカニズムを備えているわけではありません。
#!
行は、スクリプトを実行している人が使用する対話型シェルではなく、スクリプトの構文と一致する必要があります。
#!/bin/csh -f
、;を使用する必要があります。-f
ユーザーのソースしていないシェルを告げる.login
と、.cshrc
より高速なスクリプトの実行を行い、ユーザーの設定に依存関係を回避し、。(または、さらに良いことに、cshスクリプトを記述しないでください。)-f
shまたはbashスクリプトには使用しないでください。同じ意味ではありません。