forward signal to sudo child

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
patdexx
Beiträge: 9
Registriert: 03.04.2017 09:26:22

forward signal to sudo child

Beitrag von patdexx » 29.06.2017 13:02:44

Hallo,

ich möchte gerne Signale eines Skripts mit Userrechten an einen Kindprozess weiterleiten, welcher mit sudo gestartet wurde.
Das folgende Beispiel funktioniert leider nicht. Der 'signal_handler_parent' wird ausgeführt, der des Kindes jedoch nicht.
Starte ich 'sudo test_child.sh' direkt, wird der signal_handler_child wie gewünscht ausgeführt.

Wo ist das Problem?

test_parent.sh:

Code: Alles auswählen

#!/bin/bash

set -x

signal_handler_parent() { 
  sudo kill -s SIGINT $CHILD_PID
}

trap signal_handler_parent SIGINT

sudo ./test_child.sh &

CHILD_PID=$! 
wait $CHILD_PID
test_child.sh:

Code: Alles auswählen

#!/bin/bash

set -x

signal_handler_child() {
    exit 0
}

trap signal_handler_child SIGINT

while sleep 1; do
    date
done

Benutzeravatar
MSfree
Beiträge: 10685
Registriert: 25.09.2007 19:59:30

Re: forward signal to sudo child

Beitrag von MSfree » 29.06.2017 14:22:17

patdexx hat geschrieben:Wo ist das Problem?
Ein Prozeß mit geringen Privilegien (Userprozeß) darf einem Prozeß mit höheren Privilegien (sudo Prozeß) keine Signale schicken.

Benutzeravatar
patdexx
Beiträge: 9
Registriert: 03.04.2017 09:26:22

Re: forward signal to sudo child

Beitrag von patdexx » 29.06.2017 14:52:18

Ja das ist klar, deshalb verwende ich 'sudo kill ...'!

Starte ich das 'test_child.sh' in einer konsole, kann ich mit 'sudo kill ..' auch Signale schicken.
Sobald ich aber das 'test_parent.sh' Skript nutzte um 'test_child.sh' zu starten, kann ich egal wie kein SIGINT senden. (auch nicht aus der Konsole)

Benutzeravatar
patdexx
Beiträge: 9
Registriert: 03.04.2017 09:26:22

Re: forward signal to sudo child

Beitrag von patdexx » 29.06.2017 15:01:30

Ich bin nun ein Stückchen weiter:

Die CHILD_PID ist nicht korrekt. 'sudo' öffnet scheinbar eine weiter Subshell.
Mit der korrekten PID kann ich nun SIGTERM an den Kindprozess senden. SIGINT leider nicht.

TomL

Re: forward signal to sudo child

Beitrag von TomL » 29.06.2017 15:11:16

patdexx hat geschrieben:Die CHILD_PID ist nicht korrekt.
Die ganze Programmlogik ist meines Erachtens nicht korrekt. Besser sieht der Child-Prozess so aus:

Code: Alles auswählen

#!/bin/bash

trap SIGTERM

while true; do
    sleep 1h &
    /bin/echo "$!" >"pidfile"
    wait 2> /dev/null

    [ ! -f "pidfile" ] && break
done

echo "alles aufgeräumt und ordentlich beendet"

exit 0
Vom Parent-Prozess kannst Du dann den Child-Prozess einfach beenden:

Code: Alles auswählen

pid=$(/bin/cat "pidfile)
/bin/rm "pidfile"
/bin/kill -SIGTERM $pid

Benutzeravatar
patdexx
Beiträge: 9
Registriert: 03.04.2017 09:26:22

Re: forward signal to sudo child

Beitrag von patdexx » 29.06.2017 15:42:55

Danke für den Hinweis mit dem 'pidfile'! Die parent -> sudo_child -> child pid bekommt man auch wie folgt raus:

Ich habe jetzt folgende Lösung:

test_parent.sh

Code: Alles auswählen

#!/bin/bash

set -x

signal_handler_parent() { 

    CHILD_PID=$(pgrep -P $SUDO_PID)
    sudo kill -SIGUSR1 $CHILD_PID
    
    wait $SUDO_PID
    exit
}

trap signal_handler_parent SIGINT

sudo /home/walter/scripts/test_child.sh &

SUDO_PID=$!
wait $SUDO_PID
test_child.sh:

Code: Alles auswählen

#!/bin/bash

set -x

signal_handler_child() { 
    exit
}

trap signal_handler_child SIGUSR1

while sleep 1; do
    date
done
Nur leider kann ich kein SIGINT schicken!?

TomL

Re: forward signal to sudo child

Beitrag von TomL » 29.06.2017 21:34:07

patdexx hat geschrieben:Nur leider kann ich kein SIGINT schicken!?
Weil Du bedauerlicherweise meine Lösung nicht verstanden hast. Du kannst mit pgrep zwar die Child-PID abfragen, aber der SIGINT verpufft einfach, weil das Programm fast immer im Sleep festhängt, was ein eigener Prozess ist.... und die Sleep-PID kannst Du nicht eindeutig identifizieren, weil es eben durchaus auch andere Sleeps geben könnte. Und wenn Du dann wahllos killst, ... na dann mal viel glück.....

Wie gesagt, beschäftige Dich mit meiner Lösung... die funktioniert... wobei ich allerdings den Zyklus von 1 Sekunde in Frage stelle... ob das wirklich so kurz so sein muss....

breakthewall
Beiträge: 507
Registriert: 30.12.2016 23:48:51

Re: forward signal to sudo child

Beitrag von breakthewall » 30.06.2017 03:24:21

patdexx hat geschrieben:

Code: Alles auswählen

trap signal_handler_parent SIGINT
So funktioniert eine trap nicht.

Die muss immer so aussehen:

Code: Alles auswählen

trap 'command; command' Signal
Es müssen Singlequotes benutzt werden, um klar abzugrenzen was hier bei entsprechenden Signalen auszuführen ist. Die Singlequotes sorgen ebenfalls dafür, dass der Inhalt erst beim Auslösen der trap aufgelöst wird, was besonders wichtig ist bei zeit-kritischen Aufgaben um bspw. Prozesse anhand von PIDs zu beenden. Des weiteren kann man unter der Bash auch das Pseudosignal EXIT verwenden, was die trap in jedem Fall auslöst, sollte das Shellscript auf welche Art auch immer beendet werden. Davon ausgeschlossen sind SIGKILL und SIGSTOP, da man beide Signale nicht abfangen kann. Auch sollte eine trap am Anfang eines Shellscriptes stehen, da sie ohnehin erst später aufgelöst wird. Zwar wird gerne empfohlen mit SIGUSR1 und SIGUSR2 zu arbeiten, doch meiner Erfahrung nach ist das nicht wirklich zuverlässig. Je nach Prozess muss es wirklich ein SIGTERM oder gar ein SIGKILL sein, um wirklich garantiert dafür zu sorgen das der Prozess beendet wird. Besonders dann wenn es um sensible Informationen geht, kann man nicht riskieren das hier noch ein hängender Prozess im Arbeitsspeicher hängt.

Benutzeravatar
patdexx
Beiträge: 9
Registriert: 03.04.2017 09:26:22

Re: forward signal to sudo child

Beitrag von patdexx » 30.06.2017 09:20:00

Ersteinmal vielen Dank für die Hilfeversuche.

Leider bringen mich die bisherigen Lösungsvorschläge nicht weiter.
Da sie entweder an meinem Problem vorbei gehen oder gar Falsch sind.

Meine Skripte funktionieren in der letzten geposteten Version genau wie ich es möchte.
Tausche ich jedoch SIGUSR1 zu SIGINT, wird dieses Signal im Kindprozess nicht mehr abgefangen. (bzw. der signal handler wird nicht ausgeführt...)
Das Problem scheint zu sein, das SIGINT einfach nicht an Hintergrundprozesse gesendet werden kann...
breakthewall hat geschrieben:
patdexx hat geschrieben:

Code: Alles auswählen

trap signal_handler_parent SIGINT
So funktioniert eine trap nicht.

Die muss immer so aussehen:

Code: Alles auswählen

trap 'command; command' Signal
Die Syntax ist korrekt, es handelt sich bei dem signal_handler_parent um eine Funktion.

TomL hat geschrieben:
patdexx hat geschrieben:Nur leider kann ich kein SIGINT schicken!?
Weil Du bedauerlicherweise meine Lösung nicht verstanden hast. Du kannst mit pgrep zwar die Child-PID abfragen, aber der SIGINT verpufft einfach, weil das Programm fast immer im Sleep festhängt, was ein eigener Prozess ist.... und die Sleep-PID kannst Du nicht eindeutig identifizieren, weil es eben durchaus auch andere Sleeps geben könnte. Und wenn Du dann wahllos killst, ... na dann mal viel glück.....

Wie gesagt, beschäftige Dich mit meiner Lösung... die funktioniert... wobei ich allerdings den Zyklus von 1 Sekunde in Frage stelle... ob das wirklich so kurz so sein muss....
Ich möchte bestimmte Signale an konkreter Stelle abfangen und nicht Prozesse beenden.
Warum sollte SIGINT verpuffen und SIGUSR1 nicht? (mit SIGTERM werden meine Skripte auch beendet)

TomL

Re: forward signal to sudo child

Beitrag von TomL » 30.06.2017 09:58:33

patdexx hat geschrieben:Ich möchte bestimmte Signale an konkreter Stelle abfangen und nicht Prozesse beenden.
Mein Vorschlag beendet NUR den Sleep, NICHT den Child-Prozess. Du hast die Funktion leider noch nicht verstanden.... schau sie dir an, teste es, oder lass es.... ich kann Dir nicht weiter helfen. Fakt ist, meine Funktion arbeitet so, wie Du es eigentlich haben willst.
Warum sollte SIGINT verpuffen
Weil der Childprozess das Signal bekommt, während er gar nicht aktiv ist und keine Kontrolle hat... "sleep" ist der aktive Prozess mit eigener PID und hat die Kontrolle.... und das fast durchgehend. Genau das Problem löst mein Beispiel, indem ich sleep in den Hintergrund schicke.

Benutzeravatar
patdexx
Beiträge: 9
Registriert: 03.04.2017 09:26:22

Re: forward signal to sudo child

Beitrag von patdexx » 30.06.2017 16:04:36

TomL hat geschrieben: Fakt ist, meine Funktion arbeitet so, wie Du es eigentlich haben willst.
Leider ganz und garnicht. Die Funktion arbeitet nicht unter meinen Randbedingungen. SIGINT kann nicht an Hintergrund Prozesse geschickt werden.
Der Hinweis, das sleep die trap blockiert ist korrekt, jedoch sollte spätestens eine Sekunde danach das Signal behandelt werden (siehe mein funktionierendes Beispiel mit SIGUSR1)

Aktueller Code:

test_parent.sh:

Code: Alles auswählen

#!/bin/bash

set -x

signal_handler_parent() { 

    CHILD_PID=$(pgrep -P $SUDO_PID)
    sudo kill -SIGUSR1 $CHILD_PID  # wird im child erkannt
    # sudo kill -SIGINT $CHILD_PID  # wird nicht im child erkannt
    
    wait $SUDO_PID
    exit
}

trap signal_handler_parent SIGINT

sudo ./test_child.sh &

SUDO_PID=$!
wait $SUDO_PID
test_child.sh:

Code: Alles auswählen

#!/bin/bash

signal_handler_child() {
    date
}

trap signal_handler_child SIGUSR1 SIGINT

while true; do
    sleep 100 &
    wait $!
done
Zuletzt geändert von patdexx am 30.06.2017 16:23:41, insgesamt 1-mal geändert.

TomL

Re: forward signal to sudo child

Beitrag von TomL » 30.06.2017 16:20:17

patdexx hat geschrieben:Leider ganz und garnicht. Die Funktion arbeitet nicht unter meinen Randbedingungen. SIGINT kann nicht an Hintergrund Prozesse geschickt werden.
Genau, deswegen sende ich ein SIGTERM an den wartenden Sleep und nicht SIGINT an den Childprozess. Nur Sleep wird beendet, Child läuft weiter oder wird beendet.... gemäß dessen, was Du danach vereinbarst bzw. vorgibst. Ich glaube, Du hast es immer noch nicht verstanden. :D Statt zu lamentieren, solltest Du einfach die Lösung einmal testen.Du brauchst bei diesem von dir gezeigten Beispiel definitiv KEINEN IRQ-Handler im Child-Prozess, nur der TRAP ist ausreichend, damit der Sleep beendet werden kann.

Benutzeravatar
patdexx
Beiträge: 9
Registriert: 03.04.2017 09:26:22

Re: forward signal to sudo child

Beitrag von patdexx » 30.06.2017 16:26:04

Ich will am Child ein Signal (konkret SIGINT) abarbeiten und nicht merken, dass irgendetwas sleep beendet hat und vorher dessen pid file gelöscht hat.

Antworte mir doch lieber auf meine Frage:
Warum funktionieren meine Skripte mit SIGUSR1 und nicht mit SIGINT an oben markierter Stelle?

TomL

Re: forward signal to sudo child

Beitrag von TomL » 30.06.2017 16:37:42

patdexx hat geschrieben:Ich will am Child ein Signal (konkret SIGINT) abarbeiten und nicht merken, dass irgendetwas sleep beendet hat und vorher dessen pid file gelöscht hat.
Wenn sleep beendet wurde, ist der inhalt des PID-Files osbsolet. Ich verwende das Löschen nur als "Pseudo-Nachricht", damit "child" sich ordungsgemäß beendet.... weil es ansonsten über den Loop wieder in einen erneuten Sleep-Wartezustand gehen würde und dabei ein neues PID-File erzeugt. Und so wie ich das verstanden habe, soll Dein SIGINT ja auch den Sleep beenden, um dann etwas anderes zu tun. Und genau das geht eben mit meinem Beispiel.

Aber wenn Du zwingend auf ein SIGINT bestehst, was m.E. in dem hier gezeigten Beispiel völlig unnötig ist, wirst Du wohl auf "sleep" verzichten und innerhalb des Scriptes "rotieren" müssen. Dann gibts keinen zusätzlichen Hintergrundprozess, alle Verantwortung liegt im Script und das Script kriegt die SIGs mit. Allerdings wird sich dann die CPU-Last bei 100% einpendeln. Probiers einfach, ich denke, dass es gehen wird. Der Nachteil ist, anstatt "idle" läuft der Rechner dann permanent unter Volllast. Dabei müsste man aber ggf. die Temperatur im Auge behalten.
Warum funktionieren meine Skripte mit SIGUSR1 und nicht mit SIGINT an oben markierter Stelle?
Keine Ahnung, weiss ich nicht... ich freu mich, wenn Du eine Lösung gefunden hast und die kurz hier posten würdest. Ich lerne immer gerne dazu.

Benutzeravatar
patdexx
Beiträge: 9
Registriert: 03.04.2017 09:26:22

Re: forward signal to sudo child

Beitrag von patdexx » 30.06.2017 17:07:41

Die Skripte sind ein Minimalbeispiel. Das Child ist real binary...

Antworten