web-dev-qa-db-ja.com

シバンはスクリプトを実行するシェルを決定しますか?

これはばかげた質問かもしれませんが、私はまだ尋ねます。シバンを宣言した場合

#!/bin/bash 

my_Shell_script.shの最初にあるので、常にbashを使用してこのスクリプトを呼び出す必要がありますか

[my@comp]$bash my_Shell_script.sh

または私は使用できますか?.

[my@comp]$sh my_Shell_script.sh

私のスクリプトは、シバンを使用して実行中のシェルを決定しますか? kshシェルでも同じですか? AIXを使用しています。

90
jrara

Shebang_#!_は、バイト文字列_0x23 0x21_で構成される マジックナンバー の人間が読めるインスタンスです。実行するファイルがスクリプトかバイナリかを決定する関数のexec()ファミリー。シバンが存在する場合、exec()はシバンの後に指定された実行可能ファイルを代わりに実行します。

これは、質問で与えられたbothケースで行われるように、コマンドラインでインタープリターを指定してスクリプトを呼び出す場合、exec()は、コマンドラインで指定されたインタープリターを実行します。スクリプトは確認しません。

したがって、他の人が述べたように、exec()でShebang行に指定されたインタープリターを呼び出す場合は、スクリプトに実行可能ビットを設定し、_./my_Shell_script.sh_として呼び出す必要があります。

この動作は、次のスクリプトで簡単に説明できます。

_#!/bin/ksh
readlink /proc/$$/exe
_

説明:

  • _#!/bin/ksh_は、kshをインタープリターとして定義します。

  • _$$_は、現在のプロセスのPIDを保持します。

  • _/proc/pid/exe_は、プロセスの実行可能ファイルへのシンボリックリンクです(少なくともLinuxでは、AIXでは、/ proc/$$/object/a.outは実行可能ファイルへのリンクです)。

  • readlinkは、シンボリックリンクの値を出力します。

例:

:Ubuntuでこれをデモンストレーションしています。デフォルトのシェル_/bin/sh_は、へのシンボリックリンクです。 dashie _/bin/dash_および_/bin/ksh_は_/etc/alternatives/ksh_へのシンボリックリンクであり、_/bin/pdksh_へのシンボリックリンクです。

_$ chmod +x getshell.sh
$ ./getshell.sh 
/bin/pdksh
$ bash getshell.sh 
/bin/bash
$ sh getshell.sh 
/bin/dash
_
123
Thomas Nyman

はい、そうです。ちなみにそれはばかげた質問ではありません。私の回答のリファレンスは here です。 #でスクリプトを開始する

  • それはシバンまたは「バング」ラインと呼ばれています。

  • これは、Bashインタープリターへの絶対パスにすぎません。

  • 番号記号と感嘆符文字(#!)で構成され、その後に/ bin/bashなどのインタープリターへの絶対パスが続きます。

    Linuxでのすべてのスクリプトは、最初の行で指定されたインタープリターを使用して実行されます。ほとんどすべてのbashスクリプトは、多くの場合#!/ bin/bashで始まります(Bashが/ binにインストールされていると想定)。これにより、Bashを使用してスクリプトが解釈されます。別のシェルで実行された場合。 Shebangは、Bell LaboratoriesのVersion 7 Unixと8の間でDennis Ritchieによって紹介されました。その後、バークレーのBSDラインにも追加されました。

通訳ラインを無視する(Shebang)

インタープリター行を指定しない場合、デフォルトは通常/ bin/shです。ただし、#!/ bin/bash行を設定することをお勧めします。

9
vfbsilva

Linuxカーネルのexecシステムコールはシバン(#!)をネイティブに理解します

Bashを行う場合:

./something

linuxでは、これはexecシステムコールをパス./somethingで呼び出します。

カーネルのこの行は、execに渡されたファイルで呼び出されます: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25 =

if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))

ファイルの最初のバイトを読み取り、それらを#!と比較します。

比較が真の場合、行の残りの部分はLinuxカーネルによって解析され、最初の引数としてパス/usr/bin/env pythonと現在のファイルを使用して別のexec呼び出しが行われます。

/usr/bin/env python /path/to/script.py

これは、#をコメント文字として使用するすべてのスクリプト言語で機能します。

そして、はい、あなたは無限ループを作ることができます:

printf '#!/a\n' | Sudo tee /a
Sudo chmod +x /a
/a

Bashはエラーを認識します。

-bash: /a: /a: bad interpreter: Too many levels of symbolic links

#!はたまたま人間が読める形式ですが、必須ではありません。

ファイルが異なるバイトで始まった場合、execシステムコールは異なるハンドラーを使用します。他の最も重要な組み込みハンドラーはELF実行可能ファイル用です: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305 これはバイトをチェックします7f 45 4c 46(これは.ELFでも人間が読める形式です)。 ELF実行可能ファイルである/bin/lsの最初の4バイトを読み取ることで確認します。

head -c 4 "$(which ls)" | hd 

出力:

00000000  7f 45 4c 46                                       |.ELF|
00000004                                                                 

カーネルがこれらのバイトを認識すると、ELFファイルを取得し、それをメモリに正しく配置して、新しいプロセスを開始します。参照: https://stackoverflow.com/questions/8352535/how-does-kernel-get-an-executable-binary-file-running-under-linux/31394861#31394861

最後に、binfmt_miscメカニズムを使用して独自のShebangハンドラーを追加できます。たとえば、 .jarファイルのカスタムハンドラ を追加できます。このメカニズムは、ファイル拡張子によってハンドラーもサポートします。別のアプリケーションは QEMUを使用して異なるアーキテクチャの実行可能ファイルを透過的に実行する です。

POSIXがシバンを指定しているとは思いませんが、 https://unix.stackexchange.com/a/346214/32558 ですが、根拠のセクションと「実行可能の場合」の形式で言及していますスクリプトはシステムによってサポートされています。何かが起こる可能性があります。」.

実際、結果的にそれをとった場合、Shebang行に記載されている実行可能ファイルは単なる実行可能ファイルです。一部のテキストインタープリターを実行可能ファイルとして使用することは理にかなっていますが、必須ではありません。明確化とデモのために、私はかなり役に立たないテストを行いました:

#!/bin/cat
useless text
more useless text
still more useless text

ファイルにtest.txtという名前を付け、実行可能ビットを設定しますchmod u+x test.txt、それを「呼び出し」:./test.txt。予想通り、ファイルの内容が出力されます。この場合、猫はシバン線を無視しません。単にすべてのラインを出力します。したがって、有用な通訳者はこのシバン行を無視できるはずです。 bash、Perl、およびPHPの場合、これは単なるコメント行です。そう、これらはシバン行を無視します。

4
Siegfried