Como lidar com um processo zumbi no Linux

De forma bem simplificada (ou em termos leigos), processo zumbi é aquele que ainda pode ser visto na tabela de processos, mesmo que já tenha sido finalizado.
Processos nestas condições também são chamados “defuntos” (ou defunct).

Para entender como os zumbis são criados, é necessário compreender como os processos são retirados do espaço da memória do sistema, após serem finalizados
Apesar da coincidência de temas, não há nada de macabro neste post.
Sob o ponto de vista técnico, a presença de zumbis no seu sistema é uma realidade, provavelmente, constante — e normalmente não é preocupante.

Como os zumbis aparecem

A cada vez que um processo completa seu ciclo e termina sua execução com sucesso, ele desocupa a memória e avisa que “morreu” ao processo que lhe deu origem (processo pai).
Neste momento, o pai deve executar uma chamada de sistema (system call) WAIT, que faz a leitura do estado do filho morto.
Quando o WAIT termina de ser executado, o cadáver é removido da memória — e a vida segue.
O problema aparece quando há defeitos no código do processo pai ou, por alguma razão, este é incapaz de ler o estado do processo filho.
Neste caso, a chamada de sistema pode simplesmente não ocorrer.
Como consequência, o cadáver não é removido, permanece na memória e continua aparecendo na tabela de processos.
Toda esta operação, descrita acima, é muito rápida.
Os zumbis são previstos pelo Linux.
São inócuos e, na maioria das vezes, nem são notados.
Muitos tem PID 1 como pai, que é o próprio init.
O init executa um processo de limpeza periódica que acaba por remover naturalmente os zumbis do sistema.
Por isto, é seguro dizer que não há com que se preocupar.

Como encontrar zumbis no Linux

Use o comando ps para checar o seu sistema:


ps axu | grep Z

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
justinc+  1920  0.0  0.0      0     0 tty2     Z+   nov07   0:00 [single] 
justinc+ 20324  0.0  0.0  12792   932 pts/1    S+   17:57   0:00 grep --color=auto Z

Observe a coluna STAT, que informa o estado de cada processo listado.
A letra Z indica quando um processo está em estado zombie.

How to find zombies

Como matar zumbis

Você não pode matar o que já está morto!

Não é possível terminar processos zumbis. Eles já estão finalizados.
Se a situação te preocupa, é possível informar ao processo pai que “sua criança” está morta — para que rodem a chamada de sistema WAIT.
Use o comando pstree para descobrir qual é o PID do processo pai.
Em seguida, é possivel enviar o sinal SIGCHLD para o PID do pai:

kill -s SIGCHLD ppid

Acima, substitua ppid pelo número do PID do processo pai.

Impacto da presença de processos zumbis no sistema

Como já foi dito, ocupam pouco espaço e sua presença, em geral, é inofensiva e sequer chega a ser percebida.
Mas há casos em que a quantidade de zumbis continua a crescer — às vezes rapidamente. Aí, sim, temos um problema.
Como consequencia da multiplicação dos zumbis, podemos nos deparar com 2 stuações desagradáveis:

  1. Cada zumbi mantem seu PID enquanto cria novos processos, com novos PIDs.
    Depois de um tempo, as possibilidades de criar novos PIDs sao exauridas pelo kernel do sistema.
  2. Mesmo que cada zumbi ocupe apenas uma quantidade muito pequena de memoria, um numero muito grande deles pode fazer a diferença e causar a lentidao ou, mesmo, o travamento do sistema.

Você pode agir individualmente em relação a cada zumbi… ou não.
Pode ser legal mostrar aos seus amigos que você tem uma ou outra “criatura” destas habitando o seu sistema, temporariamente.
É possível que o seu amigo também tenha…
Só uma rápida e crescente multiplicação deles é que irá exigir uma medida mais drástica: reboot, para limpar o sistema.

Como manter a execução de um programa, mesmo após finalizar a sessão no Linux

Ao finalizar uma sessão no Linux (na GUI ou na CLI), o sistema operacional entende que todos os programas e processos iniciados pelo usuário devem ser fechados.
Terminar uma sessão não é a mesma coisa que desligar o computador.
Comumente, as pessoas encerram uma sessão, para iniciar outra, sob um novo perfil de usuário.
Este pode ser o momento ideal para executar programas de manutenção, como um script de backup, por exemplo.
O truque pode ser realizado com o utlitário nohup.

O nohup executa comandos imunes a hangups e envia seus resultados (output) a um terminal non-tty.
Em resumo, ele mantém o comando vivo, em execução, mesmo após o fim da sua sessão.
O nome é derivado da junção dos 2 termos: no hangup.

Veja um exemplo, tirado do manual do comando:


nohup wget site.com/file.zip

Outro caso em que ele pode ser útil, é na atualização do sistema.
Se você estava adiando o update, para não sobrecarregar a sua conexão, pode rodar o procedimento ao sair:


nohup sudo apt update

Webmasters podem se valer deste utilitário, para manter procedimentos em funcionamento, mesmo após se desconectarem do servidor remoto.
Como padrão, um arquivo será gerado no diretório local, em que o nohup foi executado, com o nome de nohup.out — contendo as saídas do comando que ele executou.
Para atualizar o sistema, abra um novo terminal e autentique-se como root. Agora rode o procedimento de atualização:


nohup apt update; apt -y full-upgrade


nohup: ignorando entrada e anexando saída a 'nohup.out'
Lendo listas de pacotes... Pronto
Construindo árvore de dependências
Lendo informação de estado... Pronto Calculando atualização... Pronto ...

Pode fechar o terminal.
Quando quiser verificar o andamento da sua atualização, basta dar uma olhada no arquivo nohup.out:


sudo cat nohup.out

linux terminal nohup apt

Como desvincular um programa da shell em que foi executado

Já desejou fechar a janela do console, mas tinha um programa rodando dentro dele, cujo funcionamento você não queria interromper?
Se a sua resposta é sim e você gostaria de conhecer um meio de solucionar esta situação, me acompanhe.
Neste texto, vou mostrar como enviar um aplicativo, em execução, para os bastidores do sistema (background) e desvinculá-lo da shell que estiver rodando no terminal.
Até agora, sabemos que ao executar um comando Linux, dentro de uma janela do console, ele é finalizado junto com a janela.
Linux tux

A abordagem, descrita no texto, permite se conectar a um servidor remoto, executar uma tarefa em segundo plano e mantê-la rodando, mesmo depois de fechar a sessão SSH.

Se o aplicativo estiver sendo executado em segundo plano, o resultado é o mesmo.
Uma sessão SSH, através da qual, você está rodando um processo em uma máquina remota também seria terminada, junto com o processo, ao fechar a janela do console.
Isto acontece por que uma shell, que é o processo pai de todos os outros que estejam rodando em segundo plano — no terminal ou na sessão SSH – envia um SIGINT a todos os seus processos filhos, antes de ela mesma se finalizar.
Se você quer que um processo continue rodando depois que a sessão do terminal tiver sido fechada, você precisa desconectá-lo “desta família”.

Como desvincular um processo do bash shell

Comece por interromper o processo que estiver em execução, com a combinação de teclas ‘Ctrl + z’.
Agora, execute o processo em segundo plano, com o comando bg.
Por último, desvincule o processo com o comando disown.
Veja um exemplo, usando o aplicativo gnome-disks:

gnome-disks &
[1] 13023
disown %1
exit

No exemplo acima, já comecei executando o aplicativo gnome-disks em segundo plano, o que me permitiu usar o comando disown, logo.
Ao dar o comando exit, a janela do terminal foi fechada, mas o aplicativo gnome-disks permaneceu aberto e em execução.
exemplo de uso do comando disown no Linux
O disown é um dos comandos embutidos da shell bash, cuja ação é não permitir que o SIGHUP chegue aos processos descendentes — o que lhes permitirá continuar em execução, mesmo depois que a shell tiver sido fechada.
Se você costuma usar o comando jobs, para obter uma lista dos processos em execução na shell de trabalho atual, saiba que o comando desapropriado (ou disowned), em execução no segundo plano, não irá aparecer na lista.
Você ainda poderá vê-lo com o ps aux.
O que importa é que é seguro fechar o terminal e, até mesmo, se desautenticar do sistema e terminar a sua sessão SSH — o comando continuará em execução.
Se você rodar o comando disown, sem qualquer argumento ou opção, ele irá entender que deve agir sobre o job mais recente na lista de processos.
Nem todas as shells irão ter suporte ao comando disown.
Ele existe no bash e no zsh.
Alternativamente, é possível desvincular um processo Linux da uma shell com o comando nohup.
Neste, caso, ele deve ser usado no lançamento do processo.

nohup gnome-disks &

A diferença básica entre este método e o anterior é que o disown previne que uma shell, ao ser fechada, envie sinais SIGHUP.
O segundo método já pré-configura o comando, a ser executado, para ignorar os sinais SIGHUP enviados por aquela shell.

Obrigado pela leitura!

O aplicativo parou de responder? Use xkill para matar.

Relacionado ao comando kill, o xkill é usado no ambiente gráfico para matar janelas ou aplicativos que não estejam mais respondendo.
Pelos mesmos motivos expostos aqui, não deve ser usado o tempo todo. Você pode perder informações e tornar a sua sessão instável, ao abusar do uso deste método para terminar programas.

POSTS RELACIONADOS

Como fechar programas no ambiente gráfico do Linux

Quando um programa para de responder, no ambiente gráfico, você ainda tem opções para evitar a perda dos dados que estavam sob o trato do aplicativo.
Se o mouse ainda não parou de responder, tente fechar o aplicativo pelo próprio menu do sistema:

  • clique com o botão direito do mouse sobre a aba referente à janela do programa (na barra de tarefas);
  • selecione a opção Fechar F4;
  • confirme que você deseja terminar o programa
  • Aviso do sistema para fechar programa que parou de responder
    Clique para ampliar.

Só para constar: este é o jeito certo de fechar aplicativos que pararam de responder. Aguarde, pacientemente, enquanto o sistema fecha a janela do aplicativo.
Se isto não deu certo, use o xkill

Como usar o xkill para fechar aplicativos

Desenvolvido por Jim Fulton e pela programadora Dana Chee, o xkill, permite fechar arbitrariamente a conexão de um programa com o servidor X.
Se o xkill não for encontrado no menu do sistema, você pode iniciá-lo a partir de um terminal:

xkill

ao iniciar, o xkill transforma o cursor do mouse em uma “caveirinha“. Ao clicar dentro de qualquer janela, a caveirinha vai “tentar matar” o aplicativo que estiver rodando ali.
Se você se arrepender, aperte a tecla ESC no seu teclado para cancelar o “assassinato”.

Usar o xkill é recomendável?

Não. Não é.
Use-o apenas como último recurso.
Entre os resultados indesejados, você pode tornar o seu sistema instável e perder os dados que estavam dentro do aplicativo fechado.
Além disto, o xkill não garante o fechamento do aplicativo — a única coisa que ele se propõe é fechar sua conexão com o gerenciador gráfico de janelas.
Embora a maioria dos aplicativos costume abortar quando a sua conexão com o X é fechada, alguns podem optar por continuar rodando, em background.

LEITURA SUGERIDA

Como matar programas no Linux

Da série de comandos tradicionais do universo Linux e Unix, o comando kill permite interromper processos arbitrariamente.
Uma definição simplificada de processo é de que se trata de um programa ou uma tarefa em execução
É um sistema UNIX! Eu conheço isto! Kill
Ao iniciar, cada processo recebe uma identificação numérica única, atribuída pelo sistema — chama-se PID, Process IDentification.
Para “matar” um programa em execução, você precisa saber o PID dele (no final do artigo, vou mostrar como matar um processo sem saber seu PID).

POSTS RELACIONADOS

A sintaxe do comando kill

Apesar do nome, o comando kill serve para muito mais do que apenas matar processos.
Sua função é enviar sinais para processos e alguns destes não tem absolutamente qualquer coisa a ver com “morte”.
Sua execução segue, portanto, a seguinte forma:


kill -s SINAL PID

Nos exemplos, abaixo, vou mostrar outras formas de usar o comando.

Como encontrar o PID de um processo específico

O comando ps aux pode mostrar uma lista bem extensa de processos em execução, o que pode dificultar a busca.
É aqui que entra o comando grep, um velho conhecido da gente.
Para exemplificar, vou rodar o ftp em background (&) e determinar o seu PID com o grep em conjunto com o ps:


ftp &

[1] 2983

ps aux | grep ftp

proftpd   1242  0.0  0.1  11996  2172 ?        Ss   10:01   0:00 proftpd: (accepting connections)              
1000      2983  0.0  0.0   5212  1012 pts/5    T    11:51   0:00 ftp
1000      2985  0.0  0.0   4724   836 pts/5    S+   11:51   0:00 grep --color=auto ftp
[1]+  Parado                  ftp

Neste exemplo, o programa ftp tem o PID 2983. No seu sistema o PID será diferente. Verifique.

O comando kill, em exemplos

Uma vez que você já sabe como determinar o PID dos processos, já pode entender como usar esta informação em conjunto com o kill.
Há dois sinais básicos para indicar que se deseja interromper a execução de um processo:

  • SIGTERM(15) — que requisita educadamente a interrupção de um processo. Cabe a este aceitar ou ignorar o sinal. Se aceitar, ele finaliza sua própria execução, graciosamente e gravando o que precisa ser gravado. Há um sinal semelhante a ele, chamado SIGINT. Cada sinal atende por um número. O do SIGTERM é 15.
  • SIGKILL(9) — envia uma requisição ao processo para que este seja terminado imediatamente. Ele não pode ser ignorado e é sequer analisado pelo processo, que é interrompido incontinenti. O número deste sinal é 9.

Vamos ver como aplicá-los:
Podemos enviar um SIGTERM ao processo 2983, de 4 formas diferentes:


kill 2983
kill -s TERM 2983
kill -TERM 2983

ou indicando o número do sinal:


kill -15 2983

Para enviar um SIGKILL, use uma destas 3 opções:


kill -9 2983
kill -s KILL 2983
kill -KILL 2983

Espero ter deixado claro, como terminar um processo via terminal, no Linux. O ambiente gráfico tem um comando similar, chamado xkill, do qual falaremos em outro artigo.

POSTS RELACIONADOS

Como finalizar um programa sem conhecer o seu PID

Há casos em que um processo abre vários outros processos – em que um programa abre várias outras instâncias de si mesmo. Quando o usuário dá um ps no sistema, vê uma quantidade muito grande de PIDs para fechar.
Veja a figura, abaixo, onde se pode ver uma certa quantidade de processos do chromium-browser abertos.
comando ps aux linux
É possível fechá-los todos com o killall. Veja como:


killall chromium-browser

Você pode repassar o número de um sinal para o comando, assim:


killall -9 chromium-browser

Fácil, não é?