Ссылки на linux.about.com не являются полезными. Они не дают удаленного понимания, как выполнение команды или конвейера команд с использованием 'exec' отличается от обычного их выполнения. Отсюда вопрос ОП "в чем польза exec"?
Джонатан Хартли
2
Stack Overflow - сайт для вопросов программирования и разработки. Этот вопрос кажется не по теме, потому что он не касается программирования или разработки. Смотрите, какие темы я могу задать здесь, в Справочном центре. Возможно, лучше спросить Super User или Unix & Linux Stack Exchange .
18-18
Ответы:
281
На execвстроенной командных зеркалах функции в ядре, есть семья из них на основе execve, которая обычно вызывается из C.
execзаменяет текущую программу в текущем процессе без forkнового процесса. Это не то, что вы бы использовали в каждом сценарии, который вы пишете, но иногда это удобно. Вот несколько сценариев, которые я использовал;
Мы хотим, чтобы пользователь запускал определенную прикладную программу без доступа к оболочке. Мы могли бы изменить программу входа в / 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в оболочках, таких как 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, например:
есть еще одно применение, которое я нашел довольно удобным и заслуживающим упоминания, потому что оно относится к веб-приложениям на python и кажется чем-то промежуточным между вашими (удивительными) ответами 2 и 3. Обычно я запускаю веб-приложения wsgi (например, django или flask) через супервизор, вызывающий gunicorn app: последний, как известно, требует довольно много переменных окружения, он намного проще и удобнее в обслуживании, выполняя gunicorn из сценария оболочки, который все настраивает и в итоге exec gunicornвозвращает правильный pid супервизору.
Гру
1
Документы действительно говорят , что execможет быть использованы для перенаправления:> Если команда не указана, все переназначения вступают в силу в текущей оболочке, и возвращается статус 0. Если есть ошибка перенаправления, возвращается статус 1. Но как делает execна самом деле работать, чтобы изменить дескриптор файла? Почему именно эта команда выбрана для этой задачи? (Markdown терпит неудачу прямо сейчас?)
Другое использование: Перенаправить весь вывод скрипта в лог-файл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это полезно.
Это делает некоторые вещи для подготовки среды, чтобы она содержала то, что нужно. Как только это будет сделано, shэкземпляр больше не нужен, и поэтому (незначительная) оптимизация заключается в том, чтобы просто заменить shэкземпляр commandпроцессом, а не shзапускать его как дочерний процесс и ждать его, а затем завершить работу, как только он завершится.
Точно так же, если вы хотите высвободить как можно больше ресурсов для тяжелой команды в конце сценария оболочки, вы можете использовать execэту команду в качестве оптимизации.
Если что-то заставляет вас бежать sh , но вы действительно хотите , чтобы запустить что - то еще, exec something elseэто, конечно , обходной путь , чтобы заменить нежелательную shэкземпляр (как, например , если вы действительно хотите , чтобы запустить свой собственный Spiffy goshвместо , shно у вас нет в списке в/etc/shells , так что вы можете не указывайте его в качестве оболочки входа в систему).
Второе использование execдля управления файловыми дескрипторами - это отдельная тема. Принятый ответ охватывает это хорошо; чтобы сохранить это самодостаточным, я просто обращусь к руководству для всего, что execсопровождается перенаправлением вместо имени команды.
Сопротивление искушению назвать свою собственную элегантную оболочку bush. Конечно, это относится bashили вообще к любой популярной оболочке Unix; хотя, как отмечает @anishsane , Bash тайно оптимизирует bash -c 'command', фактически делая exec command.
tripleee
1
Код выхода оболочки обычно является кодом выхода последней выполненной команды. Конечно, если оболочка не запускается или не выполняет команду, состояние выхода оболочки будет отражать это с подходящим кодом ошибки.
tripleee
2
@JonathanLeffler Я намеренно документирую антипаттерн, который вижу в вопросах новичка. Этот был вызван этим дубликатом, но я видел его раньше, поэтому я хотел осветить это конкретно.
tripleee
2
@JonathanLeffler Незначительная настройка формулировки; как вы думаете, этого достаточно? Спасибо за ответ.
tripleee
2
Спасибо - я добавил еще один краткий абзац об этой оптимизации. Мне не совсем понятно, есть ли у вас другие возражения или вы просто хотите объяснить вещи с другой стороны.
Ответы:
На
exec
встроенной командных зеркалах функции в ядре, есть семья из них на основеexecve
, которая обычно вызывается из C.exec
заменяет текущую программу в текущем процессе безfork
нового процесса. Это не то, что вы бы использовали в каждом сценарии, который вы пишете, но иногда это удобно. Вот несколько сценариев, которые я использовал;Мы хотим, чтобы пользователь запускал определенную прикладную программу без доступа к оболочке. Мы могли бы изменить программу входа в / etc / passwd, но, возможно, мы хотим, чтобы настройки среды использовались из файлов запуска. Итак, в (скажем)
.profile
, последнее утверждение говорит что-то вроде:так что теперь нет оболочки, к которой можно вернуться. Даже в случае
appln-program
сбоя конечный пользователь не может попасть в оболочку, потому что ее там нет - ееexec
заменили.Мы хотим использовать оболочку, отличную от оболочки в / etc / passwd. Как ни странно, некоторые сайты не позволяют пользователям изменять свою оболочку входа. На одном сайте, который я знаю, все начинали с каждого
csh
, и каждый просто помещал в свой.login
(файл запуска csh) вызовksh
. Несмотря на то, что это сработало, он оставилcsh
запущенный процесс запущенным, и выход из системы состоял из двух этапов, которые могли запутать. Поэтому мы изменили его на тот,exec ksh
который просто заменил программу c-shell на оболочку korn, и упростил все (с этим связаны и другие проблемы, такие как тот факт, чтоksh
это не оболочка входа в систему).Просто чтобы сохранить процессы. Если мы звоним
prog1 -> prog2 -> prog3 -> prog4
и т. Д. И никогда не возвращаемся, то сделайте каждый звонок исполнительным Это экономит ресурсы (правда, не так много, если не повторяется) и упрощает отключение.Вы, очевидно, видели
exec
где-то использованное, возможно, если бы вы показали код, который вас глючит, мы могли бы оправдать его использование.Изменить : я понял, что мой ответ выше, является неполным. Существует два варианта использования
exec
в оболочках, таких какksh
иbash
- для открытия файловых дескрипторов. Вот некоторые примеры:Обратите внимание, что расстояние очень важно здесь. Если вы поместите пробел между номером fd и символом перенаправления, то
exec
вернетесь к первоначальному значению:Есть несколько способов , которые вы можете использовать их, на КШ использовании
read -u
илиprint -u
, наbash
, например:источник
exec gunicorn
возвращает правильный pid супервизору.exec
может быть использованы для перенаправления:> Если команда не указана, все переназначения вступают в силу в текущей оболочке, и возвращается статус 0. Если есть ошибка перенаправления, возвращается статус 1. Но как делаетexec
на самом деле работать, чтобы изменить дескриптор файла? Почему именно эта команда выбрана для этой задачи? (Markdown терпит неудачу прямо сейчас?)exec >.\logfilename.log 2>&1
&>
этоbash
расширение (см.man bash
), И ваш пример эквивалентенexec >/var/log/userdata.log 2>&1
. Другими словами, он перенаправляет stdout и stderr в этот файл. Следующие команды будут наследовать эти перенаправления до тех пор, пока они не будут сброшены, но они будут выполнены.Просто, чтобы дополнить принятый ответ коротким коротким ответом для новичков, вам, вероятно, не нужно
exec
.Если вы все еще здесь, следует надеяться, что последующее обсуждение покажет, почему. Когда вы бежите, скажем,
вы запускаете
sh
экземпляр, а затем начинаетеcommand
как потомок этогоsh
экземпляра. Когдаcommand
заканчивается,sh
экземпляр также заканчивается.запускает
sh
экземпляр, а затем заменяет этотsh
экземплярcommand
двоичным файлом и запускает его вместо этого.Конечно, оба они бесполезны в этом ограниченном контексте; ты просто хочешь
Есть некоторые крайние ситуации, когда вы хотите, чтобы оболочка прочитала свой файл конфигурации или как-то иначе настроила среду как подготовку к запуску
command
. Это практически единственная ситуация, когдаexec command
это полезно.Это делает некоторые вещи для подготовки среды, чтобы она содержала то, что нужно. Как только это будет сделано,
sh
экземпляр больше не нужен, и поэтому (незначительная) оптимизация заключается в том, чтобы просто заменитьsh
экземплярcommand
процессом, а неsh
запускать его как дочерний процесс и ждать его, а затем завершить работу, как только он завершится.Точно так же, если вы хотите высвободить как можно больше ресурсов для тяжелой команды в конце сценария оболочки, вы можете использовать
exec
эту команду в качестве оптимизации.Если что-то заставляет вас бежать
sh
, но вы действительно хотите , чтобы запустить что - то еще,exec something else
это, конечно , обходной путь , чтобы заменить нежелательнуюsh
экземпляр (как, например , если вы действительно хотите , чтобы запустить свой собственный Spiffygosh
вместо ,sh
но у вас нет в списке в/etc/shells
, так что вы можете не указывайте его в качестве оболочки входа в систему).Второе использование
exec
для управления файловыми дескрипторами - это отдельная тема. Принятый ответ охватывает это хорошо; чтобы сохранить это самодостаточным, я просто обращусь к руководству для всего, чтоexec
сопровождается перенаправлением вместо имени команды.источник
bush
. Конечно, это относитсяbash
или вообще к любой популярной оболочке Unix; хотя, как отмечает @anishsane , Bash тайно оптимизируетbash -c 'command'
, фактически делаяexec command
.