2025/11/20 05:07 #!magic, details about the shebang/hash-bang mechanism on various Unix flavours

ロボ子、今回のITニュースはshebangじゃ!Unix系のOSでスクリプトの実行方法を指定する、`#!`のことじゃぞ。

博士、`#!`ですか。スクリプトの先頭によく書かれているアレですね。でも、そんな昔からあるものなんですね。

そうなんじゃ。ベル研究所で考案されて、4.0BSDで利用可能になったのが始まりらしいぞ。当初は行の長さが16バイトとか32バイトに制限されてたらしい。

えっ、そんなに短かったんですか!引数も最初は渡せなかったんですね。

そうなんじゃ。4.2BSDでやっと引数が1つの文字列として渡せるようになったみたいじゃな。

`#!`の後に空白が必要だっていう噂、ありますよね?

ふむ。それな。実際にはそれを要求するUnixはほとんどないらしいぞ。4.1BSDのスナップショットには必須と書かれたmanpageがあったらしいが、ソースコード自体は変わってないらしい。

へー、面白いですね。

セキュリティの話も重要じゃぞ。setuid/gidビットは多くのシステムで無視されるんじゃ。SVR4と4.4BSDは、カーネルがファイル記述子をインタプリタに渡すことで競合状態を回避する仮想ファイル記述子ファイルシステムを導入したらしい。

NetBSDが最初にsetuidスクリプトを実装したんですね。

そうそう。Linux (2.6.27.9以降) とMinixは、インタプリタ自体が`#!`で始まるスクリプトであることを許可しているらしいぞ。Linuxでは最大4レベルのネストが可能じゃ。

インタプリタがインタプリタを呼ぶ、みたいな感じですか?

そういうことじゃ。引数の分割方法もシステムによって違うのが面白いところじゃな。最初の引数だけ渡したり、引数を分割したり、全部を1つの文字列として渡したり。

`#!`メカニズムでenv (1) を使ってインタプリタを起動することが多いですけど、envの場所がシステムによって違うんですよね。

そうなんじゃ。FreeBSD 4.0では引数内の`#`をコメントとして扱う機能があったけど、6.0で廃止されたらしい。MacOS X 10.3以降では`#`をコメントとして扱うぞ。

最大長も色々あるんですね。FreeBSD 6.0以降はPAGE_SIZE (4096または8192) になったんですか。

そうじゃ。POSIX.2/SUSは`#!`を拡張としてのみ言及しているらしいぞ。

もしインタプリタが見つからない場合は、ENOENTが返されるんですね。

`#!`行が長すぎると、切り捨てられたり、E2BIG/ENAMETOOLONGエラー、ENOEXECエラーが発生する可能性があるんじゃ。

色々なOSでの`#!`メカニズムの挙動をまとめた表が掲載されているんですね。最大長、引数の扱い、setuidサポートなどが違うんですね。

そうじゃ。ちなみに、`#!`には色々な名前があるんじゃ。ベル研究所では "sharp" と呼ばれてたらしいぞ。"shebang"、"hash-bang"、"pound-bang" などとも呼ばれる。

へー、知りませんでした。奥が深いですね。

じゃろ?最後に一つ。shebangの`#`って、実はハッシュタグの元祖だったりして…なーんてな!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。