ナンモワカランアザラシ

技術的なアレコレを自分の言葉で書いて保管・公開しておくための静かなインターネット

`#!`が何をしているかstraceで探りたかった

#!は"シェバング"と読むらしい。

スクリプトの最初に示すことで、実行するインタプリタを指定できる。

例えば次の場合を考える。

#!/usr/bin/fish

echo "hello"

これをfishから実行する。

./test.sh

このとき、次の流れが行われる。

  1. スクリプトファイルtest.shが開かれる

  2. OSが先頭の#!を解釈する

  3. !で指定されたインタプリタスクリプトが実行される

せっかくなのでstraceでOSの動きを眺める。

strace ./test.sh 2>&1 | grep "read" | grep "fish" 
readlink("/proc/self/exe", "/usr/bin/fish", 4095) = 13
readlink("/usr/bin/fish", 0x7ffc244bb390, 1023) = -1 EINVAL (Invalid argument)
read(4, "# This file contains fish univer"..., 4096) = 1624
read(4, "# Main file for fish command com"..., 4096) = 4096
read(12, "pported by fish\n  set -ug FIG_CH"..., 128) = 128
read(12, "lor=%s\" \"$fish_color_autosuggest"..., 128) = 128
read(12, "g_copy_fn fish_mode_prompt fig_u"..., 128) = 128
read(12, "      function fish_right_prompt"..., 128) = 128
read(4, "# Put system-wide fish configura"..., 4096) = 425
read(4, "#!/usr/bin/fish\necho \"hello\"\n", 4096) = 29

2>&1で繋いでいるのは、straceで得られるあれこれは標準エラーに出るらしいからである。/usr/bin/fishであれこれしていそうな様子は分かるが、シェバングを読んでいる感じではなさそう?もう少しシンプルな内容で実験してみる。

#!hoge
echo "hello"

存在しないインタプリタを指定した。

strace ./test.sh                                                 
execve("./test.sh", ["./test.sh"], 0x7ffcc2c81000 /* 41 vars */) = -1 ENOENT (No such file or directory)
strace: exec: No such file or directory
+++ exited with 1 +++

hogeに関するログは出ない。

どうやら、シェバングの処理はシステムコールのトレースでは拾えないところで作業しているらしい。おそらくexecveの前段階。