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

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

Ответ 1

В ядре встроена функция встроенной команды 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

Ответ 2

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