web-dev-qa-db-ja.com

Bashスクリプトでシバンを使用する必要がありますか?

私はバッシュを使用しています

$ echo $Shell
/bin/bash

約1年前から、BashスクリプトでのShebangsの使用をやめました。 #!/bin/shまたは#!/bin/bashを使用するメリットはありますか?

更新:特定の状況では、ファイルはシバンのスクリプトとしてのみ扱われます、例

$ cat foo.sh
ls

$ cat bar.sh
#!/bin/sh
ls

$ file foo.sh bar.sh
foo.sh: ASCII text
bar.sh: POSIX Shell script, ASCII text executable
35
Steven Penny

UNIXライクなシステムでは、alwaysスクリプトをShebang行で開始する必要があります。システムコールexecve(これはプログラムの開始を担当します)は、実行可能ヘッダーまたはShebang行のいずれかを持つ実行可能ファイルに依存します

FreeBSDの execveマニュアルページ から:

 The execve() system call transforms the calling process into a new
 process.  The new process is constructed from an ordinary file, whose
 name is pointed to by path, called the new process file.
 [...]

 This file is
 either an executable object file, or a file of data for an interpreter.

 [...]

 An interpreter file begins with a line of the form:

       #! interpreter [arg]

 When an interpreter file is execve'd, the system actually execve's the
 specified interpreter.  If the optional arg is specified, it becomes the
 first argument to the interpreter, and the name of the originally
 execve'd file becomes the second argument

同様に Linuxマニュアルページ から:

execve()は、ファイル名が指すプログラムを実行します。 filenameは、バイナリ実行可能ファイルか、次の形式の行で始まるスクリプトである必要があります。

#! interpreter [optional-arg]

実際、ファイルのヘッダーに適切な「マジックナンバー」がない場合(ELFヘッダーや#!など)、execveは失敗しますENOEXECエラー(FreeBSDのexecveマンページから):

[ENOEXEC]新しいプロセスファイルには適切なアクセス許可がありますが、ヘッダーに無効なマジックナンバーがあります。


ファイルに実行権限があるが、Shebang行はないがテキストファイルのように見える場合、動作は実行しているシェルによって異なります。

ほとんどのシェルは、自分自身の新しいインスタンスを開始してファイルにフィードするようです。以下を参照してください。

スクリプトがそのシェル用に実際に作成されたという保証はないので、これは機能するか、見事に失敗する可能性があります。

tcsh(1) から:

   On  systems which do not understand the `#!' script interpreter conven‐
   tion the Shell may be compiled to emulate it;  see  the  version  Shell
   variable.  If so, the Shell checks the first line of the file to see if
   it is of the form `#!interpreter arg ...'.  If it is, the Shell  starts
   interpreter  with  the  given args and feeds the file to it on standard
   input.

FreeBSDの sh(1) から:

If the program is not a normal executable file (i.e., if it
     does not begin with the “magic number” whose ASCII representation is
     “#!”, resulting in an ENOEXEC return value from execve(2)) but appears to
     be a text file, the Shell will run a new instance of sh to interpret it.

Bash(1)から:

   If this execution fails because the file is not in  executable  format,
   and  the file is not a directory, it is assumed to be a Shell script, a
   file containing Shell commands.  A subshell is spawned to  execute  it.

Bashのような非標準プログラムの場所に常に依存することはできません。いくつか例を挙げると、/usr/bin/usr/local/bin/opt/fsf/bin/opt/gnu/binでbashを目にしたことがあります。

したがって、一般的にはenvを使用することをお勧めします。

#!/usr/bin/env bash

スクリプトを移植可能にする場合は、shの代わりにbashを使用します。

#!/bin/sh

POSIXのような標準は標準ユーティリティの絶対パスを保証しないが、ほとんどのUNIXライクなシステムではsh/binおよびenv/usr/bin内)。

45
Roland Smith

スクリプトは常にシバン行で始まる必要があります。スクリプトがこれで始まらない場合、現在のシェルによって実行される可能性があります。しかし、これは、スクリプトを使用する誰かがあなたとは異なるシェルを実行している場合、スクリプトの動作が異なる可能性があることを意味します。また、プログラムから直接スクリプトを実行できないことを意味します(例:C exec()システムコール、またはfind -exec)、シェルから実行する必要があります。

13
Barmar

#!を発明したDennis M Ritchie(dmr)による 初期の説明 に興味があるかもしれません。

Uucp Thu Jan 10 01:37:58 1980から

。> dmr Thu Jan 10 04:25:49 1980から研究から離れている

システムが変更され、実行中のファイルがマジックキャラクター#!で始まるようになりました。 、行の残りの部分は、実行されたファイルのインタプリタの名前であると理解されます。以前(実際にはまだ)、シェルはこの仕事の大部分を行いました。テキストファイルの名前がコマンドとして入力されたときに、実行可能モードのテキストファイルで自動的に実行されました。施設をシステムに組み込むと、次の利点があります。

1)シェルスクリプトが「exec」の対象になる可能性があるため、シェルスクリプトが実際の実行可能ファイルのようになります。

2)このようなコマンドの実行中に「ps」を実行すると、「sh」の代わりに実際の名前が表示されます。同様に、会計は実名に基づいて行われます。

3)シェルスクリプトは、set-user-IDにできます。

4)代替シェルを使用できるようにする方が簡単です。例えばBerkeley cshが気に入った場合、どのシェルがファイルを解釈するかについての質問はありません。

5)他の通訳がよりスムーズに対応できるようになります。

この素晴らしい機会を利用するには、

   #! /bin/sh

シェルスクリプトの最初の行の左マージン。後の空白!大丈夫です。完全なパス名を使用します(検索は行われません)。現時点では、行全体が16文字に制限されていますが、この制限は引き上げられます。

お役に立てれば

3
jrjc
  • bashスクリプト、つまりbashismを含む移植性のないスクリプトを作成する場合は、正しいインタープリターが使用されていることを確認するために、#!/bin/bashシバンを引き続き使用する必要があります。 bashはPOSIXモードで実行されるため、一部のスクリプトの動作が異なる可能性があるため、Shebangを#!/bin/shに置き換えないでください。

  • portableスクリプト、つまりPOSIXユーティリティとそのサポートされているオプションのみを使用するスクリプトを作成する場合、#!/bin/shyourシステム(つまり/bin/shはPOSIXシェルです)。

  • 厳密に準拠するPOSIXスクリプトを記述して、さまざまなプラットフォームで配布し、POSIX準拠システムからのみ起動することを確認します。POSIX標準に記載されているように、おそらくShebangを削除する必要があります。

現状では、厳密に準拠するアプリケーションでは、ファイルの最初の2文字として「#!」を使用しないでください。

理論的根拠は、POSIX標準が/bin/shをPOSIX準拠のシェルにすることを義務付けていないため、シバンでそのパスを指定するポータブルな方法はありません。この3番目のケースでは、シバンレスのまだ実行可能なスクリプトを実行できないシステムで 'find -exec'構文を使用できるようにするために、findコマンド自体にインタープリターを指定するだけです。例:

find /tmp -name "*.foo" -exec sh -c 'myscript "$@"' sh {} + 

ここでは、shがパスなしで指定されているため、POSIXシェルが実行されます。

3
jlliagre

ヘッダーは、スクリプトの実行時に使用するシェルを指定するので便利です。例えば、 #!/bin/zshは、シェルをbashではなくzshに変更します。ここで、さまざまなコマンドを使用できます。

たとえば、 this page は以下を指定します。

UNIXのほとんどの商用バリアントのデフォルトのBourne Shellである#!/ bin/shを使用すると、Bash固有の機能は犠牲になりますが、スクリプトをLinux以外のマシンに移植できます...

1
pyrrhic

$ Shellと#!/ bin/bashまたは#!/ bin/shは異なります。

まず、#!/ bin/shは、ほとんどのLinuxシステムの/ bin/bashへのシンボリックリンクです(Ubuntuでは、現在は/ bin/dashです)。

しかし、/ bin/shまたは/ bin/bashのどちらから始めるかについては、次のようになります。

Bashとshは2つの異なるシェルです。基本的にbashはshであり、より多くの機能とより良い構文を備えています。ほとんどのコマンドは同じように機能しますが、異なります。

問題が発生する可能性があるため、bashスクリプトを作成している場合は、/ shではなく/ bin/bashを使用してください。

$ Shellは、現在実行中のシェルを必ずしも反映しているわけではありません。代わりに、$ Shellはユーザーの優先シェルであり、通常は/ etc/passwdに設定されているものです。ログイン後に別のシェルを起動すると、必ずしも$ Shellが現在のシェルと一致するとは限りません。

たとえば、これは私のものですが、passwdに入力したシェルに応じて、/ root:/ bin/dashまたは/ root:/ bin/shになることもあります。したがって、問題を回避するには、passwdファイルを/ bin/bashに置いておき、$ Shellと#!/ bin/bashを使用することはそれほど重要ではありません。

root@kali:~/Desktop# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash

出典: http://Shebang.brandonmintern.com/bourne-is-not-bash-or-read-echo-and-backslash/https://unix.stackexchange.com/questions/43499/difference-between-echo-Shell-and-which-bashhttp://man.cx/shhttp://man.cx/bash

0
Chirality

他の人が言ったことに加えて、Shebangは、vimなどの一部のテキストエディターで構文の強調表示を有効にします。

0
Konrad Höffner