Итак, сначала делаем ./test.sh
с терминала. Итак, у нас есть один процесс с именем test.sh
.
process_count=`pgrep 'test.sh' | wc -l`
Подстановка команд, вызываемая обратными кавычками, запускает подоболочку. Подоболочка - это отдельный процесс с тем же именем test.sh
. Итак, теперь есть два процесса с разными pid, которые имеют имя test.sh
. Таким образом, pgrep
возвращает две строки.
Это можно, например, проверить с помощью:
process_count=$(
ps -e -o pid,comm | grep 'test.sh' >&2
echo BASHPID=$BASHPID \$=$$ >&2
pgrep 'test.sh' | wc -l
)
с выходами на stderr:
495463 test.sh
495466 test.sh
BASHPID=495466 $=495463
495466
is pid подоболочки, а 495463
- pid процесса родительской оболочки.
Когда вы это делаете:
pids=`pgrep 'test.sh'`;
это выводит единственный pid. Это связано с тем, что bash имеет оптимизацию, которая при определенных c обстоятельствах (например, no trap
s), когда только один процесс остается для выполнения в оболочке, он оптимизируется и не вызывает fork()+exec()
вместо этого вызывает просто exec
, потому что следующего процесса не будет, поэтому он может просто выйти. Внутренняя подоболочка с именем процесса test.sh
существует только в течение короткого времени, подоболочка обнаруживает, что есть только одна команда для запуска, поэтому она пропускает fork()
, просто выполняет exec("pgrep")
и становится процессом с именем процесса pgrep
. Вот почему в этом случае вы не видите другой pid.
Примечания: Пожалуйста, не используйте обратные кавычки `. Вместо этого используйте $(...)
.
Дополнительно: больше подоболочек! Следующие
echo "$(echo "$(echo "$(pgrep 'test.sh' | wc -l)")")"
# would output 4