Я использую startx
для запуска X, который будет оценивать мой .xinitrc
. По моему .xinitrc
я запускаю свой оконный менеджер, используя/usr/bin/mywm
. Теперь, если я убью свой WM (чтобы проверить какой-то другой WM), X тоже прекратит работу, потому что .xinitrc
сценарий достиг EOF. Поэтому я добавил это в конце моего .xinitrc
:
while true; do sleep 10000; done
Таким образом, X не завершится, если я убью свой WM. Теперь мой вопрос: как я могу сделать бесконечный сон вместо зацикленного сна? Есть ли команда, которая вроде как заморозит скрипт?
С уважением
sleep infinity
, хотя это было круто для изучения Linux. Тем не менее,while true; do sleep 86400; done
должно быть адекватной заменой.infinity
преобразуется в C из "строки" вdouble
. Затем этоdouble
усекается до максимально допустимых значенийtimespec
, что означает очень большое количество секунд (зависит от архитектуры), но, теоретически, конечно.tail
не блокируетКак всегда: для всего есть ответ, который короток, прост для понимания, легок для понимания и совершенно неверен. Вот
tail -f /dev/null
попадает в эту категорию;)Если вы посмотрите на это вместе,
strace tail -f /dev/null
вы заметите, что это решение далеко не блокирует! Вероятно, это даже хуже, чемsleep
решение в вопросе, поскольку он использует (под Linux) драгоценные ресурсы, такие какinotify
система. Также другие процессы, которые пишут, чтобы/dev/null
сделатьtail
цикл. (На моем Ubuntu64 16.10 это добавляет несколько 10 системных вызовов в секунду в уже загруженной системе.)Вопрос был для команды блокировки
К сожалению, нет такой вещи ..
Читайте: я не знаю, как архивировать это с помощью оболочки напрямую.
Все (даже
sleep infinity
) может быть прервано каким-то сигналом. Поэтому, если вы хотите быть действительно уверенным, что он не исключительно возвращается, он должен работать в цикле, как вы уже сделали для своегоsleep
. Обратите внимание, что (в Linux), по-/bin/sleep
видимому, ограничено 24 днями (посмотритеstrace sleep infinity
), поэтому лучшее, что вы можете сделать, это:(Обратите внимание, что я считаю, что
sleep
циклы внутренне для более высоких значений, чем 24 дня, но это означает: это не блокирование, а очень медленное зацикливание. Так почему бы не переместить этот цикл наружу?).. но вы можете подойти довольно близко с неназванным
fifo
Вы можете создать что-то, что действительно блокирует, пока нет никаких сигналов, посылаемых процессу. Следующее использование
bash 4
, 2 PID и 1fifo
:Вы можете проверить, что это действительно блокирует,
strace
если вам нравится:Как это было построено
read
блокирует, если нет входных данных (см. некоторые другие ответы). Однакоtty
(aka.stdin
) Обычно не является хорошим источником, так как он закрывается, когда пользователь выходит из системы. Также это может украсть некоторый вклад отtty
. Не хорошо.Чтобы сделать
read
блок, нам нужно ждать чего-то вроде a,fifo
которое никогда ничего не вернет. Вbash 4
есть команда , которая может точно предоставить нам такиеfifo
:coproc
. Если мы также ждем блокировкуread
(которая является нашейcoproc
), мы сделали. К сожалению, для этого необходимо оставить открытыми два идентификатора PID и afifo
.Вариант с именем
fifo
Если вы не удосужились использовать именованные
fifo
, вы можете сделать это следующим образом:Не использовать цикл при чтении немного небрежно, но вы можете использовать его
fifo
так часто, как вам нравится, и заставить егоread
завершить с помощьюtouch "$HOME/.pause.fifo"
(если имеется более одного ожидания чтения, все завершаются одновременно).Или используйте
pause()
системный вызов LinuxДля бесконечной блокировки есть вызов ядра Linux, который называется
pause()
, который делает то, что мы хотим: ждать вечно (пока не придет сигнал). Однако для этого пока нет программы для пользователя.С
Создать такую программу легко. Вот фрагмент кода для создания очень маленькой программы для Linux, которая называется на
pause
неопределенный срок (нуждыdiet
иgcc
т. Д.):python
Если вы не хотите что-то компилировать самостоятельно, но уже
python
установили, вы можете использовать это под Linux:(Примечание: использовать
exec python -c ...
для замены текущей оболочки, это освобождает один PID. Решение может быть улучшено также путем некоторого перенаправления ввода-вывода, освобождая неиспользуемые FD. Это ваше дело.)Как это работает (я думаю):
ctypes.CDLL(None)
загружает стандартную библиотеку C и запускает в нейpause()
функцию в каком-то дополнительном цикле. Менее эффективен, чем версия C, но работает.Моя рекомендация для вас:
Оставайтесь в дремлющем сне. Это легко понять, очень переносимо и блокирует большую часть времени.
источник
trap
(который изменяет поведение оболочки для сигналов), ни фон (который позволяет оболочке перехватывать сигналы от терминала, например, Strg + C). Такsleep infinity
что достаточно (ведет себя так, какexec sleep infinity
будто это последнее утверждение. Чтобы увидеть разницу использоватьstrace -ffDI4 bash -c 'YOURCODEHERE'
). Цикл сна лучше, потому чтоsleep
может вернуться при определенных обстоятельствах. Например, вы не хотите, чтобы X11 внезапно закрывался на akillall sleep
, потому что он.xstartup
заканчиваетсяsleep infinity
вместо цикла ожидания.s6-pause
это команда пользователя для запускаpause()
, опционально игнорируя различные сигналы./bin/sleep
не ограничен 24 днями, как вы говорите. Было бы хорошо, если бы вы могли обновить это. В Linux сейчас этот код активен. Он ограничивает отдельныеnanosleep()
системные вызовы до 24 дней, но вызывает их в цикле. Поэтомуsleep infinity
не следует выходить через 24 дня.double
Положительная бесконечность преобразуется кstruct timespec
. Глядяrpl_nanosleep
в GDB,infinity
преобразуется в{ tv_sec = 9223372036854775807, tv_nsec = 999999999 }
Ubuntu 16.04.strace
одиночку я не могу доказать факт, что действительно есть некоторый зацикленный кодsleep
, и я не хочу ждать 24 дня, чтобы проверить это (или декомпилировать/bin/sleep
). Всегда лучше программировать в обороне, если нет серьезных математических доказательств того, что что-то действительно так, как кажется. Также никогда не доверяйте ничему:killall -9 sleep
Может быть, это кажется уродливым, но почему бы просто не запустить
cat
и не дождаться ввода навсегда?источник
cat
это?mkfifo pipe && cat pipe
TL; DR:
sleep infinity
фактически спит максимально допустимое время, которое является конечным.Удивляясь, почему это нигде не задокументировано, я потрудился прочитать исходники из GNU coreutils и обнаружил, что он выполняет примерно следующее:
strtod
из C stdlib первый аргумент, чтобы преобразовать бесконечность в двойную точность. Таким образом, при условии двойной точности IEEE 754 64-разрядное положительное значение бесконечности сохраняется вseconds
переменной.xnanosleep(seconds)
( находится в gnulib ), это, в свою очередь, вызываетdtotimespec(seconds)
( также в gnulib ) для преобразования изdouble
вstruct timespec
.struct timespec
это просто пара чисел: целая часть (в секундах) и дробная часть (в наносекундах). Наивное преобразование положительной бесконечности в целое число приведет к неопределенному поведению (см. §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
есть__kernel_time_t
иtime_t
естьlong
; используется модель данных LP64, а такжеsizeof(long)
8 (64 бита).Какие результаты в:
TIME_T_MAX = 9223372036854775807
.То есть:
sleep infinite
приводит к фактическому времени сна 9223372036854775807 секунд (10 ^ 11 лет). А для 32-разрядных систем Linux (sizeof(long)
4 (32 бита)): 2147483647 секунд (68 лет; см. Также проблему 2038 года ).Редактировать : очевидно, что
nanoseconds
вызываемая функция - это не системный вызов, а зависимая от ОС оболочка (также определенная в gnulib ).Там это дополнительный шаг в результате: для некоторых систем , в которых
HAVE_BUG_BIG_NANOSLEEP
являетсяtrue
сон сокращается до 24 дней , а затем вызывается в цикле. Это касается некоторых (или всех?) Дистрибутивов Linux. Обратите внимание, что эта обертка может не использоваться, если тест настройки времени успешен ( источник ).В частности, это будет
24 * 24 * 60 * 60 = 2073600 seconds
(плюс 999999999 наносекунд); но это вызывается в цикле для соблюдения указанного общего времени ожидания. Поэтому предыдущие выводы остаются в силе.В заключение, результирующее время сна не бесконечно, но достаточно велико для всех практических целей , даже если результирующий фактический промежуток времени не является переносимым; это зависит от ОС и архитектуры.
Чтобы ответить на исходный вопрос, это, очевидно, достаточно хорошо, но если по какой-то причине (система с очень ограниченными ресурсами) вы действительно хотите избежать бесполезного дополнительного таймера обратного отсчета, я думаю, что наиболее правильной альтернативой является использование
cat
метода, описанного в других ответах. ,источник
sleep infinity
теперь будет фактически спать вечно без зацикливания: lists.gnu.org/archive/html/bug-gnulib/2020-02/msg00081.htmlsleep infinity
выглядит наиболее элегантно, но иногда это не работает по какой-то причине. В этом случае, вы можете попробовать другие команды блокировки , такие какcat
,read
,tail -f /dev/null
, иgrep a
т.д.источник
tail -f /dev/null
было также для меня рабочим решением на платформе SaaStail -f /dev/null
также имеет то преимущество, что не потребляет стандартный ввод. Я использовал это по этой причине.Как насчет отправки SIGSTOP самому себе?
Это должно приостановить процесс до получения SIGCONT. Что в вашем случае: никогда.
источник
Позвольте мне объяснить, почему
sleep infinity
работает, хотя это не задокументировано. Ответ jp48 также полезен.Самая важная вещь: указав
inf
илиinfinity
(независимо от регистра), вы можете спать дольше, чем позволяет ваша реализация (т.е. меньшее значениеHUGE_VAL
иTYPE_MAXIMUM(time_t)
).Теперь давайте углубимся в детали. Исходный код
sleep
команды можно прочитать из coreutils / src / sleep.c . По сути, функция делает это:Понимание
xstrtod (argv[i], &p, &s, cl_strtod)
xstrtod()
Согласно gnulib / lib / xstrtod.c , вызов
xstrtod()
преобразования преобразует строкуargv[i]
в значение с плавающей запятой и сохраняет ее*s
, используя функцию преобразованияcl_strtod()
.cl_strtod()
Как видно из coreutils / lib / cl-strtod.c ,
cl_strtod()
преобразует строку в значение с плавающей запятой, используяstrtod()
.strtod()
Согласно
man 3 strtod
,strtod()
преобразует строку в значение типаdouble
. На странице написанои бесконечность определяется как
Хотя в документе говорится
, не понятно, как лечится бесконечность. Итак, давайте посмотрим на исходный код gnulib / lib / strtod.c . То, что мы хотим прочитать, это
Таким образом,
INF
иINFINITY
(оба без учета регистра) рассматриваются какHUGE_VAL
.HUGE_VAL
семьяДавайте использовать N1570 в качестве стандарта C.
HUGE_VAL
,HUGE_VALF
ИHUGE_VALL
макросы определены в §7.12-3и в §7.12.1-5
Понимание
xnanosleep (s)
Теперь мы понимаем всю суть
xstrtod()
. Из приведенных выше объяснений совершенно ясно, чтоxnanosleep(s)
мы впервые увидели, что означаетxnanosleep(HUGE_VALL)
.xnanosleep()
Согласно исходному коду gnulib / lib / xnanosleep.c , по
xnanosleep(s)
сути это:dtotimespec()
Эта функция преобразует аргумент типа
double
в объект типаstruct timespec
. Поскольку это очень просто, позвольте мне привести исходный код gnulib / lib / dtotimespec.c . Все комментарии добавлены мной.Поскольку
time_t
определяется как целочисленный тип (см. §7.27.1-3), естественно, мы предполагаем, что максимальное значение типаtime_t
меньше, чемHUGE_VAL
(типаdouble
), что означает, что мы входим в случай переполнения. (На самом деле это предположение не является необходимым, поскольку во всех случаях процедура по существу одинакова.)make_timespec()
Последняя стена, на которую мы должны подняться, это
make_timespec()
. К счастью, это так просто, что достаточно сослаться на исходный код gnulib / lib / timespec.h .источник
У меня недавно была необходимость сделать это. Я придумал следующую функцию, которая позволит bash спать вечно без вызова какой-либо внешней программы:
ПРИМЕЧАНИЕ. Ранее я публиковал эту версию, в которой каждый раз открывался и закрывался дескриптор файла, но обнаружил, что в некоторых системах, выполняющих это сотни раз в секунду, в конечном итоге происходит блокировка. Таким образом, новое решение сохраняет дескриптор файла между вызовами функции. Bash все равно очистит при выходе.
Это можно вызвать так же, как / bin / sleep, и он будет спать в течение запрошенного времени. Вызывается без параметров, он будет висеть вечно.
В моем блоге есть рецензия с чрезмерными подробностями
источник
Этот подход не потребляет ресурсов для поддержки процесса.
while :; do sleep 1; done & kill -STOP $! && wait $!
Сломать
while :; do sleep 1; done &
Создает фиктивный процесс в фоновом режимеkill -STOP $!
Останавливает фоновый процессwait $!
Подождите, пока фоновый процесс, это будет блокировать навсегда, потому что фоновый процесс был остановлен доисточник
Вместо того, чтобы убивать оконный менеджер, попробуйте запустить новый с
--replace
или,-replace
если доступно.источник
--replace
я всегда получаю предупреждение, какanother window manager is already running
. Это не имеет большого смысла для меня, хотя.не дожидаясь детского процесса сна.
источник
stdin
если это все еще случается, связано сtty
. Если вы запускаете его с< /dev/null
занятыми циклами. Это может быть полезно в определенных ситуациях, поэтому я не буду понижать голос.