Я запускаю фоновый процесс из своего сценария оболочки и хочу завершить этот процесс, когда мой сценарий завершится.
Как получить PID этого процесса из моего сценария оболочки? Насколько я вижу, переменная $!
содержит PID текущего скрипта, а не фоновый процесс.
linux
shell
background-process
pid
Владимир Безуглый
источник
источник
Ответы:
Вам нужно сохранить PID фонового процесса во время его запуска:
Вы не можете использовать управление заданиями, поскольку это интерактивная функция, связанная с управляющим терминалом. К сценарию не обязательно будет присоединен терминал вообще, поэтому контроль работы не обязательно будет доступен.
источник
foo
и$!
, и мы получаем что-то pid вместоfoo
s?foo
случается несколько команд по конвейеру (например,tail -f somefile.txt | grep sometext
). В таких случаях вы получите PID команды grep,$!
а не команду tail, если это то, что вы искали. Вам нужно будет использоватьjobs
илиps
или лайки в этом случае.grep
, но если вы убьете это, tail получит SIGPIPE, когда попытается записать в канал. Но как только вы пытаетесь войти в любой сложный процесс управления / контроля, bash / shell становится довольно болезненным./bin/sh -c 'echo $$>/tmp/my.pid && exec program args' &
- sysfault 24 ноября '10 в 14:28Вы можете использовать
jobs -l
команду, чтобы добраться до определенного задания.В этом случае 46841 является PID.
От
help jobs
:jobs -p
это еще один вариант, который показывает только PID.источник
$!
сразу после запуска делает его более переносимым и простым в большинстве ситуаций. Это то, что делает в настоящее время принятый ответ.jobs -p
вернулся так же, какjobs -l
на Lubuntu 16.4$$
pid текущего скрипта$!
pid последнего фонового процессаВот пример стенограммы из сеанса bash (
%1
относится к порядковому номеру фонового процесса, как видно изjobs
):источник
%1
не возвращает фоновый процесс на моем Ubuntu, тогдаecho $!
какЕще более простой способ уничтожить все дочерние процессы скрипта bash:
-P
Флаг работает так же , как сpkill
иpgrep
- он получает дочерние процессы, толькоpkill
дочерние процессы убивают иpgrep
ребенка ИДП печатается на стандартный вывод.источник
bash -c 'bash -c "sleep 300 &"' &
запускаpgrep -P $$
ничего не отобразится, потому что сон не будет прямым потомком вашей оболочки.$$
относится к текущей оболочке.bash -c 'bash -c "sleep 300 &"' & ; pgrep -P $$
, я встаю на stdout[1] <pid>. So at least it shows something, but this is probably not the output of
pgrep`bash -c 'bash -c "sleep 10 & wait $!"' & sleep 0.1; pstree -p $$
это то, что я сделал. Проверьте это, надеюсь, это поможет.
Затем просто запустите его как:
./bgkill.sh
с соответствующими разрешениями, конечноисточник
Вы также можете использовать pstree:
Обычно это дает текстовое представление всех процессов для «пользователя», а опция -p - идентификатор процесса. Насколько я понимаю, это не зависит от того, будут ли процессы принадлежать текущей оболочке. Это также показывает вилки.
источник
pgrep
может получить вам все дочерние PID родительского процесса. Как уже упоминалось ранее,$$
это текущие сценарии PID. Итак, если вам нужен скрипт, который очищается после себя, это должно сработать:источник
trap 'pkill -P $$' SIGING SIGTERM EXIT
выглядит проще, но я этого не проверял.SIG
префикс. Это разрешено POSIX, но только как расширение, которое могут поддерживать реализации : pubs.opengroup.org/onlinepubs/007904975/utilities/trap.html Например, оболочка dash не поддерживает.