Hack de encerramento do processo Bash

Conteúdo

Bash Shell

Ao desenvolver código bash multi-threaded, gerenciar processos de servidor ou criar controles de processo, um dos principais desafios geralmente é terminar corretamente, processos bash existentes eficientes e precisos. Esta postagem mostrará como.

Que e um Procedimento Bash?

Um procedimento bash é simplesmente um executável que está rodando. Como um exemplo, quando você inicia a calculadora em seu ambiente de trabalho, um procedimento bash é criado. Tal bash tem dois identificadores de procedimento principais, a saber, a PID e ele PPID, a Identificador de procedimento, e ele Identificador de procedimento principal.

Em resumo, a PID contém um ID único com base em um número para um determinado aplicativo em execução (Em outras palavras, Um procedimento), Entretanto ele PPID para qualquer aplicativo em execução (Em outras palavras, processo) armazena o PID pai do procedimento que iniciou este novo aplicativo, daí o termo 'Pai'.

Além disso, você pode ver imediatamente como isso forma uma estrutura semelhante a uma árvore, tecendo todos os processos até a raiz / primeiro procedimento que tem um PPID a partir de 0.

Processos raiz no Linux

Para uma postagem relacionada que fornece informações adicionais e um exemplo prático de PID e PPID, É possível que você queira revisar nossa postagem Exportando variáveis ​​no Bash: porquê e como.

A administração do procedimento Bash parece fácil à primeira vista (apenas corra ps -ef na linha de comando do seu terminal para ver todos os processos em execução no seu sistema, com o prefixo PID e PPID identificadores.

Até terminar um procedimento parece fácil, mas logo avisos e armadilhas começam a aparecer ao lidar com sistemas de gerenciamento de processos mais complexos.

Encerrar um procedimento Bash

Vamos começar simples, iniciando o gnome-calculator na linha de comando e, em seguida, finalizando o procedimento.

gnome-calculator &
ps -ef | grep gnome-calculator
kill -9 $RELEVANT_PID

Um processo de kill simples no Linux

nós começamos gnome-calculator em modo de fundo (usando & no final do comando), para que possamos ter nosso prompt de terminal de volta imediatamente, sem ter que iniciar outra sessão de terminal.

A seguir, nós usamos ps -ef em combinação com um tubo|) e ele grep comando para localizar o ID do procedimento (PID) da nossa calculadora. A seguir, nós terminamos com um sinal 9 kill comando. Substituir $RELEVANT_PID no código com o PID relatado por ps se você tentar este código.

Observe que o procedimento em segundo plano termina imediatamente kill -9 instrução. Apesar disto, o prompt de comando bash retorna tão rápido que retorna antes mesmo que o planejador de processo possa relatar que o procedimento em segundo plano foi concluído.

E só o fará quando a notificação estiver de acordo com o trabalho existente, Em outras palavras, é mais baseado na extração do que na inserção. Quando pressionamos enter, o sistema verifica e nos notifica que o primeiro procedimento de background foi concluído, ou melhor, estava acabado / removido; [1]+ Killed gnome-calculator.

Voltando ao nosso kill command, Um sinal 9 kill é uma das mortes mais destrutivas que existem. Simplesmente, termine o show na hora, sem ser gentil com isso. Você pode revisar a seção ‘Sinal de numeração para sinais padrão’ alcançável de man signal.7 comando executado no prompt de comando do seu terminal para obter uma lista de todos os tokens disponíveis e seus números correspondentes.

Para os fins desta postagem, usaremos sinal 9 sempre encerrar imediatamente e efetivamente um procedimento. Apesar disto, mesmo ao usar um sinal 9 matar / termine o procedimento, às vezes, um procedimento pode ficar em um morto Estado.

Isso não acontece com frequência no trabalho geral de DevOps, e se isso acontecer, geralmente significa que houve alguns problemas sérios no código do programa (o procedimento que está sendo executado) para iniciar, ou com hardware de sistema ou sistema operacional.

Evite erros e escolha seus próprios processos

Recomeçar com o procedimento anterior, Existe uma maneira de automatizar o PID seleção para que não precisemos digitar manualmente, e então podemos usá-lo a partir de um script? Com certeza há;

gnome-calculator &
ps -ef | grep 'gnome-calculator' | grep -v 'grep' | awk '{imprimir $2}'
ps -ef | grep 'gnome-calculator' | grep -v 'grep' | awk '{imprimir $2}' | xargs matam -9

Término de processo mais bem definido no Linux

Aqui começamos de novo nosso gnome-calculator em modo de fundo, e usado novamente ps e grep para encontrar nosso procedimento. É aí que termina a semelhança. Na próxima instrução dentro do conjunto de tubos Bash (passando informações do comando anterior para o próximo usando um símbolo de barra vertical: |) nós excluímos o grep procedimento em si (ainda listado como parte do ps saída, uma vez que é executado durante o nosso script e, por isso, é auto-coletado pelo grep), usando o -v opção a grep e excluindo a palavra 'grep'.

Para terminar, nós imprimimos o PID (ID de procedimento) de qualquer procedimento descoberto usando awk e imprimindo o segundo ($2) coluna de saída apenas. Nós vemos que apenas um PID É devolvido, o que coincide com o fato de que só temos um gnome-calculator iniciado.

Nosso comando final adiciona um xargs comando com um kill -9 instrução para terminar nosso (s) processo (s). O xargs funciona de maneira semelhante ao próprio tubo, mas é mais capaz de manipular informações de entrada e passá-las corretamente, permitindo certos programas como kill (que você não consegue entender nativamente quando é simples PIDeles são enviados para você) aceitar entradas diretas, ou melhor, opções, como o ID do procedimento que é transmitido aqui. Observe que xargs é prefixado com uma barra vertical.

Nossa inclusão de um grep -v 'grep' evite não só o erro do eventual kill comando não consegue encontrar o PID associado ao original grep comando (desde então acabou, tendo cumprido seu dever de grepping para o 'gnome-calculator' texto), em segundo lugar, também evita o risco de terminar outro comando / procedimento mais recente que pode ter sido iniciado do original. grep finalizado, com o mesmo ID de procedimento! Mesmo que a chance de isso acontecer seja pequena, é viável.

Trabalhar essas coisas em nosso comando parece melhor, mas ainda não é perfeito. O que é este servidor com 10 usuários e 10 eles começaram uma calculadora? Supondo que temos privilégios semelhantes para sudo, Queremos mesmo encerrar os processos de calculadora dos outros usuários?? Provavelmente não. Então, podemos dar um passo adiante e definir nosso comando da seguinte maneira:

gnome-calculator &
ps -ef | grep 'gnome-calculator' | grep -v 'grep' | grep "$(Quem sou eu)" | awk '{imprimir $2}'
ps -ef | grep 'gnome-calculator' | grep -v 'grep' | grep "$(Quem sou eu)" | awk '{imprimir $2}' | xargs matam -9

Exclua os próprios processos de um comando de eliminação de processo

Neste exemplo, inserimos um pequeno comando adicional, a saber grep "$(whoami)", que executou uma subcamada ($(...)) e depois executa whoami dentro dessa subcamada. a whoami O comando irá retornar os usuários registrados hoje para o terminal. Bingo! Agora acabamos de terminar nossos próprios processos.

Perfeito? Não, infelizmente, erros ainda são possíveis mesmo com uma linha de comando tão detalhada e precisa. Como um exemplo, se a lista de processos contém localidade ou caracteres estranhos, nosso grep potencialmente ainda falhar. Talvez a versão mais segura seja algo como:

gnome-calculator &
ps -ef | grep -Ei --binary-files = text "^ $(Quem sou eu) [0-9 ]+:.*gnome-calculator $" | grep --binary-files = text -v 'grep' | awk '{imprimir $2}' | grep --binary-files = text -o '[0-9]+' | xargs -I{} matar -9 "{}"

Uma versão mais segura ou comando de terminação multithread

Neste exemplo, nós definimos nosso grep comando muito mais restritivo com um regex: começo (indicado por ^) com nome de usuário (usando whoami em uma subcamada), seguido por um espaço necessário, seguido apenas pelos personagens 0-9 e espaço, pelo menos um ou mais (como indicado +), seguido por dois pontos obrigatórios (parte do tempo), seguido por qualquer caractere até o nome do nosso programa, que deve ser preenchido até o final da linha (como indicado $). a grep usar expressões regulares estendidas (-E) e não diferencia maiúsculas de minúsculas (-i opção, ou simplesmente i quando adicionado ao existente -E opção)

Também protegemos nosso grep da estranha oportunidade de localidade ou caracteres estranhos usando --binary-files=text, e escrevemos nossos xargs de uma maneira mais segura, indicando uma string de substituição e citando a string de substituição.

Para terminar, nós inserimos um adicional grep -o com uma expressão regular que encontra os números 0-9 só. Por isso, mesmo se algum programa tentar trapacear este procedimento matando a linha de comando, seria mais difícil de fazer.

Como uma alternativa interessante para definir uma linha de comando de análise, você também pode dar uma olhada no killall comando:

gnome-calculator &
killall 'gnome-calculator'

Exemplo de uma excitação de comando killall

Para mais informações sobre este comando, você pode entrar no manual usando man killall. a killall O comando também permite que você configure opções como --user para matar apenas os processos pertencentes ao usuário especificado, etc.

Final

Gerenciar processos de várias maneiras nos permite escrever scripts de watchdog de processos, automatizar o gerenciamento de processos, desenvolver melhor código bash multi-threaded, gerenciar processos melhor e mais. Aproveite suas novas habilidades de bash!!

Assine a nossa newsletter

Nós não enviaremos SPAM para você. Nós odiamos isso tanto quanto você.