Matar um processo e forçá-lo a retornar 0 no Linux?

16

No ambiente Linux, como posso enviar um sinal de interrupção para um processo, certificando-me de que o código de saída retornado desse processo seja 0? Eu teria que fazer alguma mágica extravagante do GDB para isso, ou há um sinal de matança extravagante que eu desconheço?

Caso de teste:

cat; echo $?

killall cat

Tentar vários sinais de interrupção oferece apenas sinais de retorno diferentes, como 129, 137 e 143. Meu objetivo é interromper um processo executado por um script, mas fazer com que o script pense que foi bem-sucedido.

sega01
fonte

Respostas:

20

Você pode se conectar ao processo usando o GDB e o ID do processo e, em seguida, emitir o callcomando exit(0)como argumento.

callpermite chamar funções dentro do programa em execução. A exit(0)saída de chamada com um código de retorno 0.

gdb -p <process name>
....
.... Gdb output clipped
(gdb) call exit(0)

Program exited normally.

Como ferramenta de uma linha:

gdb --batch --eval-command 'call exit(0)' --pid <process id>
LeStarke
fonte
Isso não vai funcionar se o programa não usa (g) libc, por exemplo, um programa escrito em assembly: No symbol table is loaded. Use the "file" command. Embora isso seja altamente improvável.
Cristian Ciupitu
Trabalhou em um script ruby ​​:-D
Mikhail
11
@CristianCiupitu Existe uma maneira de contornar esse problema. Na entrada para a próxima chamada do sistema, modifique os registros relevantes para fazer com que o programa de destino chame a chamada do _exitsistema 0como argumento. Isso funcionará em qualquer processo que não seja simplesmente loop e queima de ciclos da CPU. Se o processo não ficar preso em um loop infinito, você ainda poderá usar a mesma abordagem se encontrar as instruções necessárias em algum lugar do executável e apontar o ponteiro para as instruções.
kasperd
@ Mikhail, ele trabalhou em "um script ruby" porque o GDB estava conectado ao processo de intérprete ruby ​​cujo binário estava vinculado à glibc.
Daniel
@ Kasperd, sim, acho que sim, mas instruções mais precisas seriam boas.
Cristian Ciupitu
8

Não. Quando o shell o captura, SIGCHLDele define incondicionalmente o valor de retorno adequadamente como um valor diferente de zero, portanto, isso exigiria modificações no script ou no shell.

Ignacio Vazquez-Abrams
fonte
3

Não tenho certeza, mas isso sairá com 0 se algum dos sinais listados for recebido. Você pode executar outras ações, incluindo chamar uma função, etc.

#!/bin/bash 
trap 'exit 0' SIGINT SIGQUIT SIGTERM
TBI Infotech
fonte
3

Este one-liner trabalhou para mim:

/bin/bash -c '/usr/bin/killall -q process_name; exit 0'
Landon Thomas
fonte
Eu não acho que você entendeu a pergunta. Não há como esse comando alcançar o que estava sendo solicitado. Isto é o que eu tenho de usar a sua comando: $ cat; echo $? Terminated 143.
kasperd
2
@Landon Thomas, sua linha de código mostrada aqui na verdade retorna 0. No entanto, o process_name que foi morto NÃO retorna 0, que é o que o OP queria.
Daniel
2

Um pouco hacky, mas ..

Você pode criar um wrapper para o seu processo, substituindo o SIGCHLD Handler. Por exemplo:

#!/bin/bash
set -o monitor
trap 'exit(0)' CHLD
/some/dir/yourcommand

Depois disso, você pode fazer seu script executando esse wrapper em vez de seu processo, colocando-o anteriormente em $ PATH e renomeando para o mesmo nome.

DukeLion
fonte