Mám příkaz, který chci znovu automaticky spustit pokaždé, když skončí, takže jsem spustil něco podobného:
while [ 1 ]; do COMMAND; done;
ale pokud nedokážu zastavit smyčku Ctrl-c protože to zabíjí COMMAND
a ne celou smyčku.
Jak bych dosáhl něčeho podobného, ale co mohu zastavit, aniž bych musel terminál uzavřít?
Zkontrolujte stav ukončení příkazu. Pokud byl příkaz ukončen signálem, bude výstupní kód 128 + číslo signálu. Z GNU online dokumentace pro bash :
Pro účely prostředí Shell byl úspěšný příkaz, který opouští stav nulového ukončení. Nenulový stav ukončení označuje selhání. Toto zdánlivě kontraintuitivní schéma se používá, takže existuje jeden dobře definovaný způsob, jak označit úspěch, a různé způsoby, jak označit různé režimy selhání. Když příkaz skončí na fatálním signálu, jehož číslo je N, použije Bash jako stav ukončení hodnotu 128 + N.
POSIX také specifikuje , že hodnota příkazu ukončeného signálem je větší než 128, ale nezdá se, že by specifikovala jeho přesnou hodnotu jako GNU dělá:
Stav výstupu 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 s control-C, bude výstupní kód 130, protože SIGINT je signálem 2 v unixových systémech. Tak:
while [ 1 ]; do COMMAND; test $? -gt 128 && break; done
Během práce můžete práci zastavit a umístit ji na pozadí ctrl+z. Pak můžete svou práci zabít:
$ kill %1
Kde [1] je vaše pracovní číslo.
Řekl bych, že by bylo nejlepší vložit nekonečnou smyčku do skriptu a zpracovat tam signály. Zde je základní výchozí bod. Určitě budete chtít upravit tak, aby vyhovovaly. Skript používá k zachycení trap
ctrl-c (nebo SIGTERM
), zabije příkaz (zde jsem použil sleep
jako test) a skončí.
cleanup ()
{
kill -s SIGTERM $!
exit 0
}
trap cleanup SIGINT SIGTERM
while [ 1 ]
do
sleep 60 &
wait $!
done
Obecně jen podržím Ctrl-C. Dříve nebo později se zaregistruje mezi COMMAND
a tím ukončí smyčku while
. Možná existuje lepší způsob.
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;
Pokud spustíte bash s -e
ukončí se za všech chybových podmínek:
#!/bin/bash -e
false # returns 1
echo This won't be printed
Dávám přednost jinému řešení:
touch .runcmd; while [ -f ".runcmd" ]; do COMMAND; sleep 1; done
Chcete-li zabít smyčku, stačí:
rm .runcmd && kill `pidof COMMAND`
while :
vytvoří nekonečnou smyčku a ušetří vám psaní [ 1 ]
while :; do COMMAND; done &
Tím se vytiskne PID. Pokud ukončíte výzvu pomocí ctrl+d
pak se úloha na pozadí neukončí a později ji můžete zabít odkudkoli pomocí kill PID
Pokud ztratíte přehled o svém PID, můžete použít pstree -pa $USER
nebo pgrep -fl '.*PROCESS.*'
, které vám pomohou najít
Co pro mě funguje docela dobře, je:
while sleep 1; do COMMAND; done
Funguje to proto, že spánek 1 se chvíli drží a pokud se dostane ctrl + c, vrátí se s nulu a smyčka se ukončí.
Použijte trap
-
exit_()
{
exit
}
while true
do
echo 'running..'
trap exit_ int
done