Выполняется ли в bash «exec echo some; echo test» и выводит ли оно «some test»?

Выполняется ли в bash «exec echo some; echo test» и выводит ли оно «some test»?

Запуск exec echo "some "; echo "test"в bash никогда не выводит сообщение «some test»?

Я хотел бы получить подтверждение этому вопросу, поскольку я пишу небольшой скрипт оболочки и хочу, чтобы он не продолжал выполнять никаких действий после execвызова команды.

Я думаю, что мне не о чем беспокоиться, поскольку, как я понял после консультации:

  • man 3 exec
  • man 1p exec

Скрипты оболочки, при выполнении их оболочкой, сделают

  1. оболочка выполняет программу exec, которая
  2. использует 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"

Связанный контент