Как и кто определяет, что выполняется, когда Bash -like script выполняется как двоичный файл без shebang?
Я предполагаю, что работа с обычным script с shebang обрабатывается с помощью binfmt_script Модуль Linux, который проверяет shebang, анализирует командную строку и запускает назначенный интерпретатор script.
Но что происходит, когда кто-то запускает script без shebang? Я протестировал прямой подход execv
и выяснил, что там нет волшебства ядра, то есть такого файла:
$ cat target-script
echo Hello
echo "bash: $BASH_VERSION"
echo "zsh: $ZSH_VERSION"
Запуск скомпилированной C-программы, которая выполняет только вызов execv
:
$ cat test-runner.c void main() { if (execv("./target-script", 0) == -1) perror(); } $ ./test-runner ./target-script: Exec format error
Однако, если я делаю то же самое из другой оболочки script, она запускает целевой script, используя тот же интерпретатор интерпретатора оболочки, что и исходный:
$ cat test-runner.bash #!/bin/bash ./target-script $ ./test-runner.bash Hello bash: 4.1.0(1)-release zsh:
Если я делаю тот же трюк с другими оболочками (например, Debian по умолчанию sh
- /bin/dash
), он также работает:
$ cat test-runner.dash #!/bin/dash ./target-script $ ./test-runner.dash Hello bash: zsh:
Загадочно, он не работает должным образом с zsh и не следует общей схеме. Похоже, zsh выполнил /bin/sh
в таких файлах в конце концов:
[email protected] ~/z/test-runner $ cat test-runner.zsh #!/bin/zsh echo ZSH_VERSION=$ZSH_VERSION ./target-script [email protected] ~/z/test-runner $ ./test-runner.zsh ZSH_VERSION=4.3.10 Hello bash: zsh:
Обратите внимание, что ZSH_VERSION
в родительском script работал, а ZSH_VERSION
у ребенка не было!
Как оболочка (Bash, тире) определяет, что выполняется, когда нет shebang? Я попытался выкопать это место в источниках Bash/dash, но, увы, похоже, что я потерялся там. Может ли кто-нибудь пролить свет на магию, которая определяет, должен ли файл цели без shebang выполняться как script или как двоичный файл в Bash/dash? Или может быть какое-то взаимодействие с kernel/libc, и тогда я бы приветствовал объяснения того, как это работает в Linux и ядрах FreeBSD/libcs?