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

174

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

  • 0
    linux.about.com/od/commands/l/blcmdln_exec.htm это даст вам лучшее понимание
  • 27
    Ссылки на linux.about.com не являются полезными. Они не дают удаленного понимания того, как выполнение команды или конвейера команд с использованием 'exec' отличается от обычного их выполнения. Отсюда вопрос ОП "в чем польза exec"?
Показать ещё 1 комментарий
Теги:
exec

2 ответа

213
Лучший ответ

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

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

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

     exec appln-program
    

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

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

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

Вы, очевидно, видели 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"

Можно использовать несколько способов: ksh использовать read -u или print -u, на bash, например:

read <&3
echo stuff >&4
  • 17
    есть еще одно использование, которое я нашел довольно удобным и стоит упомянуть здесь, потому что оно относится к веб-приложениям на python и кажется чем-то промежуточным между вашими (удивительными) ответами 2 и 3. Обычно я запускаю веб-приложения wsgi (скажем, django или flask) через супервизор, вызывающий gunicorn app: последний, как известно, требует довольно много переменных окружения, он намного проще и удобнее в обслуживании, запускает gunicorn из сценария оболочки, который все настраивает и в итоге exec gunicorn правильный pid супервизору.
  • 0
    В документах сказано, что exec может использоваться для перенаправления:> Если команда не указана, любые перенаправления вступают в силу в текущей оболочке, а статус возврата равен 0. Если есть ошибка перенаправления, возвращаемый статус равен 1. Но как exec действительно работает, чтобы изменить дескриптор файла? Почему именно эта команда выбрана для этой задачи? (Markdown терпит неудачу прямо сейчас?)
Показать ещё 8 комментариев
19

Чтобы увеличить принятый ответ с кратким кратким ответом на новичок, вам, вероятно, не нужно 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 запускать его как дочерний процесс и подождите, а затем выйдите, как только закончите.

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

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

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

  • 0
    Спасибо tripleee за отличный ответ и голосование. Хотите знать, как можно выполнить два способа: (1) bash -c "<command>" , (2) bash -c "exec <command>" , затем после выполнения я проверяю состояние возврата с помощью $? Интересно, есть ли различия? В обоих случаях $? отслеживание, если <command> прошла успешно? Или отслеживание, если сама оболочка в порядке?
  • 2
    Не поддавайтесь искушению назвать свой bush изящной скорлупы. Конечно, это относится и к bash или вообще к любой популярной оболочке Unix; хотя, как отмечает @anishsane, Bash тайно оптимизирует bash -c 'command' , фактически выполняя exec command
Показать ещё 9 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню