Uccidere un processo e forzarlo a restituire 0 in Linux?


16

In ambiente Linux, come posso inviare un segnale kill a un processo, assicurandomi che il codice di uscita restituito da quel processo sia 0? Dovrei fare un po 'di magia GDB per questo, o c'è un segnale di uccisione di cui non sono a conoscenza?

Caso di prova:

cat; echo $?

killall cat

Provare vari segnali di interruzione offre solo segnali di ritorno diversi, come 129, 137 e 143. Il mio obiettivo è quello di uccidere un processo che viene eseguito uno script, ma far sì che lo script pensi che abbia avuto successo.

Risposte:


20

È possibile collegarsi al processo utilizzando GDB e l'ID processo e quindi emettere il callcomando exit(0)come argomento.

callconsente di chiamare funzioni all'interno del programma in esecuzione. La chiamata viene exit(0)chiusa con un codice di ritorno pari a 0.

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

Program exited normally.

Come strumento a una riga:

gdb --batch --eval-command 'call exit(0)' --pid <process id>

Questo non funziona se il programma non usa (g) libc, ad esempio, un programma scritto in assembly: No symbol table is loaded. Use the "file" command. Anche se questo è altamente improbabile.
Cristian Ciupitu,

Ha lavorato su una sceneggiatura rubino :-D
Mikhail,

1
@CristianCiupitu C'è un modo per aggirare quel problema. Quando si accede alla chiamata di sistema successiva, modificare semplicemente i registri pertinenti per fare in modo che il programma di destinazione chiami la _exitchiamata di sistema 0come argomento. Funzionerà su qualsiasi processo che non è semplicemente loop e masterizzazione dei cicli della CPU. Se il processo non si blocca in un ciclo infinito, puoi comunque utilizzare lo stesso approccio se riesci a trovare le istruzioni necessarie da qualche parte nel suo eseguibile e puntare il puntatore dell'istruzione lì.
Kasperd,

@Mikhail ha funzionato su "uno script ruby" perché GDB era collegato al processo dell'interprete ruby ​​il cui binario era collegato con glibc.
Daniel

@kasperd, sì, penso di sì, ma istruzioni più precise sarebbero carine.
Cristian Ciupitu,

8

No. Quando la shell lo cattura SIGCHLD, imposta incondizionatamente il valore di ritorno in modo appropriato su un valore diverso da zero, quindi ciò richiederebbe la modifica dello script o della shell.


3

Non sono sicuro, ma questo uscirà con uno 0 se viene ricevuto uno qualsiasi dei segnali elencati. È possibile eseguire altre azioni, inclusa la chiamata a una funzione, ecc.

#!/bin/bash 
trap 'exit 0' SIGINT SIGQUIT SIGTERM

3

Questo one-liner ha funzionato per me:

/bin/bash -c '/usr/bin/killall -q process_name; exit 0'

Non credo che tu abbia capito la domanda. Non c'è modo, quel comando otterrà ciò che è stato chiesto. Questo è quello che ho ottenuto usare i tuoi comando: $ cat; echo $? Terminated 143.
Kasperd,

2
@Landon Thomas la tua riga di codice mostrata qui in effetti restituisce 0. Tuttavia il nome_processo che è stato ucciso NON restituisce 0, che è ciò che l'OP voleva.
Daniel

2

Un po 'confuso, ma ...

È possibile creare un wrapper per il processo, ignorando il gestore SIGCHLD. Per esempio:

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

Dopodiché puoi fare in modo che lo script esegua questo wrapper anziché il processo inserendolo precedentemente in $ PATH e rinominandolo con lo stesso nome.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.