Как получить идентификатор процесса подпроцесса bash в командной строке - PullRequest
29 голосов
/ 03 февраля 2012

Я знаю, что в bash мы можем создавать подоболочки, используя круглые скобки ( и ).Согласно man-странице bash:

(list) list  is  executed  in  a  subshell environment 

Также для получения текущего идентификатора процесса мы используем:

echo $$

Теперь мой вопрос заключается в том, как получить идентификатор процесса изподоболочка, созданная с помощью ( и ) в командной строке?

Если я использую это:

echo $$; ( echo $$; ) 

Я получу идентификатор процесса родительской оболочки, напечатанный дважды на стандартный вывод, так как $$ расширяется даже до создания подоболочкиТак как же действительно заставить ленивое расширение?

[Решение должно работать не только на Linux, но и на Mac]

Обновление:

Предлагаемый связанный ответ не работает с echo $BASHPID не работает на моем Mac и возвращает пустое значение.

Ответы [ 6 ]

19 голосов
/ 03 февраля 2012

Спасибо всем, кто потратил ваше драгоценное время на поиск ответа на мой вопрос здесь.

Однако сейчас я отвечаю на свой вопрос, поскольку нашел взломать способполучите этот pid на bash ver <4 (хотя будет работать на всех версиях).Вот команда: </p>

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 действительно является пидом подоболочки.Примечание: Я вернулся к своему исходному решению, поскольку, как заметил @ChrisDodd, echo $$; ( bash -c 'echo $PPID'; ) не работает в Linux.Вышеупомянутое решение работает как на Mac, так и на Linux.

7 голосов
/ 03 февраля 2012

К сожалению, до bash версии 4, когда был представлен $ BASHPID, не было простого способа сделать это.Одна вещь, которую вы можете сделать, это написать крошечную программу, которая печатает родительский PID:

int main()
{
    printf("%d\n", getppid());
    return 0;
}

Если вы скомпилируете это как ppid и поместите его в свой путь, вы можете вызвать его, например:

$ (echo $$; ppid)
2139
29519
$ (x=$(ppid); echo $x)
29521

Одна странность, которую я заметил, однако, заключается в том, что если вы напишите

$ (ppid)

, то, похоже, на самом деле он не запускается в подоболочке - вам нужно как минимум две команды внутрикруглые скобки для bash на самом деле запустить их в подоболочке.

4 голосов
/ 20 июля 2012

Вы можете сделать:

$ ( your_action ) &
[1] 44012

И найти PID подпроцесса вот так:

$ echo "The sub PID : $!"
The Sub PID : 44012

$! возвращает последнее задание в PID фона.(см. это руководство )

2 голосов
/ 20 июля 2012

Используйте homebrew для установки pgrep на Mac: brew install pgrep

Проверьте http://mxcl.github.com/homebrew/, чтобы установить Homebrew.

1 голос
/ 12 декабря 2015

Вы можете использовать ppid родительского элемента, повторяя BASHPID родительского элемента при первом входе в оболочку, затем вы выполняете фоновый процесс и можете искать pid через ppid с помощью родительского элемента.pid.

Например, чтобы получить pid команды sleep 555, заключенной в подоболочку:

(echo "$BASHPID" > /tmp/_tmp_pid_ && sleep 555 &) && ps -ho pid --ppid=$(< /tmp/_tmp_pid_)

1 голос
/ 03 февраля 2012

Кажется, это работает:

(echo $$; echo  `ps axo pid,command,args | grep "$$" |awk '{ getline;print $1}'`)
14609
17365

По какой-либо причине OSX ограничен и не поставляется с pgrep, или можно было бы сделать (что работает в Linux):

 (echo $$; echo  `pgrep -P $$`) 
 14609
 17390
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...