Подтвердить что ты не робот

Как получить идентификатор процесса подпроцесса bash в командной строке

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

(list) list  is  executed  in  a  subshell environment 

Кроме того, чтобы получить текущий идентификатор процесса, мы используем:

echo $$

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

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

echo $$; ( echo $$; ) 

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

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

Обновление:

Рекомендуемый связанный ответ не работает, поскольку echo $BASHPID не работает на моем Mac и возвращает пустое.

4b9b3361

Ответ 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_)