はじめに
この記事は「シバン (shebang) を書いた方が可搬性が高いシェルスクリプトになる」のまとめです。ぶっちゃけタイトルが気に入らなくて内容も詳細すぎたので。(というか読者ターゲットが違う。)
シバンってなに?
この記事を読もうとする人がシバンを知らないとは思えませんが、スクリプト言語(シェルスクリプトに限らない)でファイルの一行目に書く #! で始まる行のことです。スクリプトに実行権限をつけてスクリプト名で実行すると、シバンで指定したコマンド(インタプリタ)上でスクリプトが実行されます。
シバンがないシェルスクリプトはどのシェルで動くか?
シバンがないシェルスクリプトを動かすシェルはシェル依存です。つまり現在使用しているシェルによってスクリプトを実行するシェルが異なります。
検証方法
シバンなしの ps とだけ書いた以下のスクリプトをいろんなシェル上で ./script で実行して ps コマンドの出力から判断しています。基本的に macOS 上で検証していますが Ubuntu 上でも同じ挙動をしているようです。
script
ps
検証結果
使用シェル
実行シェル(実行コマンド)
特殊条件下での実行シェル
dash 0.5.11.4
dash
bash 5.1.4
bash
ksh 2020
ksh
mksh R59
/bin/sh ./script
zsh 5.8
sh ./script
yash 2.51
sh - ./script (補足 A)
tcsh 6.21.00
/bin/sh ./script
/bin/tcsh ./script (補足 B)
fish 3.2.2
エラー(補足 E)
/bin/sh ./script (補足 C)
fish 3.3.0
/bin/sh ./script (補足 D)
xonsh 0.9.27
xonsh ./script
elvish 0.15.0
エラー(補足 E)
PowerShell 7.1.3
エラー(補足 E)
Nushell 0.33.0
sh -c ./script
補足
太字は POSIX シェル、それ以外は非 POSIX シェル
A: - はスクリプト名が - で始まる場合にオプションと誤認識されないようにするため
B: ファイルの一行目が # で始まる場合(ただしシバンではないこと)
C: ファイルの一行目が : で始まる場合
D: fish 3.3.0 でシバンや : がなくても動くようになった(参考)
Shebang (#!) lines are no longer required within shell scripts, improving support for scripts with concatenated binary contents. If a file fails to execute and passes a (rudimentary) binary safety check, fish will re-invoke it using /bin/sh (#7802).
E: エラーメッセージ
fish 3.2.2
Failed to execute process './script'. Reason:
exec: Exec format error
The file './script' is marked as an executable
but could not be run by the operating system.
elvish 0.15.0
Exception: fork/exec ./script: exec format error
[tty 2], line 1: ./script
PowerShell (pwsh) 7.1.3
ResourceUnavailable: Program 'script' failed to run: Exec format errorAt line:1 char:1
+ ./script
+ ~~~~~~~~.
まとめ
シバンがないスクリプトを実行した時の挙動は、現在使用しているシェルによって以下のいずれかになります。
/bin/sh で実行する
(PATH から見つかった)sh で実行する
現在実行中のシェルと同じシェルの別プロセスで実行するシェルは POSIX シェルとは限りません
実行ファイルではないというエラーになる
シェルスクリプト自体を POSIX シェル準拠で書いておけば問題になる可能性を減らすことはできますがエラーになるシェルも実際にあります。シバンを書かない方がいい理由はないのでちゃんと書いておきましょう。
例外 シバンを書かなくてもいい場合
.bashrc や .bash_profile などのシェルに読み込まれるスクリプトはシバンを書く必要はありません。これらは現在のシェルの設定を変更するものなので現在のシェルに読み込まれるのは当然だからです。シバンを書かなくていいし実行権限も付ける必要はありません。(書いてもコメントとして無視されるので実害はありません。)
↧