Выполнение скрипта Bash с Shebang в Linux и BSD

Как и кто определяет, что выполняет, когда баш-подобный сценарий выполнен как двоичный без шебанга?

Я думаю, что работает Нормальный скрипт с Shebang обрабатывается с модулем модулем Linux BINFMT_Script MINUX, который проверяет командную строку Shebang, Parses и выполняет указанный переводчик сценария.

Но что происходит, когда кто-то управляет сценарием без шебанга? Я проверил прямую EXECV EXECV и выяснил, что там нет магии ядра - то есть файл, такой как файл:

$ cat target-script
echo Hello
echo "bash: $BASH_VERSION"
echo "zsh: $ZSH_VERSION"

Запуск компилированной программы C, которая делает только вызов Выход:

$ cat test-runner.c
void main() {
        if (execv("./target-script", 0) == -1)
                perror();
}
$ ./test-runner
./target-script: Exec format error

Однако, если я делаю то же самое из другого скрипта Shell, он запускает целевой скрипт, используя тот же интерпретатор оболочки, что и оригинальный:

$ cat test-runner.bash
#!/bin/bash
./target-script

$ ./test-runner.bash 
Hello
bash: 4.1.0(1)-release
zsh: 

, если я делаю ту же трюку с другими оболочками (например, Debian's По умолчанию SH - / Bin / Dash ), он также работает:

$ cat test-runner.dash   
#!/bin/dash
./target-script

$ ./test-runner.dash 
Hello
bash: 
zsh: 

загадочно, он не совсем не работает, как ожидается с ZSH и не следит за общей схемой. Похоже, что ZSH выполнен / bin / sh на таких файлах в конце концов:

greycat@burrow-debian ~/z/test-runner $ cat test-runner.zsh 
#!/bin/zsh
echo ZSH_VERSION=$ZSH_VERSION
./target-script

greycat@burrow-debian ~/z/test-runner $ ./test-runner.zsh 
ZSH_VERSION=4.3.10
Hello
bash: 
zsh: 

Обратите внимание, что ZSH_Version в родительском скрипте работал, а ZSH_Version у ребенка не !

Как раковина (Bash, Dash) определяет, что выполняется, когда нет шебанга? Я пытался выкопать это место в источниках Bash / Dash, но, увы, похоже, я вроде потерял там. Может ли кто-нибудь пролить свет на магии, который определяет, должен ли целевой файл без Shebang должен быть выполнен как скрипт или как бинарный в Bash / Dash? Или может быть там Некоторые взаимодействия с ядром / LIBC, а затем я приветствую объяснения о том, как он работает в ядер Linux и FreeBSD / Libcs?

17
задан Craig M. Brandenburg 10 November 2015 в 00:59
поделиться

2 ответа

Так как это происходит в тире, а тире проще, я сначала посмотрел там.

Похоже, exec.c - это место для поиска, и соответствующие функции - это tryexec, который вызывается из shellexec, который вызывается всякий раз, когда оболочка создает команду, которую необходимо выполнить. И (упрощенная версия) функции tryexec выглядит следующим образом:

STATIC void
tryexec(char *cmd, char **argv, char **envp)
{
        char *const path_bshell = _PATH_BSHELL;

repeat:

        execve(cmd, argv, envp);

        if (cmd != path_bshell && errno == ENOEXEC) {
                *argv-- = cmd;
                *argv = cmd = path_bshell;
                goto repeat;
        }
}

Таким образом, она просто всегда заменяет команду для выполнения на путь к себе (_PATH_BSHELL по умолчанию "/bin/sh"), если ENOEXEC происходит. Здесь действительно нет магии.

Я считаю, что FreeBSD демонстрирует идентичное поведение в bash и в своем собственном sh.

Способ bash обрабатывает это похоже, но гораздо сложнее. Если вы хотите посмотреть дальше, я рекомендую прочитать bash execute_command.c и обратить особое внимание на execute_shell_script, а затем shell_execve. Комментарии довольно описательны.

16
ответ дан 30 November 2019 в 13:11
поделиться

(Похоже, что Сорпигал уже рассмотрел это, но я уже напечатал это, и это может быть интересно.)

Согласно Разделу 3.16 Unix FAQ , оболочка сначала смотрит на магическое число (первые два байта файла). Некоторые числа указывают двоичный исполняемый файл; #! указывает, что остальная часть строки должна интерпретироваться как шебанг. В противном случае оболочка пытается запустить его как скрипт оболочки.

Кроме того, кажется, что csh смотрит на первый байт, и если он #, он попытается запустить его как csh скрипт.

9
ответ дан 30 November 2019 в 13:11
поделиться