Das scheint zu funktionieren:
#!/bin/sh
pressed_ctrl_c=
trap "pressed_ctrl_c=1" INT
while true
do
(trap "" INT; foo)&
wait || wait
if [ "$pressed_ctrl_c" ]
then
# echo
break
fi
done
- Auf
pressed_ctrl_cnull initialisieren . Dies ist in einem Skript wahrscheinlich nicht erforderlich.
trap command signumWeist die Shell an, die Signalnummer abzufangen signum
und auszuführen, commandwenn sie eine abfängt. "INT" steht für "SIGINT", was für "Interrupt Signal" steht. Dies ist der Fachbegriff für das von Ctrl+ erzeugte Signal. CWenn Sie also Ctrl+ eingeben C, wird die Shell pressed_ctrl_cauf 1 gesetzt. (SIGINT hat einen numerischen Wert von 2, so können Sie sagen, trap "pressed_ctrl_c=1" 2ob Sie beim Tippen sparen möchten.)
- Innerhalb der Schleife haben wir eine Befehlszeile in Klammern. Dadurch wird eine Unterschale erstellt.
- Wir verwenden den
trapBefehl erneut. Diese Zeit commandist eine Nullzeichenfolge. Dies weist die Shell an, die Signalnummer zu ignorieren signum. Da dies in Klammern steht, betrifft es nur die Unterschale.
- Ausführen
foo. Da es von der Subshell ausgeführt wurde, foowird Ctrl+ ignoriert C, dh es wird auch dann weiter ausgeführt, wenn Sie es eingeben
.
- Stellen Sie die Unterschale in den Hintergrund….
- … Und warten Sie, bis es fertig ist.
- Wenn der
waitBefehl erfolgreich ist, fahren Sie mit der ifAnweisung fort. Wenn dies fehlschlägt, führen Sie einen anderen aus. (Ich werde darauf zurückkommen.)
- Wenn
$pressed_ctrl_ceingestellt, aus der Schleife ausbrechen. Kommentieren Sie optional den echoBefehl aus, wenn Ctrl+ Cauf Ihrem Terminal als angezeigt wird ^C
und Sie zur nächsten Zeile wechseln möchten.
Wir führen einen Befehl im Hintergrund aus und dann sofort waitdafür. Dies ist dem Ausführen des Befehls im Vordergrund sehr ähnlich (zumindest wenn dies in einem Skript ausgeführt wird). Der waitBefehl wird erfolgreich beendet, wenn die Subshell beendet wird. dh wenn der fooBefehl beendet wird. (Der waitBefehl wird erfolgreich beendet, auch wenn fooein Fehler zurückgegeben wird.) Wenn der erste waitBefehl erfolgreich beendet wird, überspringen wir den zweiten und gehen zum if.
Die Shell, die die Schleife ausführt, fängt Interrupts ab, aber die Subshell und damit der fooProzess ignorieren sie. Wenn Sie also Ctrl+ eingeben C, wird die Shell pressed_ctrl_cauf 1 gesetzt und der (erste) waitBefehl abgebrochen . Da der erste waitBefehl fehlgeschlagen ist, fahren wir mit dem zweiten fort. Denken Sie daran, dass die fooSubshell noch ausgeführt wird, sodass dies waitnoch etwas zu tun hat (dh es wird gewartet , bis die Subshell foofertig ist.)
Wenn die Variable so eingestellt wurde, dass angezeigt wird, dass während der Ausführung ein Ctrl+ Cgedrückt foowurde, wird die Schleife unterbrochen.
Wenn Sie zweimal Ctrl+ drücken C, unterbricht der zweite den zweiten waitBefehl und bricht ihn ab . Dadurch wird Ihr Skript beendet und Sie kehren zu Ihrer Shell-Eingabeaufforderung zurück, während es fooim Hintergrund ausgeführt wird. Sie können dies abmildern, indem Sie sagen wait || wait || wait || wait: Erweitern Sie es so weit wie Sie möchten. Sie müssten jeweils Ctrl+ Ceinmal eingeben, wait
um das Skript vorzeitig zu beenden.
D'oh!
Ein Problem dabei ist, dass für Prozesse, die von einem Skript in den Hintergrund gestellt werden, die Standardeingabe auf gesetzt ist /dev/null. Wenn Sie foovon der Tastatur lesen, muss das oben genannte überarbeitet werden.