Mam polecenie, które chcę uruchamiać ponownie automatycznie za każdym razem, gdy się kończy, więc uruchomiłem coś takiego:
while [ 1 ]; do COMMAND; done;
ale jeśli nie mogę „zatrzymać pętli za pomocą Ctrl-c , ponieważ to po prostu zabija COMMAND
a nie całą pętlę.
Jak osiągnąć coś podobnego, ale co mogę zatrzymać bez konieczności zamykania terminala?
Komentarze
- Jeśli ' m in bash, po prostu używam Ctrl-Z, aby zatrzymać zadanie, a następnie ” zabijam% 1 „, aby go zabić.
- Poczekaj … Linus został zacytowany jako powiedział: „Wszyscy wiemy, że Linux jest świetny … robi nieskończone pętle w 5 sekund. ” – tak naprawdę … poczekaj jeszcze kilka sekund, powinno się zakończyć.
- @PaulCager też zadziałało! Dlaczego działa tam, gdzie Ctrl-C robi nie?
- @cirosantilli zabija zewnętrzną pracę (bash ” wrapper „). W niektórych sytuacjach wygrał na przykład ' t natychmiastowo zabił ” COMMAND ” , jeśli umieścisz go w tle, może przemknąć obok żywego, nawet jeśli rodzic ' nie żyje. Ale pętla jest martwa i to ' jest ważną częścią.
Odpowiedź
Sprawdź status zakończenia polecenia. Jeśli polecenie zostało zakończone sygnałem, kod wyjścia będzie wynosił 128 + numer sygnału. Z dokumentacji online GNU dla bash :
Do celów powłoki polecenie która kończy się z zerowym kodem zakończenia, powiodła się. Niezerowy status wyjścia oznacza błąd. Ten pozornie sprzeczny z intuicją schemat jest używany, więc istnieje jeden dobrze zdefiniowany sposób wskazywania sukcesu i wiele sposobów wskazywania różnych trybów awarii. Kiedy polecenie kończy się krytycznym sygnałem o numerze N, Bash używa wartości 128 + N jako kodu wyjścia.
POSIX określa również , że wartość polecenia zakończonego sygnałem jest większa niż 128, ale nie wydaje się określać jego dokładnej wartości, tak jak robi to GNU:
Status wyjścia polecenia, które zostało zakończone z powodu odebrania sygnału, będzie zgłoszony jako większy niż 128.
Na przykład, jeśli przerwiesz polecenie za pomocą control-C, kod wyjścia będzie wynosił 130, ponieważ SIGINT jest sygnałem 2 w systemach Unix. A więc:
while [ 1 ]; do COMMAND; test $? -gt 128 && break; done
Komentarze
Odpowiedź
Możesz zatrzymać pracę i umieścić ją w tle podczas jej działania, używając ctrl + z . Następnie możesz możesz zabić swoją pracę:
$ kill %1
Gdzie [1] to Twój numer pracy.
Komentarze
- Zobacz także tę odpowiedź , aby uzyskać wyjaśnienia i nie tylko.
- Ta stosunkowo nowa odpowiedź po prostu działa. Musi być głosowano. +1
- Bardzo mi pomogłeś. Właśnie tego szukałem w tym pytaniu 🙂
Odpowiedź
Powiedziałbym, że najlepiej byłoby umieścić nieskończoną pętlę w skrypcie i tam obsługiwać sygnały. Oto podstawowy punkt wyjścia . Jestem pewien, że zechcesz go zmodyfikować, aby pasował. Skrypt używa trap
do przechwytywania ctrl – c (lub SIGTERM
), wyłącza polecenie (użyłem tutaj sleep
w ramach testu) i kończy pracę.
cleanup () { kill -s SIGTERM $! exit 0 } trap cleanup SIGINT SIGTERM while [ 1 ] do sleep 60 & wait $! done
Komentarze
- Świetnie. Oto ' jak wykorzystałem tę wskazówkę, aby utworzyć opakowanie netcat z automatycznym uruchomieniem:
trap "exit 0" SIGINT SIGTERM; while true; do netcat -l -p 3000; done
- jeśli dodasz to
trap
podejście do tego samego skryptu (bash) z nieskończoną pętlą do zabicia, użyj$$
zamiast$!
(patrz tutaj )
Odpowiedź
Generalnie po prostu przytrzymuję klawisz Ctrl-C . Wcześniej czy później „zarejestruję się między COMMAND
” s iw ten sposób zakończ pętlę while
. Może jest lepszy sposób.
Komentarze
- Nie wiem dlaczego, ale nie udaje się to w przypadku niektórych POLECEŃ, takich jak
paplay
w pliku 1s . - U mnie zadziałało
- To ' jest brutalną siłą wszystkich rozwiązań tutaj. : /
Odpowiedź
Jeśli uruchomisz bash z -e
zakończy działanie w przypadku każdego błędu:
#!/bin/bash -e false # returns 1 echo This won"t be printed
Komentarze
- Pierwsza linia jest zdecydowanie najprostsze rozwiązanie dla trywialnego skryptu, nad którym ' nie chcesz spędzać zbyt dużo czasu!
Odpowiedź
Dlaczego nie po prostu
while [ 1 ]; do COMMAND || break; done;
Lub w przypadku użycia w skrypcie
#!/bin/bash while [ 1 ]; do # ctrl+c terminates COMMAND and exits the while loop # (assuming COMMAND responds to ctrl+c) COMMAND || break done;
Komentarze
- Bardzo eleganckie rozwiązanie. Ale czy ' t nie zadziała tylko wtedy, gdy COMMAND zawsze zwraca status wyjścia sukcesu?
- Tak @howardh, że ' jest poprawne.
Odpowiedź
- Zawsze możesz zabić proces używając jego PID, tam ” Nie ma potrzeby zamykania terminala
- Jeśli chcesz uruchomić coś w nieskończonej pętli, jak demon, najlepiej umieścić to w tle
-
while :
utworzy nieskończoną pętlę i zaoszczędzi ci pisania[ 1 ]
while :; do COMMAND; done &
Spowoduje to wydrukowanie PID. Jeśli wyjdziesz z monitu za pomocą ctrl+d
, wtedy zadanie w tle nie zostanie zakończone i możesz później zabić je z dowolnego miejsca za pomocą kill PID
Jeśli zgubisz swój PID, możesz użyć pstree -pa $USER
lub pgrep -fl ".*PROCESS.*"
, które pomogą Ci go znaleźć
Odpowiedź
Wolę inne rozwiązanie:
touch .runcmd; while [ -f ".runcmd" ]; do COMMAND; sleep 1; done
Aby aby zakończyć pętlę, po prostu zrób:
rm .runcmd && kill `pidof COMMAND`
Odpowiedź
Co działa rozsądnie dobrze dla mnie jest:
while sleep 1; do COMMAND; done
To działa, ponieważ sen 1 trzyma się while i jeśli otrzyma ctrl + c, zwróci wartość niezerową, a pętla się zakończy.
Komentarze
- +1, czas uśpienia również może być zredukowana do
0.5
lub0.1
:while sleep 0.1; do COMMAND; done
Odpowiedź
Użyj trap
–
exit_() { exit } while true do echo "running.." trap exit_ int done
paplay alert.ogg
, być może dlatego, żepaplay
obsługuje sygnał?