Shell: возможно ли отложить команду без использования `sleep`?


21

Есть ли заменители, альтернативы или хитрости для задержки команд без использования sleep? Например, выполнив приведенную ниже команду без использования sleep:

$ sleep 10 && echo "This is a test"

42
Что не так с sleep?
Муру

5
Там нет реальной причины, кроме любопытства. Я подумал, что было бы интересно узнать некоторые альтернативные решения. Я думаю, что atможет быть один, но я не мог найти примеры использования.
user321697

1
@ user321697 «at» предназначен для планирования отдельных заданий. они выполняются службой atd, поэтому они не будут останавливать ваш сценарий оболочки. Один из вариантов использования at - это сделать что-то в указанное время (асинхронно) и создать файл маркера после его завершения, пока ваш скрипт ожидает появления этого файла в цикле while. Вы можете добиться аналогичного эффекта, запланировав задание на отправку сценария SIGCONT, а затем заморозив сценарий, отправив себе SIGSTOP.
Грега Бремец

1
Я пришел сюда, ожидая, что все предложат спинлок. Я приятно удивлен всеми ответами.
Даан ван Хук

3
Re: «Любопытство» - в unix.stackexchange.com/help/dont-ask обратите внимание на требование: «Вы должны задавать только практические, отвечающие на вопросы вопросы, основанные на реальных проблемах, с которыми вы сталкиваетесь », - что это было хорошо получил, несмотря на противоречие, что руководство делает его довольно редким исключением.
Чарльз Даффи

Ответы:


17

У вас есть альтернативы sleep: они есть atи cron. В противоположность sleepэтому вам необходимо указать время, в которое вы должны их запустить.

  • Убедитесь, что atdслужба работает, выполнивservice atd status .
    Теперь давайте скажем, что дата 11:17 UTC; если вам нужно выполнить команду в 11:25 UTC, синтаксис: echo "This is a test" | at 11:25.
    Имейте в виду, что atdпо умолчанию не будет регистрироваться завершение заданий. Для более подробной информации обратитесь по этой ссылке . Лучше, чтобы у вашего приложения была собственная регистрация.

  • Вы можете запланировать работу в cron, для более подробной информации: man cronчтобы увидеть его параметры или crontab -eдобавить новые работы. /var/log/cronможно проверить информацию о выполнении на рабочих местах.

FYI sleep system call приостанавливает текущее выполнение и планирует его с аргументом, переданным ему.

РЕДАКТИРОВАТЬ:

Как упомянул @Gaius, вы также можете добавить минутное время к atкоманде. Но скажем, время есть, 12:30:30и теперь вы запустили планировщик с помощью now +1 minutes. Хотя была указана 1 минута, что соответствует 60 секундам, на atсамом деле12:31:30 выполнения задания, а выполняет ее в 12:31:00. Единицы времени могут быть minutes, hours, days, or weeks. Для более подробной информацииman at

например: echo "ls" | at now +1 minutes


7
Это неправда, вы можете запланировать на работе, скажем, сейчас +1 минуту, чтобы запустить в течение минут
Гай

29

Со bashвстроенными вы можете сделать:

coproc read -t 10 && wait "$!" || true

Спать 10 секунд без использования sleep. Нужно coprocсделать так, чтобы readstdin - это труба, из которой ничего не выйдет. || trueэто потому чтоwait с тем, что состояние выхода будет отражать доставку SIGALRM, что приведет к выходу оболочки, если эта errexitопция установлена.

В других оболочках:

mkshи ksh93естьsleep встроенный, нет смысла использовать что-либо еще там (хотя они оба также поддерживают read -t).

zshтакже поддерживает read -t, но также имеет встроенную оболочку вокругselect() , так что вы также можете использовать:

zmodload zsh/zselect
zselect -t 1000 # centiseconds

Если вам нужно запланировать запуск вещей из сеанса интерактивной оболочки, см. Также zsh/schedмодуль вzsh .


Вы считаете read -t 10 < /dev/zero || true?
Джефф Шаллер

5
@JeffSchaller Я бы этого избегал, потому что это занятый цикл.
Стефан Шазелас

@ StéphaneChazelas Я бы не ожидал, что это будет занятый цикл - я ожидаю, что любая оболочка readбудет реализована с использованием select (2) или чего-то подобного (подразумевая, что чтение с тайм-аутом будет хорошим ответом на этот вопрос). Я выражаю удивление, а не противоречу вам, но можете ли вы указать на дальнейшее обсуждение этого?
Норман Грей,

5
@NormanGray, /dev/zeroэто файл, который содержит бесконечное количество данных (байтов NUL). Так readчто прочитайте столько, сколько сможете за эти 10 секунд. К счастью, в случае, bashкогда не поддерживается сохранение байтов NUL в своих переменных, это не израсходует никакой памяти, но при этом все равно увеличивает ресурсы процессора.
Стефан Шазелас

1
@NormanGray, если он запускается из терминала, /dev/stdoutбудет устройством tty, поэтому у него будут побочные эффекты (например, остановка сценария, если он работает в фоновом режиме), и он будет возвращаться, если пользователь нажимает, например, enter. read -t 10 /dev/stdout | :будет работать на Linux, но только на Linux, хотя coprocдолжен работать независимо от ОС.
Стефан Шазелас

7

Некоторые другие идеи.

top -d10 -n2 >/dev/null

vmstat 10 2 >/dev/null

sar 10 1 >/dev/null

timeout 10s tail -f /dev/null

1
Вы "украли" мое представление о предельном времени / тайм-ауте .... +1
Rui F Ribeiro

1
Оооооооооооооооооооочень было без сна, топ потрясающий!
Fire-Dragon-DoL

6

Поскольку есть ответы, которые предлагают использовать нестандартную -t delayопцию read, вот способ сделать тайм-аут чтения в стандартной оболочке:

{ ss=`stty -g`; stty -icanon min 0 time 20; read foo; stty "$ss"; }

Аргумент к stty timeнаходится в десятых долях секунды.


5

Использование встроенной переменной bash $SECONDSи цикла занятости:

for((target=$((SECONDS + 10)); SECONDS < target; true)); do :; done

2
Это фактически приведет к паузе в течение периода времени , начиная где - то между 9 и 10 секунд , хотя (из - за ошибки вbash , zshи mkshбыли подобные проблемы , но были установлены так)
Stéphane Chazelas

7
Хороший способ сделать тепло.
Ctrl-Alt-Delor

6
меня не обвинят в том, что я полон горячего воздуха! :)
Джефф Шаллер

4

самый старый трюк в книге:

read && echo "This is a test"

Просто нажмите, Enterи это будет продолжаться!


Это не будет, если процесс должен быть запущен без взаимодействия или в фоновом режиме, верно?
ss_iwe

Правильно: Но это не было одним из требований ОП согласно первоначальному вопросу, поэтому все еще действительный ответ ... ;-)> :-)
Fabby

1
ОП конкретно приводит пример (с sleep) и просит эквивалентную альтернативу без. Так readчто не разбираюсь, извините. ;)
AnoE

@AnoE Ответ Стефана, конечно, самый лучший, мой только самый старый --- press «enter» to continue --- ;-)
Fabby

4

В те времена, когда микрокомпьютеры работали с BASIC, задержки обычно заканчивались пустым циклом:

FOR I = 1 TO 10000:NEXT

Тот же принцип можно использовать для вставки задержки в сценарий оболочки:

COUNTER=0; while [ $COUNTER -lt 10000 ]; do :; let COUNTER=COUNTER+1; done

Конечно, проблема с этим подходом состоит в том, что длина задержки будет варьироваться от машины к машине в зависимости от скорости процессора (или даже на одной и той же машине при разных нагрузках). В отличие от этого sleep, он, вероятно, будет также максимально использовать ваш процессор (или одно из его ядер).


2
Хороший способ сделать тепло.
Ctrl-Alt-Delor

2
Циклы задержки - ужасная идея для всего, кроме самого короткого из снов (пара наносекунд или тактовых циклов в драйвере устройства) на любом современном процессоре, который может работать под Unix-подобной ОС. т. е. такой короткий сон, что ЦП не может с пользой делать что-либо еще во время ожидания, например, планировать другой процесс или переходить в режим ожидания с низким энергопотреблением, прежде чем проснуться от прерывания по таймеру. Динамическая частота ЦП делает невозможным даже калибровку контура задержки для отсчетов в секунду, за исключением минимальной задержки, которая потенциально может спать намного дольше на низких тактовых частотах до увеличения.
Питер Кордес

У древних компьютеров энергопотребление было намного меньше в зависимости от рабочей нагрузки. Современным процессорам необходимо максимально динамически отключать различные части чипа, чтобы не расплавить (например, отключить части исполнительных блоков FPU или SIMD, пока выполняется только целочисленный код, или, по крайней мере, передать синхросигнал частям чипа это не должно быть переключением). И переход в спящий режим с низким энергопотреблением во время простоя (вместо вращения в бесконечном цикле ожидания прерываний по таймеру) также более поздний, чем у древних компьютеров, о которых вы упоминали.
Питер Кордес

Для получения дополнительной информации об истории процессоров см. Руководство по современным микропроцессорам за 90 минут! - lighterra.com/papers/modernmicroprocessors .
Питер Кордес

3

Там нет встроенного, который делает так же, как sleep (если sleepне встроен). Однако есть некоторые другие команды, которые будут ждать.

Некоторые включают.

  • atи cron: используется для планирования задач в определенное время.

  • inotifywait: используется для ожидания файла или файлов, которые будут изменены / удалены / добавлены / и т. д.


Спасибо за это. Не могли бы вы привести пример выполнения запланированного задания (через 10 секунд) с помощью at?
user321697

1
редактировать и upvote! ;-)
Fabby

cronхранить задачи в crontab, верно? Где atхранятся запланированные данные?
user321697

@ user321697 Уже ответили здесь
Fabby

Извините, что вернули ваше редактирование в вопрос: вы изменили основную цель вопроса ОП, которая лишает законной силы самый простой ответ из всех ... ¯ \ _ (ツ) _ / ¯
Fabby

3

Классика из Страны окон и партий:

ping -c 11 localhost >/dev/null && echo "This is a test"

Неправильная настройка брандмауэра или системы имен может привести к значительной дополнительной задержке.
спектры

1
127.0.0.1 ... @spectras
AnoE

1
К счастью, больше не нужен, так как Windows теперь поддерживает режим сна.
Baldrickk

1
@AnoE> решает часть системы имен, а не часть брандмауэра. Хотя это и не распространено, его можно настроить так, чтобы он отбрасывал пинг на локальном интерфейсе. Это заставит пинг ждать намного дольше.
спектры

+1 за «теплые» воспоминания
AC

0

Если вы хотите в интерактивном режиме ждать новую строку в файле, то

tail -f
,

Ожидание изменения в файловой системе? Затем используйте, например,

inotify / inoticoming
,

И есть другие варианты, в зависимости от того, что вы подразумеваете под «ждать».

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.