У чому полягає використання команди exec у скриптах оболонки?


250

Чи може хтось пояснити, якими є використання команди exec в сценарії оболонок простими прикладами?


31
Посилання на linux.about.com не є корисними. Вони не дозволяють дистанційно зрозуміти, чим виконання команди або конвеєра команд за допомогою "exec" відрізняється від того, щоб їх просто виконати нормально. Звідси виникає питання ОП "у чому полягає використання виконавця"?
Джонатан Хартлі

2
Переповнення стека - це сайт для програмування та питань розробки. Це питання видається поза темою, оскільки мова не йде про програмування чи розробку. Дивіться, які теми я можу запитати тут, у довідковому центрі. Можливо, краще користуватися питаннями Super User або Unix & Linux Stack Exchange .
jww

Відповіді:


281

На execвбудованої командних дзеркалах функції в ядрі, є сім'я з них на основі execve, яка зазвичай викликається з C.

execзамінює поточну програму в поточному процесі, не forkзастосовуючи новий процес. Це не те, що ви використовували б у кожному написаному вами сценарії, але це корисно при нагоді. Ось кілька сценаріїв, якими я користувався;

  1. Ми хочемо, щоб користувач запускав конкретну прикладну програму без доступу до оболонки. Ми могли б змінити програму входу в / etc / passwd, але, можливо, ми хочемо, щоб налаштування середовища використовувались із запуску файлів. Отже, в (скажімо) .profile, останньому твердженні сказано щось на зразок:

     exec appln-program

    тому зараз немає оболонки, до якої можна було б повернутися. Навіть якщо відбувається appln-programзбій, кінцевий користувач не може потрапити до оболонки, оскільки його там немає - execзамінив його.

  2. Ми хочемо використовувати іншу оболонку до тієї в / etc / passwd. Як не здається, деякі сайти не дозволяють користувачам змінювати оболонку входу. Один сайт, який я знаю, мав почати з усіх csh, і кожен просто вніс у свій .login(csh файл запуску) дзвінок на ksh. Поки це працювало, він покинув блукаючий cshпроцес, і вихід був два етапи, які могли заплутатися. Тож ми змінили його на те, exec kshщо просто замінили програму c-shell на оболонку korn, і зробили все простішим (з цим є інші проблеми, наприклад, те, що kshце не оболонка входу).

  3. Просто для збереження процесів. Якщо ми дзвонимо 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"

Існує кілька способів їх використання, наприклад, за допомогою ksh read -uабо print -u, bashнаприклад:

read <&3
echo stuff >&4

22
Є ще одне використання, яке я знайшов досить зручним і варто згадати тут, оскільки це стосується веб-додатків python і, здається, щось середнє між вашими (дивовижними) відповідями 2 та 3. Я зазвичай запускаю веб-додатки wsgi (скажімо, django або flask) через керівник, який викликає рушницю додаток: останній, як відомо, вимагає досить багато змінних оточуючих, це набагато простіше і більш ремонтований запуск пістолета з сценарію оболонки, який налаштовує все, і в кінцевому підсумку exec gunicornповертає правильний pid назад до супервізора.
гру

1
Документи говорять, що execїх можна використовувати для перенаправлення:> Якщо команда не вказана, будь-які перенаправлення набувають чинності в поточній оболонці, а статус повернення - 0. Якщо є помилка перенаправлення, стан повернення дорівнює 1. Але як це execнасправді працює над зміною дескриптора файлу? Чому саме для цього завдання обрана така команда? (Маркдаун зараз не вдається?)
Рей,

@Ray: найкраще я це можу: pubs.opengroup.org/onlinepubs/009604599/utilities/exec.html . Якщо вам потрібно знати, як тоді подивіться на вихідний код оболонки.
cdarke

7
Ще одне використання: перенаправлення всіх результатів сценарію на логфайл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це корисно.

#!/bin/sh
ENVIRONMENT=$(some complex task)
exec command

Це робить деякі речі, щоб підготувати навколишнє середовище, щоб воно містило те, що потрібно. Як тільки це буде зроблено, shекземпляр більше не потрібен, і тому (незначна) оптимізація просто замінить shекземпляр commandпроцесом, а не матиsh запустити його як дочірній процес і чекати його, а потім вийти, як тільки він закінчиться.

Аналогічно, якщо ви хочете звільнити якомога більше ресурсів для важкої команди в кінці сценарію оболонки, ви можете exec цією командою як оптимізацією.

Якщо щось змушує вас запустити, shале ви дійсно хотіли запустити щось інше, exec something elseзвичайно, це рішення для заміни небажаного shекземпляра (наприклад, якщо ви дійсно хотіли запустити власний спіфій goshзамість, shале ваш не вказаний у/etc/shells щоб ви могли не вказати його як свою оболонку для входу).

Друге використання для управління execдескрипторами файлів - окрема тема. Прийнята відповідь це гарно висвітлює; щоб зберегти це самостійно, я просто відкладу керівництво для будь-якого місця exec, за яким слід переспрямування замість імені команди.


2
Протистоявши спокусі викликати власну колючу оболонку bush. Звичайно, це стосується bashі будь-якої популярної оболонки Unix; хоч як зазначає @anishsane , Bash таємно оптимізує bash -c 'command', фактично роблячи exec command.
tripleee

1
Код виходу оболонки, як правило, є кодом виходу останньої виконуваної ним команди. Звичайно, якщо оболонці не вдалося запустити або виконати команду, стан виходу оболонки буде відображати це з відповідним кодом помилки.
трійка

2
@JonathanLeffler Я навмисно документую антипатерн, який я бачу в питаннях новачків. Цей запит запропонував цей дублікат, але я його бачив і раніше, тому хотів конкретно висвітлити.
tripleee

2
@JonathanLeffler Незначні формулювання формулювання; чи достатньо це, на вашу думку? Дякуємо за відгук.
трійка

2
Дякую - я додав ще один короткий параграф про цю оптимізацію. Мені не зовсім зрозуміло, чи є у вас інші заперечення чи ви просто хочете пояснити речі під іншим кутом зору.
трійчатка
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.