¿Matar un proceso y forzarlo a devolver 0 en Linux?

16

En el entorno Linux, ¿cómo puedo enviar una señal de cierre a un proceso, mientras me aseguro de que el código de salida devuelto por ese proceso sea 0? ¿Tendría que hacer un poco de magia GDB elegante para esto, o hay una señal de muerte elegante que desconozco?

Caso de prueba:

cat; echo $?

killall cat

Probar varias señales de muerte solo ofrece diferentes señales de retorno, como 129, 137 y 143. Mi objetivo es matar un proceso que ejecuta un script, pero hacer que el script piense que fue exitoso.

sega01
fuente

Respuestas:

20

Puede adjuntar al proceso utilizando GDB y la ID del proceso y luego emitir el callcomando exit(0)como argumento.

callle permite llamar a funciones dentro del programa en ejecución. Las llamadas se exit(0)realizan con un código de retorno de 0.

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

Program exited normally.

Como herramienta de una línea:

gdb --batch --eval-command 'call exit(0)' --pid <process id>
LeStarke
fuente
Esto no funcionará si el programa no utiliza (g) libc, por ejemplo, un programa escrito en conjunto: No symbol table is loaded. Use the "file" command. Aunque esto es muy poco probable.
Cristian Ciupitu
Trabajó en un guión de ruby ​​:-D
Mikhail
1
@CristianCiupitu Hay una forma de evitar ese problema. Al ingresar a la siguiente llamada del sistema, simplemente modifique los registros relevantes para que el programa de destino llame a la llamada del _exitsistema con un 0argumento. Eso funcionará en cualquier proceso que no sea simplemente bucle y grabación de ciclos de CPU. Si el proceso no se atasca en un bucle infinito, aún puede usar el mismo enfoque si puede encontrar las instrucciones necesarias en algún lugar de su ejecutable y apuntar el puntero de instrucciones allí.
Kasperd
@Mikhail funcionó en "un script de ruby" porque GDB estaba conectado al proceso de intérprete de ruby ​​cuyo binario estaba vinculado con glibc.
Daniel
@kasperd, sí, eso creo, pero sería mejor tener instrucciones más precisas.
Cristian Ciupitu
8

No. Cuando el shell lo atrapa SIGCHLD, incondicionalmente establece el valor de retorno de manera apropiada en un valor distinto de cero, por lo que esto requeriría la modificación del script o del shell.

Ignacio Vazquez-Abrams
fuente
3

No estoy seguro, pero esto saldrá con un 0 si se recibe alguna de las señales enumeradas. Puede realizar otras acciones, como llamar a una función, etc.

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

Esta frase me funcionó:

/bin/bash -c '/usr/bin/killall -q process_name; exit 0'
Landon Thomas
fuente
No creo que hayas entendido la pregunta. No hay manera, ese comando va a lograr lo que se le pidió. Esto es lo que tengo la utilización de su comando: $ cat; echo $? Terminated 143.
Kasperd
2
@Landon Thomas su línea de código que se muestra aquí de hecho devuelve 0. Sin embargo, el nombre_proceso que se eliminó NO devuelve 0, que es lo que quería el OP.
Daniel
2

Un poco hacky, pero ...

Puede crear un contenedor para su proceso, anulando el controlador SIGCHLD. Por ejemplo:

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

Después de eso, puede hacer que su script ejecute este contenedor en lugar de su proceso al colocarlo anteriormente en $ PATH y cambiarle el nombre al mismo nombre.

DukeLion
fuente