Каковы применения команды exec в сценариях оболочки?

250

Может кто-нибудь объяснить простыми примерами использования команды exec в сценариях оболочки?

user2400564
источник
31
Ссылки на linux.about.com не являются полезными. Они не дают удаленного понимания, как выполнение команды или конвейера команд с использованием 'exec' отличается от обычного их выполнения. Отсюда вопрос ОП "в чем польза exec"?
Джонатан Хартли
2
Stack Overflow - сайт для вопросов программирования и разработки. Этот вопрос кажется не по теме, потому что он не касается программирования или разработки. Смотрите, какие темы я могу задать здесь, в Справочном центре. Возможно, лучше спросить Super User или Unix & Linux Stack Exchange .
18-18

Ответы:

281

На execвстроенной командных зеркалах функции в ядре, есть семья из них на основе execve, которая обычно вызывается из C.

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

  1. Мы хотим, чтобы пользователь запускал определенную прикладную программу без доступа к оболочке. Мы могли бы изменить программу входа в / etc / passwd, но, возможно, мы хотим, чтобы настройки среды использовались из файлов запуска. Итак, в (скажем) .profile, последнее утверждение говорит что-то вроде:

     exec appln-program

    так что теперь нет оболочки, к которой можно вернуться. Даже в случае appln-programсбоя конечный пользователь не может попасть в оболочку, потому что ее там нет - ее execзаменили.

  2. Мы хотим использовать оболочку, отличную от оболочки в / etc / passwd. Как ни странно, некоторые сайты не позволяют пользователям изменять свою оболочку входа. На одном сайте, который я знаю, все начинали с каждого csh, и каждый просто помещал в свой .login(файл запуска csh) вызов ksh. Несмотря на то, что это сработало, он оставил cshзапущенный процесс запущенным, и выход из системы состоял из двух этапов, которые могли запутать. Поэтому мы изменили его на тот, exec kshкоторый просто заменил программу c-shell на оболочку korn, и упростил все (с этим связаны и другие проблемы, такие как тот факт, что kshэто не оболочка входа в систему).

  3. Просто чтобы сохранить процессы. Если мы звоним prog1 -> prog2 -> prog3 -> prog4и т. Д. И никогда не возвращаемся, то сделайте каждый звонок исполнительным Это экономит ресурсы (правда, не так много, если не повторяется) и упрощает отключение.

Вы, очевидно, видели execгде-то использованное, возможно, если бы вы показали код, который вас глючит, мы могли бы оправдать его использование.

Изменить : я понял, что мой ответ выше, является неполным. Существует два варианта использования execв оболочках, таких как kshи bash- для открытия файловых дескрипторов. Вот некоторые примеры:

exec 3< thisfile          # open "thisfile" for reading on file descriptor 3
exec 4> thatfile          # open "thatfile" for writing on file descriptor 4
exec 8<> tother           # open "tother" for reading and writing on fd 8
exec 6>> other            # open "other" for appending on file descriptor 6
exec 5<&0                 # copy read file descriptor 0 onto file descriptor 5
exec 7>&4                 # copy write file descriptor 4 onto 7
exec 3<&-                 # close the read file descriptor 3
exec 6>&-                 # close the write file descriptor 6

Обратите внимание, что расстояние очень важно здесь. Если вы поместите пробел между номером fd и символом перенаправления, то execвернетесь к первоначальному значению:

  exec 3 < thisfile       # oops, overwrite the current program with command "3"

Есть несколько способов , которые вы можете использовать их, на КШ использовании read -uили print -u, на bash, например:

read <&3
echo stuff >&4
cdarke
источник
22
есть еще одно применение, которое я нашел довольно удобным и заслуживающим упоминания, потому что оно относится к веб-приложениям на python и кажется чем-то промежуточным между вашими (удивительными) ответами 2 и 3. Обычно я запускаю веб-приложения wsgi (например, django или flask) через супервизор, вызывающий gunicorn app: последний, как известно, требует довольно много переменных окружения, он намного проще и удобнее в обслуживании, выполняя gunicorn из сценария оболочки, который все настраивает и в итоге exec gunicornвозвращает правильный pid супервизору.
Гру
1
Документы действительно говорят , что execможет быть использованы для перенаправления:> Если команда не указана, все переназначения вступают в силу в текущей оболочке, и возвращается статус 0. Если есть ошибка перенаправления, возвращается статус 1. Но как делает execна самом деле работать, чтобы изменить дескриптор файла? Почему именно эта команда выбрана для этой задачи? (Markdown терпит неудачу прямо сейчас?)
Ray
@Ray: лучше всего я могу это сделать: pubs.opengroup.org/onlinepubs/009604599/utilities/exec.html . Если вам нужно знать, как это сделать, посмотрите на исходный код оболочки.
cdarke
7
Другое использование: Перенаправить весь вывод скрипта в лог-файлexec >.\logfilename.log 2>&1
Hogan
1
@Carmageddon: &>это bashрасширение (см. man bash), И ваш пример эквивалентен exec >/var/log/userdata.log 2>&1. Другими словами, он перенаправляет stdout и stderr в этот файл. Следующие команды будут наследовать эти перенаправления до тех пор, пока они не будут сброшены, но они будут выполнены.
cdarke
41

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

Если вы все еще здесь, следует надеяться, что последующее обсуждение покажет, почему. Когда вы бежите, скажем,

sh -c 'command'

вы запускаете shэкземпляр, а затем начинаете commandкак потомок этого shэкземпляра. Когда commandзаканчивается, shэкземпляр также заканчивается.

sh -c 'exec command'

запускает shэкземпляр, а затем заменяет этот shэкземплярcommand двоичным файлом и запускает его вместо этого.

Конечно, оба они бесполезны в этом ограниченном контексте; ты просто хочешь

command

Есть некоторые крайние ситуации, когда вы хотите, чтобы оболочка прочитала свой файл конфигурации или как-то иначе настроила среду как подготовку к запуску command. Это практически единственная ситуация, когда exec commandэто полезно.

#!/bin/sh
ENVIRONMENT=$(some complex task)
exec command

Это делает некоторые вещи для подготовки среды, чтобы она содержала то, что нужно. Как только это будет сделано, shэкземпляр больше не нужен, и поэтому (незначительная) оптимизация заключается в том, чтобы просто заменить shэкземпляр commandпроцессом, а не shзапускать его как дочерний процесс и ждать его, а затем завершить работу, как только он завершится.

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

Если что-то заставляет вас бежать sh , но вы действительно хотите , чтобы запустить что - то еще, exec something elseэто, конечно , обходной путь , чтобы заменить нежелательную shэкземпляр (как, например , если вы действительно хотите , чтобы запустить свой собственный Spiffy goshвместо , shно у вас нет в списке в/etc/shells , так что вы можете не указывайте его в качестве оболочки входа в систему).

Второе использование execдля управления файловыми дескрипторами - это отдельная тема. Принятый ответ охватывает это хорошо; чтобы сохранить это самодостаточным, я просто обращусь к руководству для всего, что execсопровождается перенаправлением вместо имени команды.

tripleee
источник
2
Сопротивление искушению назвать свою собственную элегантную оболочку bush. Конечно, это относится bashили вообще к любой популярной оболочке Unix; хотя, как отмечает @anishsane , Bash тайно оптимизирует bash -c 'command', фактически делая exec command.
tripleee
1
Код выхода оболочки обычно является кодом выхода последней выполненной команды. Конечно, если оболочка не запускается или не выполняет команду, состояние выхода оболочки будет отражать это с подходящим кодом ошибки.
tripleee
2
@JonathanLeffler Я намеренно документирую антипаттерн, который вижу в вопросах новичка. Этот был вызван этим дубликатом, но я видел его раньше, поэтому я хотел осветить это конкретно.
tripleee
2
@JonathanLeffler Незначительная настройка формулировки; как вы думаете, этого достаточно? Спасибо за ответ.
tripleee
2
Спасибо - я добавил еще один краткий абзац об этой оптимизации. Мне не совсем понятно, есть ли у вас другие возражения или вы просто хотите объяснить вещи с другой стороны.
tripleee