pgrep возвращает дополнительные процессы при передаче другими командами
Вот очень странный вопрос об использовании pgrep для поиска, какие процессы оболочки выполняют тот же сценарий, что и текущий.
Вот тестовый скрипт с именем test.sh
#!/bin/bash
full_res=`pgrep -a -l -f 'test\.sh'`
res=$(pgrep -a -l -f 'test\.sh' | cat)
echo "short result is $full_res"
echo "weird result is $res"
При выходе
sh test.sh &
[1] 19992
➜ logs short result is 19992 sh test.sh
weird result is 19992 sh test.sh
19996 sh test.sh
[1] + 19992 done sh test.sh
Я не знаю, где19996 sh test.sh
исходит, особенно при использовании трубы для кошки. Я считаю, что это может быть ошибка в реализации pgrep.
Жду разумного объяснения
Спасибо,
Балин
2 ответа
Когда вы создали конвейер с помощью обратных кавычек или$(...)
создается подоболочка, которая является точной копией исходной оболочки bash, которую вы вызвали.
В тот момент, когда вы выполняете pgrep, на самом деле у вас есть следующее:
bash test.sh
└─bash test.sh
└─ pgrep -f test.sh
└─ cat
Такpgrep
делает то, что вы просили.
Вы можете смоделировать это поведение следующим образом.
#!/bin/bash
echo mypid $$
$(sleep 60 | sleep 60 | sleep 60)
Запустите процесс в фоновом режиме, используя выданный им pid, проверьте его с помощьюpstree
.
$ ./test.bash
mypid 335153
^Z
[1]+ Stopped ./test.bash
$ bg
[1]+ ./test.bash &
$ pstree -p 335153
test.bash(335153)───test.bash(335154)─┬─sleep(335155)
├─sleep(335156)
└─sleep(335157)
Из Pipelines в руководстве по bash:
Каждая команда в многокомандном конвейере, в котором создаются каналы, выполняется в своей подоболочке, представляющей собой отдельный процесс.
Кстати, вот почему это не сработает:
date | read theDate
echo "$theDate"
посколькуread
команда выполняется в подоболочке, поэтомуtheDate
переменная заполняется в подоболочке, а не в текущей оболочке.