O que é um processo <defunct> e por que ele não é morto?

180

O navegador Chrome não respondeu e tentei matá-lo, mas, em vez de desaparecer, o processo estava <defunct>certo e não foi morto:

insira a descrição da imagem aqui

O que é <defunct>um processo e por que ele não é morto?

Eduard Florinescu
fonte
3
A resposta aceita menciona que " kill -9 PIDnão funciona". É parcialmente verdade: na realidade, nenhuma matança funcionará. Além disso, -9 deve ser usado como último recurso. 99% do tempo, uma morte padrão do processo pai a matará e colherá todos os filhos. Um "kill padrão" é um SIGTERM (-15). Encorajo os fãs do -9 (SIGKILL) a ler stackoverflow.com/questions/690415/… #
Mike S

Respostas:

172

Na sua saída, vemos um "defunto", o que significa que o processo concluiu sua tarefa ou foi corrompido ou morto, mas seus processos filhos ainda estão em execução ou esse processo pai está monitorando seu processo filho. Para matar esse tipo de processo, kill -9 PID não funciona. Você pode tentar matá-los com este comando, mas ele será exibido repetidamente.

Determine qual é o processo pai desse processo extinto e mate-o. Para saber isso, execute o comando:

ps -ef | grep defunct

UID          PID     PPID       C    STIME      TTY          TIME              CMD
1000       637      27872      0   Oct12      ?        00:00:04 [chrome] <defunct>
1000      1808      1777       0    Oct04     ?        00:00:00 [zeitgeist-datah] <defunct>

Em kill -9 637 27872seguida, verifique se o processo extinto passou ps -ef | grep defunct.

Paddington
fonte
13
você não pode matar o processo "extinto". Você só pode acelerar a exclusão de sua entrada em uma tabela de processos matando seu pai.
jfs
57
E se o ppid for 1( init)? Suponha que vou ter que esperar?
Luc
7
para automatizar o kill, você também pode fazer isso (pode ser necessário alterar os bytes que você está cortando da saída):ps -ef | grep defunct | grep -v grep | cut -b8-20 | xargs kill -9
warren
3
Obrigado @warren. Você também pode tornar isso um pouco mais curto e (imo) mais simples, não fazendo um segundo grep. Basta alterar o primeiro grep para grep [d]efunctou similar e ele não será compatível.
26416 Thor84no
4
@ warren você não pode matar um processo extinto, mesmo com um SIGKILL. Além disso, você está usando kill -9 de maneira indiscriminada. Consulte stackoverflow.com/questions/690415/… . Se você quer matar crianças extinta, você pode tentar: parents_of_dead_kids=$(ps -ef | grep [d]efunct | awk '{print $3}' | sort | uniq | egrep -v '^1$'); echo "$parents_of_dead_kids" | xargs kill. Execute o script novamente após 30 segundos, aproximadamente, com o kill -9se desejar. (Note-se que I especificamente impedir morte de Init)
Mike S
60

A página do manual ps (1) diz :

Processos marcados <defunct>são processos mortos (os chamados "zumbis" ) que permanecem porque seus pais não os destruíram corretamente. Esses processos serão destruídos init(8)se o processo pai sair.

Você não pode matá-lo porque já está morto. A única coisa que resta é uma entrada na tabela de processos :

Nos sistemas operacionais Unix e Unix-like, um processo zumbi ou um processo extinto é um processo que concluiu a execução, mas ainda possui uma entrada na tabela de processos. Essa entrada ainda é necessária para permitir que o processo pai leia o status de saída do filho.

Não há mal algum em permitir que tais processos ocorram, a menos que existam muitos deles. O zumbi é colhido por seus pais (chamando wait(2)). Se o pai original não o colheu antes de sua própria saída, initprocess ( pid == 1) faz isso posteriormente. O Processo Zombie é apenas:

Um processo que foi finalizado e excluído quando seu status de saída foi relatado para outro processo que está aguardando o término do processo.

jfs
fonte
1

Obrigado Mike S. Pegamos sua linha e escrevemos um script que matará processos extintos cujo pai é in.telnetd. Não queríamos que ele matasse nenhum processo pai, apenas o telnetd que sabemos estar causando um problema e o executaremos várias vezes para matar vários, se necessário.

# egrep -v '^1$ = Make sure the process is not the init process.
# awk '{print $3}' = Print the parent process.

first_parent_of_first_dead_kid=$(ps -ef | grep [d]efunct | awk '{print $3}' | head -n1 | egrep -v '^1$')
echo "$first_parent_of_first_dead_kid"

# If the first parent of the first dead kid is in.telnetd, then kill it.
if ps -ef | grep $first_parent_of_first_dead_kid | grep in.telnetd;then
        echo "We have a defunct process whose parent process is in.telnetd" | logger -t KILL-DEFUNCT-TELNET
        echo "killing $first_parent_of_first_dead_kid" | logger -t KILL-DEFUNCT-TELNET
        kill $first_parent_of_first_dead_kid 2>&1 | logger -t KILL-DEFUNCT-TELNET
fi
David Brazzeal
fonte
1

expandindo a resposta de Paddington ..

Em sua saída, vemos um extinto , o que significa que esse processo filho concluiu sua tarefa ou foi corrompido ou morto. Seu processo pai ainda está em execução e não notou seu filho morto.

kill -9 PID não funcionará (já está morto).

Para determinar o pai desse processo filho, execute este comando:

ps -ef | grep defunct

 UID  PID **PPID** C STIME TTY TIME     CMD
 1000 637  27872   0 Oct12 ?   00:00:04 [chrome] <defunct>

Veja quem é o pai: ps ax | grep 27872

Se você quiser, pode matar o pai, e o extinto desaparecerá. kill -9 27872

veja a resposta de JF Sebastian para um raciocínio mais técnico.

kevinf
fonte
1

Adicionando à resposta de @ Paddington, adicionei esta função ao meu bashrc para verificação rápida:

defunct(){
    echo "Children:"
    ps -ef | head -n1
    ps -ef | grep defunct
    echo "------------------------------"
    echo "Parents:"
    ppids="$(ps -ef | grep defunct | awk '{ print $3 }')"
    echo "$ppids" | while read ppid; do
        ps -A | grep "$ppid"
    done
}

Ele gera algo como:

Crianças:
UID PID PPID C TEMPO DE ATITUDE CMD
usuário 25707 25697 0 fev26 pts / 0 00:00:00 [sh] 
usuário 30381 29915 0 11:46 pts / 7 00:00:00 grep desativado
------------------------------
Pais:
25697 pts / 0 00:00:00 npm
agregate1166877
fonte