Нахождение количества дочерних процессов

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


person Adam Matan    schedule 18.07.2012    source источник


Ответы (6)


Чтобы получить PID сценария bash, вы можете использовать переменную $$.

Затем, чтобы получить его дочерние элементы, вы можете запустить:

bash_pid=$$
children=`ps -eo ppid | grep -w $bash_pid`

ps вернет список родительских PID. Затем grep фильтрует все процессы, не связанные с дочерними элементами bash-скрипта. Для того, чтобы получить количество детей, вы можете сделать:

num_children=`echo $children | wc -w`

На самом деле число, которое вы получите, будет на 1 меньше, так как ps также будет дочерним элементом сценария bash. Если вы не хотите считать выполнение ps дочерним, вы можете просто исправить это с помощью:

let num_children=num_children-1

ОБНОВЛЕНИЕ: во избежание вызова grep может использоваться следующий синтаксис (если он поддерживается установленной версией ps):

num_children=`ps --no-headers -o pid --ppid=$$ | wc -w`
person betabandido    schedule 18.07.2012
comment
grep -w $bash_pid в случае, если pid bash является подстрокой идентификатора дочернего процесса. - person chepner; 18.07.2012
comment
Не уверен, но я думаю, что дополнительный процесс — это подоболочка, содержащая конвейер ps/grep. Просто педантичен :) - person chepner; 18.07.2012
comment
Нет необходимости в grep: ps -o ppid= -p $$ (по крайней мере, с GNU ps). - person Dennis Williamson; 18.07.2012
comment
@chepner Я тоже не был уверен, поэтому просто быстро проверил. Я создал небольшой скрипт, содержащий foo=$(sleep 10 | wc -l). Затем я проверил с помощью ps, и оба sleep и wc были указаны как прямые дочерние элементы сценария (т.е. между ними не было новой оболочки). - person betabandido; 18.07.2012
comment
О, извините, я на мгновение забыл, что ОП искал детей, и я пропустил ход вашего пошагового ответа. - person Dennis Williamson; 18.07.2012

Я предпочитаю:

num_children=$(pgrep -c -P$$)

Он порождает только один процесс, вам не нужно считать слова или настраивать номера PID программами в канале.

Пример:

~ $ echo $(pgrep -c -P$$)
0
~ $ sleep 20 &
[1] 26114
~ $ echo $(pgrep -c -P$$)
1
person nrc    schedule 24.02.2014

Вы также можете использовать pgrep:

child_count=$(($(pgrep --parent $$ | wc -l) - 1))

Используйте pgrep --parent $$, чтобы получить список дочерних элементов процесса bash.
Затем используйте wc -l на выходе, чтобы получить количество строк: $(pgrep --parent $$ | wc -l) Затем вычтите 1 (wc -l сообщает 1, даже если pgrep --parent $$ пусто)

person pretorh    schedule 23.10.2013

Используйте ps с параметром --ppid, чтобы выбрать дочерние элементы текущего процесса bash.

bash_pid=$$
child_count=$(ps -o pid= --ppid $bash_id | wc -l)
let child_count-=1    # If you don't want to count the subshell that computed the answer

(Примечание: для этого требуется Linux-версия ps для --ppid. Я не знаю, есть ли эквивалент для BSD ps или нет.)

person chepner    schedule 18.07.2012
comment
Не работает для меня. Дает мне ps: illegal option -- -. Возможно, вы предполагаете конкретную версию ps? - person ghoti; 18.07.2012
comment
Да, я предполагал версию, используемую Linux. - person chepner; 18.07.2012
comment
Ах. Я тестировал на FreeBSD и OSX. - person ghoti; 18.07.2012

Если количества заданий (вместо количества pid) достаточно, я только что пришел с версией только для bash:

job_list=($(jobs -p))
job_count=${#job_list[@]}
person Jonny    schedule 20.09.2019

Вы можете оценить встроенные командные задания оболочки, например:

counter = `jobs | wc -l`
person pdug    schedule 18.07.2012
comment
Здесь учитываются задания, а не процессы. Задание может состоять из нескольких процессов. - person chepner; 18.07.2012
comment
Без пробелов вокруг знака равенства. Используйте $() вместо обратных кавычек. - person Dennis Williamson; 18.07.2012