Может кто-нибудь объяснить простыми примерами использования команды 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сопровождается перенаправлением вместо имени команды.