Bash: бесконечный сон (бесконечная блокировка)
Я использую startx
запуск X, который будет оценивать мой .xinitrc
. В моем .xinitrc
Я запускаю свой оконный менеджер с помощью /usr/bin/mywm
. Теперь, если я убью свой WM (для того, чтобы f.e. проверить некоторые другие WM), X тоже завершится, потому что .xinitrc
сценарий будет достигнут конец файла.
Поэтому я добавил Это в конце моего .xinitrc
:
while true; do sleep 10000; done
таким образом, X не завершится, если я убью своего WM. Теперь мой вопрос: как я могу сделать бесконечного сна вместо циклического сна? Есть ли команда, которая будет нравится заморозить сценарий?
С наилучшими пожеланиями
9 ответов:
может быть, это кажется уродливым, но почему бы просто не запустить
cat
и пусть он ждет ввода навсегда?
tail
не блоккак всегда: на все есть ответ, который является коротким, легко понять, легко следовать, и совершенно неправильно. Здесь
tail -f /dev/null
попадает в эту категорию ;)если вы посмотрите на это с
strace tail -f /dev/null
вы заметите, что это решение далеко не блокирует! Это, наверное, даже хуже, чемsleep
решение в вопросе, так как он использует (под Linux) драгоценные ресурсы, такие как ), мы сделали. К сожалению, это должно держать открытыми два PIDs иfifo
.вариант с именем
fifo
если вы не утруждаете себя использованием имени
fifo
, вы можете сделать это следующим образом:mkfifo "$HOME/.pause.fifo" 2>/dev/null; read <"$HOME/.pause.fifo"
не используя цикл на чтение немного небрежно, но вы можете использовать это
fifo
так часто, как вам нравится, и сделатьread
s terminat с помощьюtouch "$HOME/.pause.fifo"
(если есть более одного ожидания чтения, все они завершаются сразу).или использовать Linux
pause()
syscallдля бесконечной блокировки есть вызов ядра Linux, называемый
pause()
, который делает то, что мы хотим: ждать вечно (пока не приходит сигнал). Однако для этого нет программы userspace (пока).C
создать такую программу легко. Вот фрагмент для создания очень маленькой программы Linux под названием
pause
который останавливается на неопределенный срок (нуждаетсяdiet
,gcc
etc.):printf '#include <unistd.h>\nint main(){for(;;)pause();}' > pause.c; diet -Os cc pause.c -o pause; strip -s pause; ls -al pause
python
если вы не хотите, чтобы скомпилировать что-то самостоятельно, но у вас есть
python
установлен, вы можете использовать это под Linux:python -c 'while 1: import ctypes; ctypes.CDLL(None).pause()'
(Примечание: Используйте
exec python -c ...
чтобы заменить текущую оболочку, это освобождает один PID. Решение может быть улучшено с некоторым перенаправлением ввода-вывода, а также, освобождая неиспользуемые FDs. Это зависит от вас.)как это работает (я думаю):
ctypes.CDLL(None)
загружает стандартную библиотеку C ++ и работаетpause()
функция в нем в пределах некоторого дополнительного цикла. Менее эффективен, чем версия C, но работает.моя рекомендация для вас:
пребывания в циклический сон. Это легко понять, очень портативный, и блокирует большую часть времени.
TL; DR:
sleep infinity
фактически спит максимальное допустимое время, которое является конечным.интересно, почему это нигде не задокументировано, я потрудился прочитать источники из GNU coreutils и я обнаружил, что он выполняет примерно следующее:
- используйте strtod из C stdlib в первом аргументе для преобразования "бесконечности" в двойную точность. Итак, предполагая, что IEEE 754 двойная точность 64-бит положительная бесконечность значение хранится в
seconds
переменной.- Invoke
xnanosleep(seconds)
( найдено в gnulib), это в свою очередь вызываетdtotimespec(seconds)
(также в gnulib) для преобразования изdouble
доstruct timespec
.struct timespec
это просто пара целых чисел: целая часть (в секундах) и дробная часть (в наносекундах). Наивно обращая положительная бесконечность to integer приведет к неопределенному поведению (см. §6.3.1.4 из стандарта C), поэтому вместо этого он усекается доTYPE_MAXIMUM (time_t)
.- фактическое значение
TYPE_MAXIMUM (time_t)
не входит в стандарт (дажеsizeof(time_t)
нет); Итак, для примера давайте выберем x86-64 из недавнего ядра linux.это
TIME_T_MAX
в ядре Linux, которое определено (time.h
) как:(time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
отметим, что
time_t
и__kernel_time_t
иtime_t
иlong
; используется модель данных LP64, поэтомуsizeof(long)
8 (64 бита).что дает:
TIME_T_MAX = 9223372036854775807
.это:
sleep infinite
приводит к фактическому времени сна 9223372036854775807 секунд (10^11 лет). И для 32-битных систем linux (sizeof(long)
is 4 (32 бит): 2147483647 секунд (68 лет; см. Также проблему 2038 года).
Edit: видимо
nanoseconds
вызываемая функция не является непосредственно syscall, а зависящей от ОС оболочкой (также определено в gnulib).в результате есть дополнительный шаг: для некоторых систем, где
HAVE_BUG_BIG_NANOSLEEP
иtrue
время сна сокращается до 24 дней, а затем вызывается в цикле. Это касается некоторых (или всех?) Дистрибутивов Linux. Обратите внимание, что эта оболочка может не использоваться, если настроитьтест завершается успешно (источник).в частности, это было бы
24 * 24 * 60 * 60 = 2073600 seconds
(плюс 999999999 наносекунд), но это вызывается в цикле для того, чтобы соблюдать заданное общее время сна. Поэтому предыдущие выводы остаются в силе.
в заключение в результате время сна не бесконечно, но достаточно высоко для всех практических целей, даже если полученный фактический промежуток времени не переносится; это зависит от ОС и архитектуры.
чтобы ответить на исходный вопрос, это, очевидно, достаточно хорошо, но если по какой-то причине (a очень система с ограничением ресурсов) вы действительно хотите избежать бесполезного дополнительного таймера обратного отсчета, я думаю, что наиболее правильной альтернативой является использование
cat
метод, описанный в другой ответ.
sleep infinity
выглядит наиболее элегантно, но иногда это не работает по какой-то причине. В этом случае вы можете попробовать другие команды блокировки, такие какcat
,read
,tail -f /dev/null
,grep a
etc.
Как насчет отправки SIGSTOP для себя?
это должно приостановить процесс до получения SIGCONT. Что в вашем случае: никогда.
kill -STOP "$$"; # grace time for signal delivery sleep 60;
недавно у меня возникла необходимость сделать это. Я придумал следующую функцию, которая позволит Башу спать вечно без вызова какой-либо внешней программы:
snore() { [[ -n "${_snore_fd:-}" ]] || exec {_snore_fd}<> <(:) read ${1:+-t ""} -u $_snore_fd || : }
примечание: Я ранее опубликовал версию этого, которая будет открывать и закрывать файловый дескриптор каждый раз, но я обнаружил, что на некоторых системах, делающих это сотни раз в секунду, в конечном итоге заблокируется. Таким образом, новое решение сохраняет дескриптор файла между вызовами функции. Баш уберет его на выходе в любом случае.
Это можно назвать так же, как /bin/sleep, и он будет спать в течение запрошенного времени. Вызывается без параметров, он будет висеть вечно.
snore 0.1 # sleeps for 0.1 seconds snore 10 # sleeps for 10 seconds snore # sleeps forever