Может ли кто-нибудь объяснить, что использует команда exec в сценариях оболочки с помощью простых примеров?
В ядре встроена функция встроенной команды 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
exec gunicorn
правильный pid супервизору.
exec
может использоваться для перенаправления:> Если команда не указана, любые перенаправления вступают в силу в текущей оболочке, а статус возврата равен 0. Если есть ошибка перенаправления, возвращаемый статус равен 1. Но как exec
действительно работает, чтобы изменить дескриптор файла? Почему именно эта команда выбрана для этой задачи? (Markdown терпит неудачу прямо сейчас?)
Чтобы увеличить принятый ответ с кратким кратким ответом на новичок, вам, вероятно, не нужно 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
следует перенаправление вместо имени команды.
bash -c "<command>"
, (2) bash -c "exec <command>"
, затем после выполнения я проверяю состояние возврата с помощью $?
Интересно, есть ли различия? В обоих случаях $?
отслеживание, если <command>
прошла успешно? Или отслеживание, если сама оболочка в порядке?
bush
изящной скорлупы. Конечно, это относится и к bash
или вообще к любой популярной оболочке Unix; хотя, как отмечает @anishsane, Bash тайно оптимизирует bash -c 'command'
, фактически выполняя exec command