Запуск exec echo "some "; echo "test"
в bash никогда не выводит сообщение «some test»?
Я хотел бы получить подтверждение этому вопросу, поскольку я пишу небольшой скрипт оболочки и хочу, чтобы он не продолжал выполнять никаких действий после exec
вызова команды.
Я думаю, что мне не о чем беспокоиться, поскольку, как я понял после консультации:
man 3 exec
man 1p exec
Скрипты оболочки, при выполнении их оболочкой, сделают
- оболочка выполняет программу
exec
, которая - использует
exec***
системные вызовы семейства, которые заменяют оболочку/bash, которая выполняла скрипт, этимпрепятствующийдальнейшие действия оболочки (которая была «заменена»)
Как уже говорилось ранее, главная цель этого вопроса — найти подтверждение моим доводам о том, что необходимо предотвратить echo test
выполнение чего-либо в скрипте, происходящего после exec (например, ).
Я был бы признателен за общий ответ (POSIX), насколько это возможно, но на всякий случай, если возникнут подробности, меня больше всего интересуют GNU/Linux и GNU/Bash.
решение1
Правильно, если exec
все успешно, то текущая оболочка заменяется, поэтому следующие команды, err.. не выполняются.
Однако,по крайней мере в Баше, оболочка также выходит, еслиexec
терпит неудачу:
exec [-cl] [-a name] [command [arguments]]
Есликомандапоставляется, он заменяет оболочку, не создавая новый процесс. [...] Есликомандане может быть выполнен по какой-то причине, неинтерактивная оболочка завершает работу, если только
execfail
опция оболочки не включена. В этом случае возвращается ошибка.
Так что даже что-то вроде bash -c 'exec /bin/nosuchfile; echo foo'
просто выведет сообщение об ошибке об отсутствующем файле программы. Чтобы обработать ошибку в скрипте, вам понадобится что-то вроде
#!/bin/bash
shopt -s execfail
exec /someprogram
echo whoops, it failed
Но вы все равно получаете сообщение об ошибке от exec
. Если вы установите перенаправление на exec
,он остается в силеесли скрипт продолжит работу после exec
сбоя.
решение2
Встроенная функция exec
(с аргументом команды¹) заменяет процесс оболочки². Никакой последующий код в процессе оболочки не выполняется.
Таким образом, единственный способ exec echo "some "; echo "test"
распечатать some text
— это если бы была вызванная echo
в PATH исполняемая команда, и эта исполняемая команда распечатала бы some text
вместо some
. Это не может произойти в обычных обстоятельствах, когда echo
исполняемый файл ведет себя так, как можно было бы ожидать от команды, вызванной echo
.
echo
Если в PATH нет исполняемого файла или его выполнение не удается, то exec
выводится сообщение об ошибке и происходит выход из оболочки. Даже в этом случае echo "test"
не выполняется.
¹ без аргумента команды — это другой зверь. Он не заменяет процесс оболочки, а просто применяет перенаправления.
² В подоболочке затрагивается только подоболочка, родительская оболочка продолжает работать нормально. exec
решение3
exec
всегда заканчивает сценарийеслион выполняет команду и делает это успешно (это связано не с кодом завершения команды, а с ее запуском).
exec
можно запустить без команды очень полезным способом: для постоянного перенаправления файловых дескрипторов:
exec 3>/path/to/file
Если команду запустить не удается, то поведение оболочки зависит от конфигурации. bash
По умолчанию происходит выход.
Возможно, вам будет лучше использовать функцию:
safe_exec () {
cmd="$1"
if test -z "$cmd" || ! test -f "$cmd" || ! test -x "$cmd"; then
exit 1
else
exec "$@"
fi
}
safe_exec echo "some "; echo "test"