Как остановить бесконечный цикл в bash-скрипт корректно?
Мне нужно запускать приложение каждые X секунд, поэтому, поскольку cron не работает с секундами таким образом, я написал сценарий bash с бесконечным циклом, в котором X секунд спит.
когда мне нужно остановить запущенный скрипт вручную, я хотел бы сделать это правильно - пусть приложение завершит работу и просто не войдет в цикл в следующий раз.
У вас есть идеи, как этого можно добиться? Я подумал о том, чтобы поспорить, но не смог. найдите, как передать аргумент в running script.
4 ответов
вы можете поймать сигнал, сказать SIGUSR1:
echo "My pid is: $$"
finish=0
trap 'finish=1' SIGUSR1
while (( finish != 1 ))
do
stuff
sleep 42
done
затем, когда вы хотите выйти из цикла на следующей итерации:
kill -SIGUSR1 pid
здесь pid
- идентификатор процесса скрипта. Если сигнал поднимается во время сна, он проснется (сон спит, пока не появится какой-либо сигнал).
вы можете передать некоторые аргументы файлом. На каждой итерации вы можете прочитать этот файл и посмотреть, изменились ли ваши запущенные условия.
следующая структура может быть подходящей, если вам все равно нужно выполнить некоторую очистку. Используйте kill, как показано в ответе cdarke.
#===============================================================
# FUNCTION DEFINITIONS
#===============================================================
# . . .
#=== FUNCTION ================================================
# NAME: cleanup
# DESCRIPTION:
#===============================================================
cleanup ()
{
# wait for active children, remove empty logfile, ..., exit
exit 0
} # ---------- end of function cleanup ----------
#===============================================================
# TRAPS
#===============================================================
trap cleanup SIGUSR1
#===============================================================
# MAIN SCRIPT
#===============================================================
echo -e "Script '' / PID ${$}"
while : ; do # infinite loop
# . . .
sleep 10
done
# . . .
#===============================================================
# STATISTICS / CLEANUP
#===============================================================
cleanup
решение trap, опубликованное ранее, хорошо для больших циклов, но громоздко для общего случая, когда вы просто зацикливаетесь на одной или нескольких командах. В этом случае я рекомендую следующее решение:
while whatever; do
command || break
done
это выйдет из цикла, если команда имеет ненулевой код выхода, что произойдет, если он будет прерван. Так что, если command
ручки SIGINT
, нажатие ctrl-C остановит текущую команду и выйдет из цикла.
Edit: после прочтения вашего вопроса более внимательно я вижу, что вы хотите, чтобы текущая команда продолжала выполняться. В этом случае данное решение не применяется.