Bash に似たスクリプトがシバンなしでバイナリとして実行された場合、実行する内容を誰がどのように決定するのでしょうか?
シバンで通常のスクリプトを実行することは、シバンをチェックし、コマンドラインを解析し、指定されたスクリプトインタープリターを実行するbinfmt_script Linux モジュールで処理されると思います。
しかし、誰かがシバンなしでスクリプトを実行するとどうなるでしょうか? 直接的なexecv
アプローチをテストしたところ、そこにはカーネル マジックがないことがわかりました。つまり、次のようなファイルです。
$ cat target-script
echo Hello
echo "bash: $BASH_VERSION"
echo "zsh: $ZSH_VERSION"
execv
呼び出しだけを行うコンパイル済みの C プログラムを実行すると、次の結果が得られます。
$ cat test-runner.c ボイドメイン(){ if (execv("./target-script", 0) == -1) perror(); } $ ./テストランナー ./target-script: Exec 形式エラー
ただし、別のシェル スクリプトから同じことを行うと、元のシェル インタープリターと同じシェル インタープリターを使用してターゲット スクリプトが実行されます。
$ cat test-runner.bash #!/ビン/バッシュ ./ターゲットスクリプト $ ./test-runner.bash こんにちは バッシュ: 4.1.0(1) リリース zsh:
他のシェル (たとえば、Debian のデフォルトsh
- /bin/dash
) で同じトリックを行うと、それも機能します。
$ cat test-runner.dash #!/ビン/ダッシュ ./ターゲットスクリプト $ ./test-runner.dash こんにちは バッシュ: zsh:
不思議なことに、zsh では期待どおりに動作せず、一般的なスキームに従っていません。/bin/sh
結局、そのようなファイルに対して実行された zsh のように見えます:
graycat@burrow-debian ~/z/test-runner $ cat test-runner.zsh #!/bin/zsh echo ZSH_VERSION=$ZSH_VERSION ./ターゲットスクリプト graycat@burrow-debian ~/z/test-runner $ ./test-runner.zsh ZSH_VERSION=4.3.10 こんにちは バッシュ: zsh:
ZSH_VERSION
親スクリプトでは機能しZSH_VERSION
ましたが、子スクリプトでは機能しなかったことに注意してください。
シェル(Bash、dash)は、シバンがないときに実行されるものをどのように決定しますか? 私は Bash/dash ソースでその場所を掘り下げようとしましたが、残念ながら、私はそこで迷っているようです。シバンのないターゲットファイルをスクリプトとして実行するか、Bash/dashのバイナリとして実行するかを決定する魔法に誰かが光を当てることができますか? または、カーネル/libc との何らかの相互作用があり、それが Linux および FreeBSD カーネル/libcs でどのように機能するかについての説明を歓迎しますか?