Pułapka „Ctrl + c” dla skryptu bash, ale nie dla procesu otwartego w tym skrypcie

11

Próbowałem mieć program interaktywny w skrypcie bash:

my_program

I chcę móc go zamknąć za pomocą „Ctrl + c”. Ale kiedy to robię, mój skrypt również się zamyka.

Wiem o.

trap '' 2
my_program
trap 2

Ale w tym przypadku po prostu nie mogę zamknąć za my_programpomocą Ctrl + c.

Czy masz pomysł, jak zezwolić Ctrl + c na program, ale nie zamykasz skryptu, który go uruchamia?

EDYCJA: dodaj przykład

#!/bin/bash
my_program
my_program2

Jeśli używam Ctrl + c do zamknięcia my_program, my_program2nigdy nie jest wykonywany, ponieważ cały skrypt jest zamknięty.

Bob Dylan
źródło

Odpowiedzi:

13

Powinieneś użyć trap true 2lub trap : 2zamiast trap '' 2. Tak mówi o tym „help trap” w powłoce bash:

Jeśli ARG jest łańcuchem zerowym, każdy SIGNAL_SPEC jest ignorowany przez powłokę i polecenia, które wywołuje .

Przykład:

$ 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
mosvy
źródło
2
Co powiesz na zabijanie tailzamiast zabijania kotów następnym razem?
kubańczyk
12

Możesz zresetować pułapkę do wartości domyślnej, podając komendę trap -jako argument akcji. Jeśli zrobisz to w podpowłoce , nie wpłynie to na pułapkę w powłoce nadrzędnej. W swoim skrypcie możesz to zrobić dla każdego polecenia, które musisz przerwać za pomocą 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
.
.
.
Mark Plotnick
źródło
1
Chociaż przyjęta odpowiedź jest prawdopodobnie lepsza i bardziej kanoniczna dla powłoki, sama w sobie jest świetną odpowiedzią, ponieważ wprowadza ogólną zasadę (nie specyficzną dla powłoki) dotyczącą bezpiecznego wykonywania tego rodzaju maskowania / ignorowania sygnału.
R .. GitHub ZATRZYMAJ LÓD
Myślę, że możesz to zrobić exec my_programw podpowłoce, aby być nieco bardziej wydajnym.
Toby Speight,
@R .. to absolutnie nie jest specyficzne dla powłoki - jeśli ustawisz sygnał na SIG_IGN (to robi pułapka z pustym łańcuchem), stan ten zostanie odziedziczony przez exec (), z wyjątkiem SIGCHLD. Takie jest zachowanie obowiązkowe POSIX. Zobacz także odpowiedź na stackoverflow.com/questions/32708086/...
mosvy
@mosvy: Nie rozumiem, z jaką częścią mojego komentarza się nie zgadzasz. Chodzi mi o to, że „maskowanie / ignorowanie przed rozwidleniem, demaskowanie / ignorowanie w dziecku przed wykonaniem” jest ogólną zasadą, którą warto znać poza kontekstem programowania powłoki.
R .. GitHub ZATRZYMAJ LÓD
1
To bardzo przydatna odpowiedź. Jako doświadczony użytkownik Linuksa mogę powiedzieć, że nigdy wcześniej o tym nie słyszałem. Ma wiele zastosowań ... masz moją opinię i moją zakładkę.
Dev
-1


Kiedy używasz Crtl+ C, przerywasz program („ zabijasz ” go).
Prawdopodobnie szukasz zawieszenia programu („ wstrzymaj ” go). W tym celu możesz użyć Crtl+ Z.
Po wstrzymaniu programu możesz go zobaczyć za pomocą jobs. Na przykład:
[1]+ Stopped ./foobar
tutaj mam tylko jedno zadanie, zadanie nr 1, ale może istnieć więcej niż jedno - każde zadanie ma swój własny numer.
Można kontrolować Ci zawieszony proces stosując szereg poleceń, na przykład bg, fgi kill.
bg %1ponownie uruchomi pracy nr 1 w b ACK g okrągły
fg %1nastąpi ponowne uruchomienie pracy # 1 w f rudyg runda
kill %1zabije przydzielonego stanowiska nr 1
Uwaga, które można wykorzystać bgi fgbez argumentów, jeśli masz tylko jedną aktywną pracę.

pi0tr
źródło
Dziękuję, ale nie, chcę zrobić Ctrl + c.
Bob Dylan