Ik heb een commando dat ik elke keer dat het eindigt automatisch opnieuw wil laten uitvoeren, dus ik heb zoiets als dit uitgevoerd:
while [ 1 ]; do COMMAND; done;
maar als ik de lus niet kan “stoppen met Ctrl-c , want dat doodt gewoon COMMAND
en niet de hele lus.
Hoe zou ik iets soortgelijks bereiken, maar dat kan ik stoppen zonder de terminal te hoeven sluiten?
Reacties
- Als ik ‘ m in bash gebruik, gebruik ik Ctrl-Z om de taak te stoppen en ” kill% 1 ” om het te doden.
- Wacht maar … Linus werd als volgt geciteerd: “We weten allemaal dat Linux geweldig is … het doet oneindige loops in 5 seconden. ” – dus echt … wacht nog een paar seconden, het zou moeten zijn voltooid.
- @PaulCager werkte ook voor mij! Waarom werkt het waar Ctrl-C doet niet?
- @cirosantilli het doodt de buitenste baan (de bash ” wrapper “). In sommige situaties wint het ‘ om bijvoorbeeld de ” COMMAND ” onmiddellijk te doden , als je het op de achtergrond doet, kan het levend voorbij sluipen, zelfs als de ouder van ‘ dood is. Maar de lus is dood, en dat ‘ is het belangrijkste deel.
Antwoord
Controleer de exit-status van de opdracht. Als de opdracht werd beëindigd door een signaal, is de exitcode 128 + het signaalnummer. Van de GNU online documentatie voor bash :
Voor de doeleinden van de shell, een commando die afsluit met een nul-exitstatus is geslaagd. Een exitstatus anders dan nul duidt op een storing. Dit schijnbaar contra-intuïtieve schema wordt gebruikt, dus er is één goed gedefinieerde manier om succes aan te geven en een verscheidenheid aan manieren om verschillende faalwijzen aan te geven. Wanneer een commando eindigt op een fataal signaal waarvan het nummer N is, gebruikt Bash de waarde 128 + N als de exitstatus.
POSIX specificeert ook dat de waarde van een commando dat wordt beëindigd door een signaal groter is dan 128, maar lijkt niet de exacte waarde te specificeren zoals GNU doet:
De exitstatus van een commando dat is beëindigd omdat het een signaal heeft ontvangen, wordt gerapporteerd als groter dan 128.
Als u bijvoorbeeld een commando onderbreekt met control-C, wordt de exitcode 130, omdat SIGINT signaal 2 is op Unix-systemen. Dus:
while [ 1 ]; do COMMAND; test $? -gt 128 && break; done
Reacties
- Er moet worden vermeld dat dit in feite niet gegarandeerd is veel applicaties zullen dit niet doen.
- @Kyle Jones: kun je linken naar de POSIX / GNU-documenten die dat vermelden?
- @cirosantilli Klaar.
- @ KyleJones bedankt! Werkt het in de praktijk nog steeds niet voor COMMAND =
paplay alert.ogg
, misschien omdatpaplay
het signaal afhandelt? - @cirosantilli Ja, dat ‘ is de reden. Als een proces het signaal afhandelt en stopt, is dat ‘ anders dan het proces dat wordt beëindigd door een onverwerkt signaal.
Antwoord
U kunt stoppen en uw taak op de achtergrond plaatsen terwijl deze wordt uitgevoerd met ctrl + z . kan uw baan doden met:
$ kill %1
Waar [1] uw baannummer is.
Opmerkingen
- Zie ook dit antwoord voor uitleg en meer.
- Dit relatief recente antwoord werkt gewoon. Moet worden upvoted. +1
- Je hebt me veel geholpen. Dit is waar ik naar heb gezocht in deze vraag 🙂
Antwoord
Ik zou zeggen dat het misschien het beste is om je oneindige lus in een script te plaatsen en daar signalen af te handelen. Hier “een basisuitgangspunt . Ik weet zeker dat je het naar wens wilt aanpassen. Het script gebruikt trap
om ctrl – c (of SIGTERM
) te vangen, doodt het commando (ik “ve gebruikt sleep
hier als een test) en sluit af.
cleanup () { kill -s SIGTERM $! exit 0 } trap cleanup SIGINT SIGTERM while [ 1 ] do sleep 60 & wait $! done
Reacties
- Leuk. Hier ‘ zie je hoe ik deze tip heb gebruikt om een automatisch herstartende netcat-wrapper te maken:
trap "exit 0" SIGINT SIGTERM; while true; do netcat -l -p 3000; done
- als je deze
trap
benadering toevoegt aan hetzelfde (bash) script met de oneindige lus om te stoppen, gebruik dan$$
in plaats van$!
(bekijk hier )
Answer
Over het algemeen houd ik Ctrl-C ingedrukt. Vroeg of laat zal het “registreren tussen COMMAND
” s en beëindig daarmee de while
lus. Misschien is er een betere manier.
Reacties
- Weet niet waarom, maar het mislukt voor bepaalde COMMANDs zoals
paplay
op een 1s-bestand . - Het werkte voor mij
- Dat ‘ de brute kracht is van alle oplossingen hier. : /
Answer
Als je bash uitvoert met -e
het wordt afgesloten bij elke foutconditie:
#!/bin/bash -e false # returns 1 echo This won"t be printed
Reacties
- De eerste regel hier is verreweg de eenvoudigste oplossing voor een triviaal script waar je niet ‘ niet te veel tijd aan wilt besteden!
Antwoord
Waarom niet gewoon,
while [ 1 ]; do COMMAND || break; done;
Of wanneer gebruikt in een script,
#!/bin/bash while [ 1 ]; do # ctrl+c terminates COMMAND and exits the while loop # (assuming COMMAND responds to ctrl+c) COMMAND || break done;
Reacties
- Zeer elegante oplossing. Maar zou dit niet ‘ werken als COMMAND altijd een exit-status voor succes retourneert?
- Ja @howardh, dat ‘ is correct.
Antwoord
- Je kunt een proces altijd afbreken met zijn PID, daar ” Het is niet nodig om je terminal te sluiten.
- Als je iets in een oneindige lus wilt draaien zoals een daemon, dan kun je het het beste op de achtergrond plaatsen
-
while :
zal een oneindige lus creëren en bespaart u het schrijven van de[ 1 ]
while :; do COMMAND; done &
Hiermee wordt de PID afgedrukt. Als u de prompt verlaat met ctrl+d
, wordt de taak op de achtergrond “niet gestopt en kunt u de taak later overal beëindigen met kill PID
Als u uw PID uit het oog verliest, kunt u pstree -pa $USER
of pgrep -fl ".*PROCESS.*"
gebruiken om u te helpen deze te vinden
Antwoord
Ik geef de voorkeur aan een andere oplossing:
touch .runcmd; while [ -f ".runcmd" ]; do COMMAND; sleep 1; done
Om om de lus te stoppen, doe je gewoon:
rm .runcmd && kill `pidof COMMAND`
Antwoord
Wat werkt redelijk goed voor mij is:
while sleep 1; do COMMAND; done
Dit werkt omdat slaap 1 lang blijft hangen while en als het ctrl + c krijgt, wordt het teruggegeven met een andere waarde dan nul en zal de lus eindigen.
Comments
- +1, slaaptijd kan ook zijn gereduceerd tot
0.5
of0.1
:while sleep 0.1; do COMMAND; done
Antwoord
Gebruik trap
–
exit_() { exit } while true do echo "running.." trap exit_ int done