Ви можете використовувати sh -c
та exec
отримувати PID команди ще до її запуску.
Для початку myCommand
, щоб його PID був надрукований ще до його запуску, ви можете використовувати:
sh -c 'echo $$; exec myCommand'
Як це працює:
При цьому починається нова оболонка, друкується PID цієї оболонки, а потім використовується exec
вбудований, щоб замінити оболонку вашою командою, гарантуючи, що вона має той самий PID. Коли ваша оболонка виконує команду з exec
вбудованим, ваша оболонка фактично стає цією командою , а не звичайнішою поведінкою розгортання нової копії себе, яка має свій окремий PID і яка потім стає командою.
Я вважаю, що це набагато простіше, ніж альтернативи, пов'язані з асинхронним виконанням (з &
), контролем роботи або з пошуком ps
. Ці підходи прекрасні, але якщо у вас немає конкретної причини використовувати їх - наприклад, можливо, команда вже запущена, і в цьому випадку сенс пошуку його PID або використання управління роботою має сенс - я пропоную розглянути цей спосіб спочатку. (І я, безумовно, не вважав би можливим написати складний сценарій чи іншу програму для досягнення цього).
Ця відповідь включає приклад цієї методики.
Частини цієї команди іноді можуть бути опущені, але зазвичай.
Навіть якщо оболонка, яку ви використовуєте, є в стилі Борна і, таким чином, підтримує exec
вбудований з цією семантикою, як правило, не слід намагатися уникати використання sh -c
(або еквівалента) для створення нового, окремого процесу оболонки для цієї мети, оскільки:
- Після того, як оболонка стала
myCommand
, оболонка не чекає виконання наступних команд. sh -c 'echo $$; exec myCommand; foo
не вдалося б спробувати запустити foo
після заміни себе на myCommand
. Якщо ви не пишете сценарій, який виконує це як останню команду, ви не можете просто використовувати echo $$; exec myCommand
в оболонці, де ви виконуєте інші команди.
- Для цього не можна використовувати підзаголовок .
(echo $$; exec myCommand)
може бути синтаксично приємніше sh -c 'echo $$; exec myCommand'
, але, коли ви запускаєте $$
всередину (
)
, він дає PID батьківської оболонки, а не самої підкашлю. Але PID підрозділу буде PID нової команди. Деякі оболонки забезпечують свої власні не портативні механізми пошуку ПІД підрозділу, який ви можете використовувати для цього. Зокрема, в Bash 4 , (echo $BASHPID; exec myCommand)
працює.
Нарешті, зауважте, що деякі оболонки виконуватимуть оптимізацію, коли вони виконують команду, як якщо б exec
(тобто вони відмовилися спочатку), коли відомо, що оболонці після цього нічого не потрібно буде робити. Деякі оболонки намагаються зробити це будь-коли, коли це остання команда, яку потрібно запустити, а інші робитимуть це лише тоді, коли інших команд перед або після команди не буде, а інші взагалі не будуть виконувати це. Ефект полягає в тому, що якщо ви забудете писати exec
і просто використовувати, sh -c 'echo $$; myCommand'
то іноді це дасть вам правильний PID для деяких систем з деякими оболонками. Я рекомендую не покладатися на таку поведінку , а натомість завжди включати, exec
коли це те, що вам потрібно.