Вы можете использовать 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 новой команды. Некоторые оболочки предоставляют свои собственные непереносимые механизмы для нахождения PID подоболочки, которые вы можете использовать для этого. В частности, в Bash 4 , (echo $BASHPID; exec myCommand)
работает.
Наконец, обратите внимание, что некоторые оболочки выполняют оптимизацию, когда они запускают команду, как если бы exec
(то есть сначала отказываются от разветвления), когда известно, что оболочке не нужно будет ничего делать позже. Некоторые оболочки пытаются сделать это в любое время, когда выполняется последняя команда, в то время как другие будут делать это только тогда, когда нет других команд до или после команды, а другие вообще не будут делать это. В результате, если вы забудете написать exec
и просто использовать, sh -c 'echo $$; myCommand'
это иногда даст вам правильный PID в некоторых системах с некоторыми оболочками. Я рекомендую никогда не полагаться на такое поведение , а вместо этого всегда включать, exec
когда это то, что вам нужно.