Tuer un processus et le forcer à retourner 0 sous Linux?

16

Dans l'environnement Linux, comment envoyer un signal d'arrêt à un processus, tout en m'assurant que le code de sortie renvoyé par ce processus est 0? Dois-je faire de la magie GDB pour cela, ou y a-t-il un signal de mise à mort fantaisiste que je ne connais pas?

Cas de test:

cat; echo $?

killall cat

L'essai de divers signaux d'arrêt ne propose que différents signaux de retour, tels que 129, 137 et 143. Mon objectif est de tuer un processus exécuté par un script, mais de faire croire au script qu'il a réussi.

sega01
la source

Réponses:

20

Vous pouvez vous attacher au processus à l'aide de GDB et de l'ID de processus, puis émettre la callcommande avec exit(0)comme argument.

callvous permet d'appeler des fonctions dans le programme en cours d'exécution. L'appel exit(0)quitte avec un code retour de 0.

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

Program exited normally.

En tant qu'outil monoligne:

gdb --batch --eval-command 'call exit(0)' --pid <process id>
LeStarke
la source
Cela ne fonctionnera pas si le programme n'utilise pas (g) libc, par exemple un programme écrit en assembleur: No symbol table is loaded. Use the "file" command. Bien que cela soit hautement improbable.
Cristian Ciupitu
A travaillé sur un script rubis :-D
Mikhail
1
@CristianCiupitu Il existe un moyen de contourner ce problème. À l'entrée de l'appel système suivant, modifiez simplement les registres appropriés pour que le programme cible appelle l' _exitappel système avec 0comme argument. Cela fonctionnera sur n'importe quel processus qui ne consiste pas simplement à boucler et à graver des cycles de processeur. Si le processus ne se trouve pas coincé dans une boucle infinie, vous pouvez toujours utiliser la même approche si vous pouvez trouver les instructions nécessaires quelque part dans son exécutable et y pointer le pointeur d'instructions.
kasperd
@Mikhail cela a fonctionné sur "un script ruby" parce que GDB était connecté au processus d'interprétation ruby ​​dont le binaire était lié à la glibc.
Daniel
@kasperd, oui, je le pensais, mais des instructions plus précises seraient bien.
Cristian Ciupitu
8

Non. Lorsque le shell intercepte, SIGCHLDil définit inconditionnellement la valeur de retour de manière appropriée à une valeur non nulle, donc cela nécessiterait une modification du script ou du shell.

Ignacio Vazquez-Abrams
la source
3

Je ne suis pas sûr, mais cela se terminera par un 0 si l'un des signaux répertoriés est reçu. Vous pouvez effectuer d'autres actions, notamment appeler une fonction, etc.

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

Ce one-liner a fonctionné pour moi:

/bin/bash -c '/usr/bin/killall -q process_name; exit 0'
Landon Thomas
la source
Je ne pense pas que vous ayez compris la question. Il n'y a aucun moyen, cette commande va réaliser ce qui était demandé. Voilà ce que je suis arrivé d'utiliser votre commande: $ cat; echo $? Terminated 143.
kasperd
2
@Landon Thomas, votre ligne de code montrée ici retourne en fait 0. Cependant, le nom_processus qui a été tué ne retourne PAS 0, ce que l'OP voulait.
Daniel
2

Un peu un peu hacky, mais ..

Vous pouvez créer un wrapper pour votre processus, remplaçant le gestionnaire SIGCHLD. Par exemple:

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

Après cela, vous pouvez faire en sorte que votre script exécute ce wrapper au lieu de votre processus en le plaçant plus tôt dans $ PATH et en renommant le même nom.

DukeLion
la source