Inicio um processo em segundo plano a partir do meu script de shell e gostaria de finalizar esse processo quando meu script terminar.
Como obter o PID desse processo no meu script de shell? Tanto quanto posso ver, a variável $!
contém o PID do script atual, não o processo em segundo plano.
linux
shell
background-process
pid
Volodymyr Bezuglyy
fonte
fonte
Respostas:
Você precisa salvar o PID do processo em segundo plano no momento em que o inicia:
Você não pode usar o controle de tarefas, pois esse é um recurso interativo e vinculado a um terminal de controle. Um script não terá necessariamente um terminal conectado, portanto o controle do trabalho não estará necessariamente disponível.
fonte
foo
e$!
, e nós recebemos algo que é pid ao invés defoo
?foo
vários comandos de canal (por exemplotail -f somefile.txt | grep sometext
). Nesses casos, você obterá o PID do comando grep em$!
vez do comando tail, se era o que estava procurando. Você precisará usarjobs
oups
ou os gostos nesta instância.grep
, mas se você matá-lo, a cauda receberá um SIGPIPE quando tentar gravar no pipe. Mas assim que você tenta entrar em qualquer controle / gerenciamento de processo complicado, o bash / shell se torna bastante doloroso./bin/sh -c 'echo $$>/tmp/my.pid && exec program args' &
- sysfault 24 de novembro '10 às 14:28Você pode usar o
jobs -l
comando para chegar a um jobL específicoNesse caso, 46841 é o PID.
De
help jobs
:jobs -p
é outra opção que mostra apenas os PIDs.fonte
$!
logo após o início é mais portátil e direto na maioria das situações. É isso que a resposta atualmente aceita faz.jobs -p
retornou o mesmo quejobs -l
no Lubuntu 16.4$$
é o pid do script atual$!
é o pid do último processo em segundo planoAqui está um exemplo de transcrição de uma sessão do bash (
%1
refere-se ao número ordinal do processo em segundo plano, conforme visto emjobs
):fonte
%1
não retorna o processo de fundo no meu Ubuntu enquantoecho $!
fazUma maneira ainda mais simples de eliminar todo o processo filho de um script bash:
O
-P
sinalizador funciona da mesma maneira compkill
epgrep
- obtém processos filhos, apenas compkill
os processos filhos sendo mortos e compgrep
os PIDs filhos impressos no stdout.fonte
bash -c 'bash -c "sleep 300 &"' &
correrpgrep -P $$
não mostra nada, porque o sono não será um filho direto do seu shell.$$
se refere ao shell atual.bash -c 'bash -c "sleep 300 &"' & ; pgrep -P $$
, eu entro no 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 $$
isto é o que eu fiz. Confira, espero que possa ajudar.
Em seguida, basta executá-lo como:
./bgkill.sh
com permissões apropriadas, é clarofonte
Você também pode usar o pstree:
Isso normalmente fornece uma representação em texto de todos os processos para o "usuário" e a opção -p fornece a identificação do processo. Até onde eu entendo, não depende de os processos pertencerem ao shell atual. Também mostra garfos.
fonte
pgrep
pode obter todos os PIDs filhos de um processo pai. Como mencionado anteriormente,$$
os scripts atuais são PID. Portanto, se você deseja um script que seja limpo depois de si mesmo, isso deve ser o que você precisa:fonte
trap 'pkill -P $$' SIGING SIGTERM EXIT
parece mais simples, mas eu não testei.SIG
prefixo. É permitido pelo POSIX, mas apenas como uma extensão que implementações podem apoiar: pubs.opengroup.org/onlinepubs/007904975/utilities/trap.html O shell traço por exemplo, não faz.