Как получить идентификатор процесса подпроцесса bash в командной строке
Я знаю, что в bash мы можем создавать подоболочки, используя круглые скобки (
и )
. По bash странице man:
(list) list is executed in a subshell environment
Кроме того, чтобы получить текущий идентификатор процесса, мы используем:
echo $$
Теперь мой вопрос: как получить идентификатор процесса подоболочки, созданной с помощью (
и )
в командной строке?
Если я использую это:
echo $$; ( echo $$; )
Я получу идентификатор процесса родительской оболочки, дважды напечатанный на stdout, поскольку $$
расширяется даже до создания подоболочки. Итак, как реально заставить ленивую экспансию?
[Решение должно работать на Mac, а не только на Linux]
Обновление:
Рекомендуемый связанный ответ не работает, поскольку echo $BASHPID
не работает на моем Mac и возвращает пустое.
Ответы
Ответ 1
Спасибо всем вам за то, что потратили свое драгоценное время на поиск ответа на мой вопрос здесь.
Однако теперь я отвечаю на свой вопрос, так как я нашел способ взломать этот pid на bash ver < 4 (будет работать во всех версиях, хотя). Вот команда:
echo $$; ( F='/tmp/myps'; [ ! -f $F ] && echo 'echo $PPID' > $F; )
Он печатает:
5642
13715
Где 13715 - pid подоболочки. Чтобы проверить это, когда я это сделаю:
echo $$; ( F='/tmp/myps'; [ ! -f $F ] && echo 'echo $PPID' > $F; bash $F; ps; )
Я получаю это:
5642
13773
PID TT STAT TIME COMMAND
5642 s001 S 0:02.07 -bash
13773 s001 S+ 0:00.00 -bash
Рассказывая мне, что 13773 действительно является pid подоболочки.
Примечание. Я вернулся к исходному решению, так как @ChrisDodd прокомментировал, что echo $$; ( bash -c 'echo $PPID'; )
не работает Linux. Над решением моих работ работает как на Mac, так и на Linux.
Ответ 2
К сожалению, нет простого способа сделать это до bash версии 4, когда был введен $BASHPID. Одна вещь, которую вы можете сделать, это написать небольшую программу, которая печатает родительский PID:
int main()
{
printf("%d\n", getppid());
return 0;
}
Если вы скомпилируете это как ppid
и поместите его в свой путь, вы можете вызвать его, например:
$ (echo $$; ppid)
2139
29519
$ (x=$(ppid); echo $x)
29521
Одна странность, я заметил, однако, заключается в том, что если вы пишете
$ (ppid)
он, похоже, фактически не запускает его в подоболочке - вам нужно как минимум две команды в круглых скобках для bash, чтобы фактически запустить их в подоболочке.
Ответ 3
Вы можете сделать:
$ ( your_action ) &
[1] 44012
И найдите подпроцесс "PID":
$ echo "The sub PID : $!"
The Sub PID : 44012
$!
возвращает последнее задание в фоновом PID. (см. данное руководство)
Ответ 4
Кажется, что это работает:
(echo $$; echo `ps axo pid,command,args | grep "$$" |awk '{ getline;print $1}'`)
14609
17365
По какой-то причине OSX ограничен и не поставляется с pgrep, или можно было бы сделать (что работает в Linux):
(echo $$; echo `pgrep -P $$`)
14609
17390
Ответ 5
Использовать homebrew для установки pgrep на Mac: brew установить pgrep
Откроется http://mxcl.github.com/homebrew/, чтобы установить Homebrew.
Ответ 6
Вы можете использовать ppid
родительского элемента, вызывая BASHPID
родителя при первом входе в оболочку, затем вы выполняете этот процесс и можете искать pid
через ppid
, используя родительский pid
.
например. Чтобы получить pid команды sleep 555
, заложенной в подоболочку:
(echo "$BASHPID" > /tmp/_tmp_pid_ && sleep 555 &) && ps -ho pid --ppid=$(< /tmp/_tmp_pid_)