Trap 'Ctrl + c' per lo script bash ma non per il processo aperto in questo script


11

Ho provato ad avere un programma interattivo in uno script bash:

my_program

E vorrei poterlo chiudere con 'Ctrl + c'. Ma quando lo faccio, anche la mia sceneggiatura si sta chiudendo.

Lo so.

trap '' 2
my_program
trap 2

Ma in questo caso, non riesco proprio a chiudere my_programcon Ctrl + c.

Hai idea di come consentire Ctrl + c su un programma, ma non chiudere lo script eseguendolo?

EDIT: aggiungi esempio

#!/bin/bash
my_program
my_program2

Se uso Ctrl + c per chiudere my_program, my_program2non viene mai eseguito perché l'intero script viene chiuso.

Risposte:


13

Dovresti usare trap true 2o trap : 2invece di trap '' 2. Ecco cosa dice "help trap" in una shell bash a riguardo:

Se ARG è la stringa nulla, ogni SIGNAL_SPEC viene ignorato dalla shell e dai comandi che invoca .

Esempio:

$ cat /tmp/test
#! /bin/sh
trap : INT
cat
echo first cat killed
cat
echo second cat killed
echo done
$ /tmp/test
   <press control-C>
^Cfirst cat killed
   <press control-C>
^Csecond cat killed
done

2
Che ne dici di uccidere tails invece di uccidere gatti la prossima volta?
Kubanczyk,

12

È possibile ripristinare una trap come predefinita dando il comando trap -come argomento dell'azione. Se lo fai in una subshell , ciò non influirà sulla trap nella shell genitore. Nel tuo script, puoi farlo per ogni comando che devi essere interrompibile con Ctrl-C:

#!/bin/bash
# make the shell (and its children) ignore SIGINT
trap '' INT
.
.
.
# but this child won't ignore SIGINT
(trap - INT; my_program)
# the rest of the script is still ignoring SIGINT
.
.
.

1
Sebbene la risposta accettata sia probabilmente migliore e più canonica per la shell, questa è un'ottima risposta in sé in quanto introduce il principio generale (non specifico della shell) su come eseguire questo tipo di mascheramento / ignoramento del segnale in modo sicuro.
R .. GitHub FERMA AIUTANDO ICE

Immagino che tu possa farlo exec my_programnella subshell, per essere leggermente più efficiente.
Toby Speight,

@R .. questo non è assolutamente specifico della shell - se imposti un segnale su SIG_IGN (è quello che sta facendo una trap con una stringa vuota), quello stato verrà ereditato da exec (), ad eccezione di SIGCHLD. Questo è il comportamento obbligatorio di POSIX. Si veda anche la risposta al stackoverflow.com/questions/32708086/...
mosvy

@mosvy: non vedo con quale parte del mio commento non sei d'accordo. Tutto il mio punto era che "maschera / ignora prima del fork, smaschera / annulla nel bambino prima di exec" è un principio generale che è utile conoscere al di fuori del contesto della semplice programmazione della shell.
R .. GitHub smette di aiutare ICE il

1
Questa è una risposta molto utile Come utente Linux esperto, posso dire di non averne mai sentito parlare prima. Ha molti usi ... hai il mio voto e il mio segnalibro.
Dev

-1


Quando usi Crtl+ C, interrompi il programma (" uccidilo ").
Quello che probabilmente stai cercando è di sospendere il tuo programma ( "metterlo in pausa "). Per questo, puoi usare Crtl+ Z.
Una volta che il programma è in pausa, puoi vederlo usando jobs. Ad esempio:
[1]+ Stopped ./foobar
qui ho solo un lavoro, il lavoro n. 1, ma può essercene più di uno: ogni lavoro ha il suo numero.
È possibile controllare il processo sospeso utilizzando una serie di comandi, ad esempio bg, fge kill.
bg %1verrà riavviato lavoro # 1 nel b ack g rotonda
fg %1riavvio volontà lavoro # 1 in f mineraleg round
kill %1ucciderà il lavoro n. 1
Si noti che è possibile utilizzare bge fgsenza argomenti se si dispone di un solo lavoro attivo.


Grazie ma no, vorrei fare Ctrl + c.
Bob Dylan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.