Esta é uma solução da Shell que não requer utilitários externos além de ps
if [[ 'ps --pid $PID -oppid=' = $PPID ]]
then
: still running
else
: not running
fi
De acordo com a página ps
man:
Except as described below, process selection options are additive. The default selection is discarded, and then the selected processes are added to the set of processes to be displayed. A process will thus be shown if it meets any of the given selection criteria.
Acho que isso significa que as correspondências são "OR" ed, não "AND" ed.
Estou desenvolvendo meu próprio script de bloqueio que cria um diretório (mkdir mutex) e grava informações de PPID e PID em um arquivo nesse diretório. Uma das funções do script é limpar os arquivos de bloqueio obsoletos, fazendo o loop de todos os arquivos de bloqueio e extraindo $ PPID e $ PID. Em seguida, ele determina se um processo com PID $ PID e PPID $ PPID ainda está em execução.
No entanto, com ps
estou obtendo todos processos que têm PPID $ PPID e também estou recebendo PID $ PID. Quero que ele mostre apenas o processo com pid $ PID e ppid $ PPID
Eu entendo que grep
é intuitivamente útil aqui, mas existe um método "menos caro" para usar? Talvez outro utilitário relacionado ao processo?
procps-3.2.7-16.el5
Acabei de verificar, parece que o CentOS 6.6 pgrep
não tem a opção -F
, então isso não é aplicável. Vou deixar essa resposta aqui, pois pode ser útil em outros casos.
pgrep
pode ser o que você quer:
-P, --parent ppid,...
Only match processes whose parent process ID is listed.
-F, --pidfile file
Read PID's from file. This option is perhaps more useful for
pkill than pgrep.
Parece que pgrep
com -F
filtrará os PIDs para que correspondam aos do arquivo:
$ pgrep libvirtd
1343
18471
$ pgrep -F /var/run/libvirtd.pid -P 1
1343
$ echo -n 18471 > other-libvirtd.pid
$ pgrep -F other-libvirtd.pid -P 1
$ pgrep -F other-libvirtd.pid
18471
Usando uma opção ps
e filtragem adicional com grep
ou awk
é uma abordagem razoável.
Não passe a opção -o
para ps
e limite os campos aos que você precisa. Use um sinal de igual após cada nome de campo para suprimir a linha de cabeçalho. Se você não precisa do nome do comando, não inclua comm
ou args
, o que poderia incluir novas linhas (e em qualquer contexto sensível à segurança, se eles contiverem uma nova linha, verifique se o script faz algo sensato). Por exemplo, se você só precisa do PID e quer todos os processos que pertencem a um determinado grupo e estão sendo executados em um determinado TTY, então você pode coletar os PIDs com
pid_list=$(ps -t tty3 -o 'pid= gid=' | awk '$2 == 1234 || $2 == "somegroup"')
No seu caso, isso é um exagero. Existe um único processo que tem um determinado PID, então a condição -p $PID
é toda a filtragem que você precisa. Recupere o PPID do processo por esse PID e compare-o com o valor esperado. ps
não produzirá nada se não houver processo com esse PID.
read pid expected_ppid <"$pidfile"
actual_ppid=$(ps -o ppid= -p "$pid")
if [ "$actual_ppid" = "$expected_ppid" ]; then …
Lembre-se de que, se você encontrar um processo com as características corretas, poderá ser o mesmo processo ou um processo não relacionado, pois o processo esperado está morto há muito tempo e seu PID foi reutilizado.