Am o comandă pe care vreau să o rulez automat de fiecare dată când se termină, așa că am rulat așa ceva:
while [ 1 ]; do COMMAND; done;
dar dacă nu pot „opri bucla cu Ctrl-c deoarece asta ucide doar COMMAND
și nu întreaga buclă.
Cum aș realiza ceva similar, dar pe care îl pot opri fără a fi nevoie să închid terminalul?
Comentarii
- Dacă ‘ m în bash folosesc doar Ctrl-Z pentru a opri jobul și apoi ” ucide% 1 ” pentru a-l ucide.
- Așteptați … Linus a fost citat spunând: „Știm cu toții că Linux este minunat … face bucle infinite în 5 secunde. ” – așa că … așteaptă încă câteva secunde, ar trebui să se finalizeze.
- @PaulCager a funcționat și pentru mine! De ce funcționează acolo unde face Ctrl-C nu?
- @cirosantilli ucide lucrarea exterioară (bash ” wrapper „). În unele situații, ‘ nu a ucis imediat ” COMANDA „, de exemplu , dacă îl fundalizați, se poate strecura în trecut, chiar dacă părintele ‘ este mort. Dar bucla este moartă, iar ‘ este partea importantă.
Răspuns
Verificați starea de ieșire a comenzii. Dacă comanda a fost terminată de un semnal, codul de ieșire va fi 128 + numărul semnalului. Din documentația online GNU pentru bash :
În scopul shell-ului, o comandă care iese cu un statut de ieșire zero a reușit. O stare de ieșire diferită de zero indică eșec. Această schemă aparent contra-intuitivă este utilizată, astfel încât există un mod bine definit de a indica succesul și o varietate de moduri de a indica diferite moduri de eșec. Când o comandă se termină pe un semnal fatal al cărui număr este N, Bash folosește valoarea 128 + N ca stare de ieșire.
POSIX specifică, de asemenea, că valoarea unei comenzi care a fost terminată de un semnal este mai mare de 128, dar nu pare să precizeze valoarea exactă a acestuia, așa cum face GNU:
Starea de ieșire a unei comenzi care a încetat deoarece a primit un semnal va fi raportată ca fiind mai mare de 128.
De exemplu, dacă întrerupeți o comandă cu control-C, codul de ieșire va fi 130, deoarece SIGINT este semnalul 2 pe sistemele Unix. Deci:
while [ 1 ]; do COMMAND; test $? -gt 128 && break; done
Comentarii
- De menționat că acest lucru nu este garantat, de fapt, multe aplicații nu vor face acest lucru.
- @Kyle Jones: puteți face legătura cu documentele POSIX / GNU care menționează acest lucru?
- @cirosantilli Gata.
- @ KyleJones mulțumesc! Încă în practică nu funcționează pentru COMMAND =
paplay alert.ogg
, poate pentru căpaplay
gestionează semnalul? - @cirosantilli Da, acesta este ‘ motivul. Dacă un proces gestionează semnalul și renunță, ‘ este diferit de procesul care este încheiat de un semnal neprelucrat.
Răspuns
Puteți opri și plasa lucrarea în fundal în timp ce rulează folosind ctrl + z . îți poate ucide jobul cu:
$ kill %1
Unde [1] este numărul jobului tău.
Comentarii
- Consultați și acest răspuns pentru explicații și multe altele.
- Acest răspuns relativ recent funcționează pur și simplu. Trebuie să fie votat în sus. +1
- M-ați ajutat foarte mult. Acesta este ceea ce am căutat în această întrebare 🙂
Răspuns
Aș spune că ar putea fi cel mai bine să vă puneți bucla infinită într-un script și să gestionați semnalele acolo. Aici este „punctul de plecare de bază . Sunt sigur că veți dori să îl modificați pentru a se potrivi. Scriptul folosește trap
pentru a prinde ctrl – c (sau SIGTERM
), elimină comanda (am „folosit sleep
aici ca test) și iese.
cleanup () { kill -s SIGTERM $! exit 0 } trap cleanup SIGINT SIGTERM while [ 1 ] do sleep 60 & wait $! done
Comentarii
- Drăguț. Iată ‘ cum am folosit acest sfat pentru a crea un împachetare netcat de pornire automată:
trap "exit 0" SIGINT SIGTERM; while true; do netcat -l -p 3000; done
- dacă adăugați această abordare
trap
la același script (bash) cu bucla infinită de ucis, utilizați$$
în loc de$!
(vezi aici )
Răspuns
În general, țin apăsat Ctrl-C . Mai devreme sau mai târziu se va înregistra între COMMAND
” s și astfel încheiați bucla while
. Poate că există o modalitate mai bună.
Comentarii
- Nu știu sigur de ce, dar eșuează pentru anumite COMENZI precum
paplay
pe un fișier 1s . - A funcționat pentru mine
- Aceasta este ‘ forța brută a tuturor soluțiilor de aici. : /
Răspuns
Dacă rulați bash cu -e
va ieși în orice condiții de eroare:
#!/bin/bash -e false # returns 1 echo This won"t be printed
Comentarii
- Prima linie aici este de departe cea mai simplă soluție pentru un script banal pe care nu ‘ nu doriți să petreceți prea mult timp!
Răspundeți
De ce nu,
while [ 1 ]; do COMMAND || break; done;
Sau când este utilizat într-un script,
#!/bin/bash while [ 1 ]; do # ctrl+c terminates COMMAND and exits the while loop # (assuming COMMAND responds to ctrl+c) COMMAND || break done;
Comentarii
- Soluție foarte elegantă. Dar ‘ nu ar funcționa decât dacă COMMAND returnează întotdeauna o stare de ieșire de succes?
- Da @howardh, că ‘ este corect.
Răspuns
- Puteți oricând oricând un proces folosind PID-ul său, acolo ” Nu este nevoie să vă închideți terminalul
- Dacă doriți să rulați ceva într-o buclă infinită ca un daemon, atunci cel mai bine îl veți pune în fundal
-
while :
va crea o buclă infinită și vă salvează scriind[ 1 ]
while :; do COMMAND; done &
Aceasta va imprima PID. Dacă părăsiți solicitarea utilizând ctrl+d
, atunci lucrarea de fundal nu va fi renunțată și puteți ulterior să o eliminați de oriunde utilizând kill PID
Dacă pierdeți urma PID-ului, puteți utiliza pstree -pa $USER
sau pgrep -fl ".*PROCESS.*"
pentru a vă ajuta să îl găsiți
Răspuns
Prefer o altă soluție:
touch .runcmd; while [ -f ".runcmd" ]; do COMMAND; sleep 1; done
În ordine pentru a ucide bucla, faceți doar:
rm .runcmd && kill `pidof COMMAND`
Răspundeți
Ce funcționează rezonabil bine pentru mine este:
while sleep 1; do COMMAND; done
Acest lucru funcționează deoarece somnul 1 rămâne în jur pentru un în timp ce și dacă primește ctrl + c se întoarce cu non zero și bucla se va termina.
Comentarii
- +1, timpul de repaus poate fi, de asemenea, redus la
0.5
sau0.1
:while sleep 0.1; do COMMAND; done
Răspuns
Use trap
–
exit_() { exit } while true do echo "running.." trap exit_ int done