Shell: чи можна затримати команду без використання "сну"?


21

Чи є замінники, альтернативи або баш-хитрощі для затримки команд без використання sleep? Наприклад, виконуючи команду нижче, фактично не використовуючи сон:

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

42
Що не так sleep?
муру

5
Немає жодної реальної причини, крім цікавості. Я думав, що було б цікаво вивчити деякі альтернативні рішення. Я думаю, це atможе бути один, але я не зміг знайти жодного прикладу використання.
користувач321697

1
@ user321697 "at" - це планувати окремі завдання. вони виконуються службою atd, тому вони не призупинять ваш скрипт оболонки. одним із випадків використання для at буде, щоб він робив щось у визначений час (асинхронізувати) та створював маркерний файл після його завершення, а ваш сценарій очікує появи цього файлу в циклі часу. ви можете домогтися аналогічного ефекту, запланувавши завдання, щоб відправити свій скрипт 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 пристроєм, тому він матиме побічні ефекти (наприклад, зупинка сценарію, якщо він працює у фоновому режимі) і повернеться, якщо користувач натисне, наприклад. 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
Ви "вкрали" мою думку про timelimit / timeout .... +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
Це фактично зробить паузу на тривалість від дев'яти до 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 Stéphane, звичайно, найкраща, моя - найстаріша --- 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, він, ймовірно, також максимум вашого CPU (або одного з його ядер).


2
Хороший спосіб зробити тепло.
ctrl-alt-delor

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

Стародавні комп’ютери мали енергоспоживання, яке значно менше залежало від навантаження. Сучасним процесорам потрібно максимально динамічно вимикати різні частини мікросхеми, щоб не плавитись (наприклад, вимкнення частин блоків виконання FPU або SIMD, поки працює лише цілий код, або принаймні передавати сигнал тактової частоти частинам мікросхеми які не потребують перемикання). І введення режиму сну з низькою потужністю, коли холостий режим (замість того, щоб крутитися в нескінченному циклі, що чекає перерви таймера), також є останнім часом, ніж стародавні комп'ютери, про які ви згадуєте.
Пітер Кордес

Докладніше про історію процесора див. У Сучасних мікропроцесорах 90-хвилинне керівництво! - lighterra.com/papers/modernmicroprocessors .
Пітер Кордес

3

Немає вбудованого, що робить те саме, що sleep(якщо sleepвбудований). Однак є деякі інші команди, які будуть чекати.

Кілька з них включають.

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

  • inotifywait: використовується для очікування файлу або файлів, які будуть змінені / видалені / додані / тощо


Дякую за це Чи можете ви надати приклад для виконання запланованого завдання (через 10 секунд) at?
користувач321697

1
редагування та оновлення! ;-)
Fabby

cronзберігати завдання в crontab, правда? Де atзберігаються заплановані дані?
користувач321697

@ User321697 Уже відповіли тут
Fabby

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

3

Класика з Країни Вікон та Пакетів:

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

Неправильне налаштування брандмауера або системи імен може призвести до значної додаткової затримки.
спектри

1
127.0.0.1 ... @spectras
AnoE

1
На щастя, більше не потрібна, оскільки Windows зараз підтримує сон спокійно.
Балдрікк

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

+1 за "приємні" спогади
AC

0

Якщо ви хочете інтерактивно чекати нового рядка у файлі, то

tail -f
.

Чекаєте змін у файловій системі? Потім використовуйте напр

inotify / inoticoming
.

А є й інші варіанти, залежно від того, що ви маєте на увазі під «чекати».

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.