Mám příkaz, který chci nechat znovu spustit automaticky při každém ukončení, takže jsem spustil něco takového:
while [ 1 ]; do COMMAND; done;
ale pokud nemůžu zastavit smyčku pomocí Ctrl-c , protože to jen zabije COMMAND
a ne celá smyčka.
Jak bych dosáhl něčeho podobného, ale čeho mohu zastavit, aniž bych musel zavírat terminál?
Komentáře
- Pokud jsem ‚ m v bash, stačí použít Ctrl-Z k zastavení úlohy a poté “ zabít% 1 “ zabít to.
- Jen počkejte … Linus byl citován slovy: „Všichni víme, že Linux je skvělý … dělá nekonečné smyčky za 5 sekund. “ – takže opravdu … počkejte ještě několik sekund, mělo by to být hotové.
- @PaulCager pracoval také pro mě! Proč to funguje tam, kde Ctrl-C ne?
- @cirosantilli zabije vnější úlohu (bash “ wrapper „). V některých situacích například nebude ‚ okamžitě zabít “ COMMAND “ , pokud jej na pozadí, může se proklouznout kolem živého, i když je ‚ rodič mrtvý. Ale smyčka je mrtvá a to je ‚ důležitou součástí.
Odpověď
Zkontrolujte stav ukončení příkazu. Pokud byl příkaz ukončen signálem, výstupní kód bude 128 + číslo signálu. Z online dokumentace GNU pro bash :
Pro účely shellu příkaz který ukončí stav nulového ukončení, byl úspěšný. Nenulový stav ukončení indikuje selhání. Toto zdánlivě protiintuitivní schéma se používá, takže existuje jeden dobře definovaný způsob, jak označit úspěch, a řada způsobů, jak označit různé režimy selhání. Když příkaz končí fatálním signálem, jehož číslo je N, použije Bash jako stav ukončení hodnotu 128 + N.
POSIX také určuje , že hodnota příkazu ukončeného signálem je větší než 128, ale nezdá se, že by specifikoval jeho přesnou hodnotu jako GNU:
Stav ukončení příkazu, který byl ukončen, protože přijal signál, musí být hlášen jako větší než 128.
Například pokud přerušíte příkaz pomocí control-C, výstupní kód bude 130, protože SIGINT je signál 2 v systémech Unix. Takže:
while [ 1 ]; do COMMAND; test $? -gt 128 && break; done
Komentáře
Odpověď
Svou úlohu můžete zastavit a dát ji na pozadí, když běží, pomocí ctrl + z . Poté může vaši práci zabít pomocí:
$ kill %1
Kde [1] je číslo vaší úlohy.
Komentáře
- Viz také tuto odpověď , kde najdete vysvětlení a další.
- Tato relativně nedávná odpověď jednoduše funguje. upvoted. +1
- Hodně jste mi pomohli. To je to, co jsem hledal v této otázce 🙂
Odpovědět
Řekl bych, že by mohlo být nejlepší vložit nekonečnou smyčku do skriptu a zpracovávat tam signály. Zde je základní výchozí bod . Jsem si jistý, že to budete chtít upravit tak, aby vyhovovalo. Skript používá trap
k zachycení ctrl – c (nebo SIGTERM
), zruší příkaz (zde jsem použil sleep
jako test) a ukončí se.
cleanup () { kill -s SIGTERM $! exit 0 } trap cleanup SIGINT SIGTERM while [ 1 ] do sleep 60 & wait $! done
Komentáře
- Pěkné. Zde ‚ jsem použil tento tip k vytvoření obálky automatického spuštění netcat:
trap "exit 0" SIGINT SIGTERM; while true; do netcat -l -p 3000; done
- pokud přidáte tento
trap
přístup ke stejnému (bash) skriptu s nekonečnou smyčkou, která má být zabita, použijte$$
místo$!
(viz zde )
Odpověď
Obvykle podržím Ctrl-C . Dříve nebo později se „zaregistruji mezi COMMAND
“ s a tím ukončit smyčku while
. Možná existuje lepší způsob.
Komentáře
- Nevím proč, ale u některých PŘÍKAZŮ jako
paplay
u souboru 1 s selže . - Fungovalo to na mě
- to je ‚ hrubá síla všech řešení zde. : /
Odpověď
Pokud spustíte bash s -e
ukončí se za jakýchkoli chybových podmínek:
#!/bin/bash -e false # returns 1 echo This won"t be printed
Komentáře
- První řádek je zdaleka nejjednodušší řešení pro triviální skript, kterému ‚ nechcete věnovat příliš mnoho času!
Odpovědět
Proč ne jednoduše,
while [ 1 ]; do COMMAND || break; done;
Nebo při použití ve skriptu,
#!/bin/bash while [ 1 ]; do # ctrl+c terminates COMMAND and exits the while loop # (assuming COMMAND responds to ctrl+c) COMMAND || break done;
Komentáře
- Velmi elegantní řešení. Ale ‚ to nebude fungovat, pouze pokud příkaz COMMAND vždy vrátí stav úspěšného ukončení?
- Ano @howardh, že ‚ s správné.
Odpověď
- Proces můžete vždy zabít pomocí jeho PID, tam “ není třeba zavírat terminál
- Pokud chcete spustit něco v nekonečné smyčce jako démon, měli byste to dát na pozadí
-
while :
vytvoří nekonečnou smyčku a ušetří vám psaní[ 1 ]
while :; do COMMAND; done &
Tím se vytiskne PID. Pokud výzvu opustíte pomocí ctrl+d
, úloha na pozadí nebude ukončena a můžete ji kdykoli zabít odkudkoli pomocí kill PID
Pokud ztratíte přehled o svém PID, můžete jej najít pomocí pstree -pa $USER
nebo pgrep -fl ".*PROCESS.*"
Odpověď
Dávám přednost jinému řešení:
touch .runcmd; while [ -f ".runcmd" ]; do COMMAND; sleep 1; done
V pořadí k zabíjení smyčky stačí:
rm .runcmd && kill `pidof COMMAND`
Odpovědět
Co funguje rozumně pro mě je:
while sleep 1; do COMMAND; done
Funguje to, protože spánek 1 se drží za while a if it gets ctrl + c it return with non zero and the loop will terminate.
Komentáře
- +1, doba spánku může být také sníženo na
0.5
nebo0.1
:while sleep 0.1; do COMMAND; done
Odpověď
Použijte trap
–
exit_() { exit } while true do echo "running.." trap exit_ int done
paplay alert.ogg
, možná proto, žepaplay
zpracovává signál?