Пример использования / практический пример для встроенного в Bash exec

12

Учтите это из документации встроенного в Bash exec:

exec заменяет оболочку без создания нового процесса

Пожалуйста, предоставьте пример использования / практический пример. Я не понимаю, как это имеет смысл.

Я гуглил и нашел про перенаправление ввода / вывода . Вы можете объяснить это лучше?

Иванов
источник
unix.stackexchange.com/search?q=exec+shell+-find для некоторых примеров
Стефан Шазелас

Ответы:

18

execчасто используется в сценариях оболочки, которые в основном действуют как оболочки для запуска других двоичных файлов. Например:

#!/bin/sh

if stuff;
    EXTRA_OPTIONS="-x -y -z"
else
    EXTRA_OPTIONS="-a foo"
fi

exec /usr/local/bin/the.real.binary $EXTRA_OPTIONS "$@"

так что после завершения работы оболочки «настоящий» двоичный файл вступает во владение, и больше не остается никаких следов сценария оболочки, который временно занимал тот же слот в таблице процессов. «Настоящий» двоичный файл является прямым потомком того, что его запустило вместо внука.

Вы также упоминаете перенаправление ввода / вывода в своем вопросе. Это совсем другой случай использования execи не имеет ничего общего с заменой оболочки другим процессом. Когда execне имеет аргументов, вот так:

exec 3>>/tmp/logfile

затем перенаправления ввода / вывода в командной строке вступают в силу в текущем процессе оболочки, но текущий процесс оболочки продолжает работать и переходит к следующей команде в сценарии.

Celada
источник
1
Вы можете сказать, что оба случая связаны между собой тем, что для обоих он execговорит оболочке не выполнять действие (выполнить команду или выполнить перенаправление) в дочернем процессе, но в одном и том же процессе.
Стефан Шазелас
5

Я использовал execвстроенную оболочку, чтобы получить идентификатор процесса (PID) для Java-программы. Возможно, сейчас есть способ получить PID изнутри Java, но несколько лет назад его не было. Как только у процесса есть свой собственный PID, он может записать его в файл PID (искать /var/run/имена файлов с суффиксом «.pid»), чтобы позволить управляющим программам узнать PID запущенного процесса и предотвратить второй экземпляр. того же сервера от запуска. Это работает примерно так:

exec java -cp=YourServer.jar StartClass -p $$

Код в main()методе класса StartClassобрабатывает разбор аргументов и может найти свой собственный идентификатор процесса.

Брюс Эдигер
источник
2

Для удовольствия запустите следующую программу (переведенную на выбранный язык реализации) в фоновом режиме в системе с учетом и ограничением пользовательских процессов.

while(true) fork();

Теперь, когда каждый слот в таблице процессов, который вам разрешено использовать, заполнен копиями этой запущенной программы, как вы собираетесь его убить? Для запуска kill (1) требуется еще один слот процесса, которого у вас нет. Конечно, было бы удобно, чтобы оболочка заменила себя командой kill ...

exec /bin/kill -9 -1

(Предполагается, что ваша система имеет kill (1) в / bin / kill. "Exec` which kill` -9 -1 "потенциально безопаснее.) Это отправляет SIGKILL каждому процессу, который вы можете.

(Примечание: не выходите из своей запускающей оболочки, если ограничения процесса не всегда разрешают новый вход в слот процесса для его оболочки. Это может быть немного сложнее очистить, если вы это сделаете. Я, конечно, не делал этого в начало 90-х. Нет.)

Эрик Тауэрс
источник
3
(1) Этот ответ был бы немного лучше, если бы вы фактически показали execкоманду, которая будет полезна в этой ситуации. (2) Этот ответ несколько архаичен; killкоманда была команда в Баш встроенная команда на протяжении многих лет, в основном из -за этой проблемы.
G-Man говорит: «Восстановите Монику»
@ G-Man: Вы понимаете, что ваш пункт (2) делает этот ответ точным ответом на ОП?
Эрик Тауэрс
Нет, я этого не понимаю. Пожалуйста, объясни мне это.
G-Man говорит «Восстановить Монику»
4
Я не слежу за тобой. Вопрос не требует практических примеров всех встроенных команд bash; он запрашивает примеры exec- и тот факт, что killвстроенная функция на самом деле не имеет ничего общего со execвстроенной функцией.
G-Man говорит «Восстановить Монику»
1
Я просто прочитал ваше обновление к вашему ответу. (1) Угадай что? Если таблица процессов заполнена, то подстановка команд (например, `which kill`) также не будет работать. (2) Кстати, $(…)форма рекомендуется над `…`формой. (3) Но нет ничего опасного в догадках по каталогу. Если вы случайно напечатаете exec /binn/kill, вы просто получите сообщение об ошибке, и ваша оболочка не исчезнет. (4) Но вы даже не нужно беспокоиться о том , что каталог killнаходится в.  execИспользует $PATH, так же , как обычные команды, поэтому exec kill …работает (если у вас есть /binв вашем пути поиска).
G-Man говорит: «Восстановите Монику»
1
  • Это похоже на пример Брюса о необходимости знать PID процесса:

    (cmdpid = $ BASHPID; (сон 300; kill "$ cmdpid") & exec long-running-command )

    в котором ты

    1. Запустить подоболочку (внешнюю (и )),
    2. Узнайте PID подоболочки. ( $$даст вам PID основной оболочки.)
    3. Отсоедините вложенную оболочку, которая убивает ваш процесс после истечения времени ожидания, и
    4. Запустите команду в процессе подоболочки, которую вы создали в шаге 1.

    Это будет выполняться long-running-command, но только в течение заранее определенного, ограниченного периода времени. 

  • Это немного несерьезно, но, если вы решите, что хотите быть суперпользователем (или другим пользователем) до конца сеанса входа в систему, вы можете это сделать exec su.

    На самом деле, я могу представить сценарий, где это было бы действительно полезно. Предположим, что вы вошли в удаленную систему, и по какой-то причине возникла проблема с разрывом соединения и установлением нового соединения. Например, предположим, что удаленная система имеет брандмауэр, который следует расписанию. Вам было разрешено подключиться, когда вы это сделали, и установленные подключения не закрываются, но в настоящее время новые подключения не принимаются.

    Вы сделали то, что хотели, и готовы выйти из системы. Ваш друг Боб находится в комнате с вами, и он хочет сделать некоторую работу с удаленной системой - но он не сможет подключиться. Итак, вы печатаете exec su - bobи, когда появляется запрос пароля, передаете рабочую станцию ​​ему. Теперь нет никакого процесса с вашим UID (если вы не запустили что-то в фоновом режиме), поэтому Боб не сможет возиться с вашими файлами. Он будет эффективно завладеть вашей связью (с вашего согласия и сотрудничества).

    Примечания:

    • Конечно, это не сработает, если вам не разрешено бежать su.
    • Он будет зарегистрирован, поэтому вам может понадобиться объяснить ваши мотивы кому-то. Поскольку вы обходите политику (расписание брандмауэра), у вас могут возникнуть проблемы.
    • Я не гарантирую, что это на 100% безопасно. Например, whoвероятно все равно покажет ваше имя. Вполне возможно, что некоторые (плохо написанные) программы будут использовать это, чтобы думать, что Боб - это вы, и дать ему доступ к вашим ресурсам.
    • Если система выполняет аудит, действия Боба могут проверяться под вашим именем.
G-Man говорит: «Восстанови Монику»
источник
Обратите внимание, что на практике в большинстве оболочек (a;b)уже используется то же самое, что и (a;exec b)в оболочках, которые оптимизируют разветвление для последней команды в подоболочке. Единственные исключения, кажется, bashи mksh. Использование execпомогает гарантировать это.
Стефан Шазелас