использование pgrep для подсчета процессов в скрипте - PullRequest
0 голосов
/ 25 апреля 2020

В моем Raspbian я использовал команду:

pgrep -c ^

Я думаю, что эта команда должна выполнять подсчет всех процессов без использования более привычного метода

ps -A --no-headers | wc -l

Однако, при запуске pgrep - c ^ в сценарии (скажем, при входе в систему) я хочу вычесть 1 из подсчитанного количества запущенных процессов, чтобы вызываемая оболочка (скажем, «sh») выполняла сценарий (или сценарий). само по себе) не считается процессом ... Я не знаю, следите ли вы за мной по этому вопросу. Затем я начал проводить эксперименты с командой pgrep

Вот пример моего сценария:

#!/bin/sh
ps1=$(pgrep -c ^)
ps2=$(expr $(pgrep -c ^) - 1)    # minus 1
ps3=$(expr $(pgrep -c ^) - 2)    # minus 2
echo ${ps1}
echo ${ps2}                      # ps1 == ps2
echo ${ps3}

Я получаю результаты (в моем случае):

112
112
111

а) В скрипте изменение порядка оценки ps1 и ps2 не имеет никакого значения. Дело в том, что ps1 и ps2 всегда равны (не знаю почему).

b) Одни и те же команды вводятся непосредственно в приглашение, как показано ниже:

$> pgrep -c ^; expr $(pgrep -c ^) - 1

показывает (как и ожидалось) ):

111
110

c) Но если я изменю команду для использования echo:

$> echo "$(pgrep -c ^) : $(expr $(pgrep -c ^) - 1)"

даже при изменении порядка оценки:

"$> echo "$(expr $(pgrep -c ^) - 1) : $(pgrep -c ^)"

in В обоих случаях, как в скрипте, я получаю:

112 : 112

Вопросы:

1) Почему вне скрипта / echo он работает как положено, но внутри скрипта или внутри и echo / printf значения одинаковы?

2) Является ли команда pgrep - c ^ правильной для подсчета запущенных процессов, как я хочу сделать?

Спасибо

1 Ответ

0 голосов
/ 26 апреля 2020

Проблема здесь в том, что вы игнорируете тот факт, что оболочки создают отдельный процесс, разветвляясь для выполнения каждой подстановки команд.

Я допускаю, что поведение оболочек сбивает с толку. Например, например:

$ pstree $$
sh───pstree
$ echo $(pstree $$)
sh───pstree

Хотя я и говорил выше, похоже, что sh не создал дополнительного процесса для выполнения подстановки команд. Но это заблуждение; на самом деле он выполнял форк, но поскольку в $() есть только одна команда, в разветвленном процессе не было смысла оставаться в живых; поэтому он просто заменил себя на pstree, вызвав функцию из семейства exe c*; то есть он стал pstree.
Если после завершения pstree была выполнена другая команда, необходимо, чтобы разветвленный процесс оставался в живых. См .:

$ echo $(pstree $$; :)
sh───sh───pstree

Расширение вложенных подстановок команд также может сбивать с толку, поэтому давайте поясним это тоже.

$ echo $(echo $(pstree $$))
sh───sh───pstree

Для примера выше, поскольку каждая подстановка команд содержит только одну команду можно ожидать увидеть только один sh в дереве процессов; но это не так. Команды, заключенные в $(), обрабатываются в подоболочке, созданной для выполнения подстановки команд, а не в родительской оболочке. Для этого случая это означает; разветвленный процесс сделал еще одну собственную копию, чтобы иметь возможность выполнить pstree и собрать свои выходные данные, а затем выполнить echo; то есть разветвленный процесс был жив, пока pstree работал, следовательно, дополнительные sh в дереве.

Итак, вместо того, чтобы иметь дело с этими исключениями (и возможными другими, о которых я не знаю или не помню ), положитесь на механизм группировки процессов вашей оболочки. Как:

pgrep -c ^
pgrep -cvg $$
echo $(pgrep -cvg $$)
echo $(echo $(pgrep -cvg $$))
echo $(echo $(echo $(pgrep -cvg $$)))

Для меня это выводит:

264
263
263
263
263
...