Это может показаться тривиальным, но я уверен, что этот вопрос еще не задавался, или, по крайней мере, я не могу его найти.
Я ищу способ построить бесконечное ожидание (не обязательно цикл) с помощью сценариев shell так, чтобы оно ждало вечно и могло быть убито (или, технически, получить SIGTERM
). Ниже приведены известные возможные конструкции и аргументы против них:
while true; do sleep 1; done
Это почти получается, но поскольку sleep
является внешней командой, когда я посылаю SIGTERM
запущенному скрипту, он должен сначала дождаться завершения sleep
, а затем обработать сигнал. Измените sleep 1
на что-то вроде sleep 10
и отставание станет очевидным. Также это решение будит процессор каждые 1 секунду, что не идеально. while true; do read; done
Это идеально, когда stdin
является tty. read
является встроенной функцией оболочки и SIGTERM
поступает в скрипт мгновенно. Но когда stdin
- это /dev/null
, сценарий съедает весь процессор, беспомощно выполняя read
вечно на /dev/null
. Таким образом, требуется встроенная конструкция оболочки, которая ждет вечно. Пролистав man dash
, я не нашел такой конструкции - единственные блокирующие встроенные модули это read
и wait
, и я не представляю, как я могу построить идеальный вариант, используя wait
.
Ответ должен быть применим к POSIX shell (эффективно dash
), или, что менее предпочтительно, к Bash.
Дополнительные замечания.
Ситуация, когда первый пример не работает идеально, сложнее, чем я думал. Со следующим shell-скриптом:
#!/bin/sh
echo $$
while true; do
sleep 100
done
если убить его на другом tty, он немедленно завершается. Самое интересное начинается, когда вы пытаетесь сделать треппинг. С этим скриптом:
#!/bin/sh
at_term() {
echo 'Terminated.'
exit 0
}
trap at_term TERM
echo $$
while true; do
sleep 20
done
Происходит то, что описано в примере 1. Это происходит с bash, dash и zsh. И именно при этом условии я ищу "идеальную" конструкцию бесконечного вида.