Какой интерпретатор оболочки запускает сценарий без shebang?

Чтобы сохранить вывод команды в переменной, используйте:

variable=$( commandFooBar )

Проверьте ЗДЕСЬ

17
26.06.2017, 01:11
2 ответа

Поскольку файл не относится ни к одному из типов исполняемых файлов, распознаваемых системой, и при условии, что у вас есть разрешение на выполнение этого файла, системный вызов execve()обычно завершается ошибкой сENOEXEC(не исполняемым файлом.)ошибка.

Дальнейшие действия зависят от приложения и/или библиотечной функции, используемой для выполнения команды.

Это может быть, например, оболочка, функция execlp()/ execvp()libc.

Большинство других приложений будут использовать любой из них при выполнении команды. Они будут вызывать оболочку, например, с помощью функции system("command line")libc, которая обычно вызывает shдля анализа этой командной строки (, путь которой можно определить во время компиляции (, например /bin/shvs /usr/xpg4/bin/shв Solaris ))или вызовите оболочку, хранящуюся в $SHELL, сами по себе, например viс ее командой !, или xterm -e 'command line'и многие другие команды(su user -cвызовут оболочку входа пользователя вместо $SHELL).

Как правило, -менее текстовый файл, который не начинается с #, считается сценарием sh. Однако shбудет варьироваться.

execlp()/ execvp(), при возврате execve()ENOEXECобычно вызывает sh. Для систем, которые имеют более одного sh, так как они могут соответствовать более чем одному стандарту, какой shон будет, как правило, определяется во время компиляции (приложения с использованием execvp()/ execlp()путем связывания другой блок кода, который ссылается на другой путь кsh). Например, в Solaris это будет либо/usr/xpg4/bin/sh(стандарт, POSIX sh), либо/bin/sh(оболочка Bourne (устаревшая оболочка )в Solaris 10 и старше, ksh93 в Solaris 11 ).

Когда дело доходит до оболочек, существует множество вариантов. bash, AT&T ksh, оболочка Борна обычно сама интерпретирует сценарий (в дочернем процессе, если execне используется )после имитации execve(), которая сбрасывает все неэкспортированные переменные,закрыл все закрытия -на -exec fds, удалил все пользовательские ловушки, псевдонимы, функции...(bashбудет интерпретировать скрипт в режиме sh). yashбудет выполнять сам (с shкак argv[0], поэтому в режиме sh)интерпретировать его.

Оболочки на основе

zsh, pdksh,ash-обычно вызывают sh(, путь к которым определяется во время компиляции ).

Для cshиtcshshнекоторых ранних BSD ), если первым символом файла является #, то они будут выполняться для его интерпретации, и shв противном случае. Это восходит к временам до -shebang, когда cshдействительно распознавал #как комментарии, но не оболочку Bourne, поэтому #был намеком на то, что это был скрипт csh.

fish(по крайней мере, версия 2.4.0 ), просто возвращает ошибку, если execve()сбой (он не пытается рассматривать это как сценарий ).

Некоторые оболочки (, такие как bashили AT&T ksh), сначала пытаются эвристически определить, предназначен ли файл для сценария или нет. Таким образом, вы можете обнаружить, что некоторые оболочки отказываются выполнять сценарий, если он содержит символ NUL в первых нескольких байтах.

Также обратите внимание, что если execve()не работает с ENOEXEC, но в файле есть строка shebang, некоторые оболочки пытаются интерпретировать эту строку самостоятельно.

Итак, несколько примеров:

  • Когда $SHELLравно /bin/bash, xterm -e 'myscript with args'будет интерпретироваться myscriptкак bashв режиме sh. В то время как с xterm -e myscript with argsxtermбудет использовать execvp(), поэтому сценарий будет интерпретироваться sh.
  • su -c myscriptв Solaris 10, где rootоболочка входа в систему — /bin/sh, а /bin/sh— оболочка Bourne, интерпретируется оболочкой Bourne myscript.
  • /usr/xpg4/bin/awk 'BEGIN{system("myscript")'на Solaris 10 будет интерпретироваться как/usr/xpg4/bin/sh(то же самое для/usr/xpg4/bin/env myscript).
  • find. -prune -exec myscript {} \;на Solaris 10 (с использованиемexecvp())будет интерпретироваться /bin/shдаже с /usr/xpg4/bin/find,даже в среде POSIX (ошибка соответствия ).
  • csh -c myscriptбудет интерпретирован csh, если он начинается с #, и с shв противном случае.

В общем, вы не можете быть уверены, какая оболочка будет использоваться для интерпретации этого скрипта, если вы не знаете, как и чем он будет вызываться.

В любом случае, read -p— этоbash-только синтаксис, поэтому вам нужно убедиться, что скрипт интерпретируетсяbash(и избегать вводящего в заблуждение .shрасширения ). Либо вы знаете путь к исполняемому файлу bashи используете:

#! /path/to/bash -
read -p...

Или вы можете попробовать и полагаться на $PATHпоиск bashисполняемого файла (, предполагая, что bashустановлен ), используя:

#! /usr/bin/env bash
read -p...

(envпочти повсеместно встречается в /usr/bin). Кроме того, вы можете сделать его совместимым с POSIX+Bourne, и в этом случае вы можете использовать /bin/sh. Все системы будут иметь /bin/sh. На большинстве из них он будет (по большей части )POSIX -совместимым, но вы все равно можете найти там время от времени оболочку Bourne.

#! /bin/sh -
printf >&2 'Enter a user name: '
read user
printf '%s\n' "$user"
8
27.01.2020, 19:47

Когда у вас нет#!(называемой shebang)строки, используется sh . Чтобы проверить это, вы можете запустить следующий скрипт.

ps -p $$
echo -n "The real shell is: "
realpath /proc/$$/exe

На моем компьютере я получаю

  PID TTY          TIME CMD
13718 pts/16   00:00:00 sh
The real shell is: /usr/bin/bash

даже если моя оболочка по умолчанию zsh . Он использует bash , так как на моей машине команда sh реализована с помощью bash .

3
27.01.2020, 19:47

Теги

Похожие вопросы