Может кто-нибудь объяснить простыми примерами использования команды exec в сценариях оболочки?
Может кто-нибудь объяснить простыми примерами использования команды exec в сценариях оболочки?
Ответы:
На 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
, например:
read <&3
echo stuff >&4
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 -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
сопровождается перенаправлением вместо имени команды.