Einen Prozess beenden und erzwingen, dass er unter Linux 0 zurückgibt?

16

Wie kann ich in der Linux-Umgebung ein Kill-Signal an einen Prozess senden und gleichzeitig sicherstellen, dass der von diesem Prozess zurückgegebene Exit-Code 0 ist? Müsste ich dafür etwas ausgefallene GDB-Magie machen, oder gibt es ein ausgefallenes Kill-Signal, von dem ich nichts weiß?

Testfall:

cat; echo $?

killall cat

Das Ausprobieren verschiedener Kill-Signale bietet nur unterschiedliche Rückgabesignale, z. B. 129, 137 und 143. Mein Ziel ist es, einen Prozess abzubrechen, der von einem Skript ausgeführt wird, das Skript jedoch für erfolgreich zu halten.

sega01
quelle

Antworten:

20

Sie können mit GDB und der Prozess-ID eine Verbindung zum Prozess herstellen und dann den callBefehl mit exit(0)als Argument ausgeben .

callErmöglicht den Aufruf von Funktionen innerhalb des laufenden Programms. Das Aufrufen von exit(0)Exits erfolgt mit dem Rückkehrcode 0.

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

Program exited normally.

Als einzeiliges Werkzeug:

gdb --batch --eval-command 'call exit(0)' --pid <process id>
LeStarke
quelle
Das wird nicht funktionieren , wenn das Programm nicht verwenden (g) libc, beispielsweise ein Programm in Assembler geschrieben: No symbol table is loaded. Use the "file" command. Dies ist jedoch höchst unwahrscheinlich.
Cristian Ciupitu
Arbeitete an einem Rubinskript :-D
Mikhail
1
@CristianCiupitu Es gibt einen Weg, um dieses Problem zu umgehen. Ändern Sie beim Eintritt in den nächsten Systemaufruf einfach die entsprechenden Register, damit das Zielprogramm den _exitSystemaufruf mit 0als Argument aufruft. Das funktioniert bei jedem Prozess, der nicht nur CPU-Zyklen durchläuft und brennt. Wenn sich der Prozess nicht in einer Endlosschleife befindet, können Sie den gleichen Ansatz verwenden, wenn Sie die erforderlichen Anweisungen irgendwo in der ausführbaren Datei finden und den Anweisungszeiger dorthin zeigen.
Kasperd
@Mikhail es funktionierte auf "einem Ruby-Skript", weil GDB mit dem Ruby-Interpreter-Prozess verbunden war, dessen Binärdatei mit glibc verknüpft war.
Daniel
@kasperd, ja, ich denke schon, aber genauere Anweisungen wären nett.
Cristian Ciupitu
8

Nein. Wenn die Shell SIGCHLDsie bedingungslos abfängt, setzt sie den Rückgabewert entsprechend auf einen Wert ungleich Null. Dies würde daher eine Änderung des Skripts oder der Shell erfordern.

Ignacio Vazquez-Abrams
quelle
3

Ich bin nicht sicher, aber dies wird mit einer 0 beendet, wenn eines der aufgelisteten Signale empfangen wird. Sie können auch andere Aktionen ausführen, z. B. das Aufrufen einer Funktion usw.

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

Dieser Einzeiler arbeitete für mich:

/bin/bash -c '/usr/bin/killall -q process_name; exit 0'
Landon Thomas
quelle
Ich glaube nicht, dass Sie die Frage verstanden haben. Dieser Befehl wird auf keinen Fall das erreichen, wonach er gefragt wurde. Dies ist , was ich aus mit Ihrem Befehl bekam: $ cat; echo $? Terminated 143.
Kasperd
2
@Landon Thomas Ihre hier gezeigte Codezeile gibt tatsächlich 0 zurück. Der Prozessname, der getötet wurde, gibt jedoch NICHT 0 zurück, was das OP wollte.
Daniel
2

Ein bisschen verrückt, aber ..

Sie können einen Wrapper für Ihren Prozess erstellen, der den SIGCHLD-Handler überschreibt. Beispielsweise:

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

Danach können Sie Ihr Skript veranlassen, diesen Wrapper anstelle Ihres Prozesses auszuführen, indem Sie ihn früher in $ PATH einfügen und in denselben Namen umbenennen.

DukeLion
quelle