Jeg har en kommando som jeg vil ha kjørt igjen automatisk hver gang den avsluttes, så jeg kjørte noe sånt:
while [ 1 ]; do COMMAND; done;
men hvis jeg ikke kan stoppe sløyfen med Ctrl-c da det bare dreper COMMAND
og ikke hele sløyfen.
Hvordan ville jeg oppnå noe lignende, men som jeg kan stoppe uten å måtte stenge terminalen?
Kommentarer
- Hvis jeg ‘ m i bash bruker jeg bare Ctrl-Z for å stoppe jobben og deretter » dreper% 1 » for å drepe det.
- Bare vent … Linus ble sitert: “Vi vet alle at Linux er flott … det gjør uendelige løkker på 5 sekunder. ” – så egentlig … bare vent noen sekunder til, det skal fullføres.
- @PaulCager jobbet også for meg! Hvorfor fungerer det der Ctrl-C gjør ikke?
- @cirosantilli det dreper den ytre jobben (bash » wrapper «). I noen situasjoner vil den ikke ‘ t umiddelbart drepe » KOMMANDO » , hvis du bakgrunner den, kan den snike seg levende selv om den ‘ sin forelder er død. Men sløyfen er død, og at ‘ er den viktigste delen.
Svar
Kontroller avslutningsstatus for kommandoen. Hvis kommandoen ble avsluttet med et signal, vil utgangskoden være 128 + signalnummeret. Fra GNU online dokumentasjon for bash :
For skallets formål, en kommando som går ut med null utgangsstatus har lyktes. En utgangsstatus som ikke er null indikerer feil. Denne tilsynelatende kontraintuitive ordningen brukes, så det er en veldefinert måte å indikere suksess på og en rekke måter å indikere forskjellige feilmodus på. Når en kommando avsluttes på et dødelig signal med tallet N, bruker Bash verdien 128 + N som utgangsstatus.
POSIX spesifiserer også at verdien av en kommando som avsluttes av et signal er større enn 128, men ikke ser ut til å spesifisere den eksakte verdien som GNU gjør:
Utgangsstatus for en kommando som ble avsluttet fordi den mottok et signal, skal rapporteres som større enn 128.
Hvis du for eksempel avbryter en kommando med kontroll-C, vil utgangskoden være 130, fordi SIGINT er signal 2 på Unix-systemer. Så:
while [ 1 ]; do COMMAND; test $? -gt 128 && break; done
Kommentarer
- Det skal nevnes at dette ikke er garantert, faktisk mange applikasjoner vil ikke gjøre dette.
- @Kyle Jones: kan du lenke til POSIX / GNU-dokumentene som nevner det?
- @cirosantilli Ferdig.
- @ Takk, KyleJones! Jobber du fremdeles ikke for COMMAND =
paplay alert.ogg
, kanskje fordipaplay
håndterer signalet? - @cirosantilli Ja, at ‘ er årsaken. Hvis en prosess håndterer signalet og avsluttes, er ‘ annerledes enn prosessen som avsluttes med et uhåndtert signal.
Svar
Du kan stoppe og sette jobben din i bakgrunnen mens den kjører med ctrl + z . Så du kan drepe jobben din med:
$ kill %1
Hvor [1] er jobbnummeret ditt.
Kommentarer
- Se også dette svaret for forklaringer og mer.
- Dette relativt nylige svaret virker ganske enkelt. Må være oppstemt. +1
- Du hjalp meg mye. Dette har jeg søkt etter i dette spørsmålet 🙂
Svar
Jeg vil si at det kan være best å sette den uendelige sløyfen din i et skript og håndtere signaler der. Her «er grunnleggende utgangspunkt . Jeg er sikker på at du vil endre den slik at den passer. Skriptet bruker trap
for å fange ctrl – c (eller SIGTERM
), dreper kommandoen (jeg har brukt sleep
her som en test) og avslutter.
cleanup () { kill -s SIGTERM $! exit 0 } trap cleanup SIGINT SIGTERM while [ 1 ] do sleep 60 & wait $! done
Kommentarer
- Hyggelig. Her ‘ hvordan jeg brukte dette tipset til å lage en autorestarting netcat wrapper:
trap "exit 0" SIGINT SIGTERM; while true; do netcat -l -p 3000; done
- hvis du legger til denne
trap
tilnærmingen til det samme (bash) skriptet med den uendelige sløyfen som skal drepes, bruk$$
i stedet for$!
(se her )
Svar
Jeg holder vanligvis bare nede Ctrl-C . Før eller senere registreres det mellom COMMAND
» s og dermed avslutte while
sløyfen. Kanskje det er en bedre måte.
Kommentarer
- Ikke sikker på hvorfor, men det mislykkes for visse KOMMANDOER som
paplay
på en 1s-fil . - Det fungerte for meg
- At ‘ er den brute kraften til alle løsningene her. : /
Svar
Hvis du kjører bash med -e
den vil gå ut under eventuelle feilforhold:
#!/bin/bash -e false # returns 1 echo This won"t be printed
Kommentarer
- Den første linjen her er langt den enkleste løsningen for et trivielt skript som du ikke ‘ ikke vil bruke for mye tid på!
Svar
Hvorfor ikke bare,
while [ 1 ]; do COMMAND || break; done;
Eller når det brukes i et skript,
#!/bin/bash while [ 1 ]; do # ctrl+c terminates COMMAND and exits the while loop # (assuming COMMAND responds to ctrl+c) COMMAND || break done;
Kommentarer
- Veldig elegant løsning. Men ville ikke ‘ ikke dette bare fungere hvis COMMAND alltid returnerer en vellykket exit-status?
- Ja @howardh, at ‘ er riktig.
Svar
- Du kan alltid drepe en prosess ved hjelp av PID, der » det er ikke nødvendig å lukke terminalen din
- Hvis du vil kjøre noe i en uendelig løkke som en demon, bør du sette den i bakgrunnen
-
while :
oppretter en uendelig løkke og sparer deg når du skriver[ 1 ]
while :; do COMMAND; done &
Dette vil skrive ut PID. Hvis du avslutter meldingen din ved å bruke ctrl+d
, vil ikke bakgrunnsjobben slutte, og du kan senere drepe jobben hvor som helst ved hjelp av kill PID
Hvis du mister oversikten over PID-en din, kan du bruke pstree -pa $USER
eller pgrep -fl ".*PROCESS.*"
for å hjelpe deg med å finne den
Svar
Jeg foretrekker en annen løsning:
touch .runcmd; while [ -f ".runcmd" ]; do COMMAND; sleep 1; done
I rekkefølge for å drepe løkken, gjør bare:
rm .runcmd && kill `pidof COMMAND`
Svar
Hva fungerer rimelig vel for meg er:
while sleep 1; do COMMAND; done
Dette fungerer fordi søvn 1 holder seg i en mens og hvis det blir ctrl + c, returnerer det uten null og sløyfen avsluttes.
Kommentarer
- +1, kan også søvntiden være redusert til
0.5
eller0.1
:while sleep 0.1; do COMMAND; done
Svar
Bruk trap
–
exit_() { exit } while true do echo "running.." trap exit_ int done