Як я сплю за мілісекунд в башш або кш


128

сон - дуже популярна команда, і ми можемо починати спати з 1 секунди:

# wait one second please 
sleep 1

але яка альтернатива, якщо мені потрібно зачекати лише 0,1 секунди або від 0,1 до 1 секунди?

  • зауваження: на Linux або OS X sleep 0.XXXпрацює чудово, але на solaris sleep 0.1або sleep 0.01- незаконний синтаксис

2
Чи можу я запитати, чому ти хочеш спати 1 мс?
Том О'Коннор

1
Так, звичайно, в моєму скрипті bash я додаю "спати 1", в деяких рядках, але сценарій працює дуже повільно, тому після деякого висновку я підрахував, що сон 0,1 також приносить хороші результати і швидше. Про затримку мені потрібно затримка для того, щоб щоб вирішити проблему ssh в моєму скрипті bash, я виконую паралельне входження в ssh на деяких машинах, очікуючи, і без затримки його не вийде, як ви знаєте з мого питання, затримка повинна відповідати як Linux, так і Solaris
yael

3
Яке б рішення ви не вибрали, майте на увазі, що сценарій оболонки не буде дуже точним з точки зору часу.
scai

Як щодо того, щоб зробити щось, на виконання якого потрібен дуже короткий час, але нічого не робить .. якecho "" >/dev/null
Том О'Коннор

Гарна ідея, але як приймати цю команду msec? , Мені потрібно 0,1 мсек, не менше того - :)
yael

Відповіді:


68

Bash має "завантажуваний" сон, який підтримує дробові секунди і виключає накладні витрати зовнішньої команди:

$ cd bash-3.2.48/examples/loadables
$ make sleep && mv sleep sleep.so
$ enable -f sleep.so sleep

Тоді:

$ which sleep
/usr/bin/sleep
$ builtin sleep
sleep: usage: sleep seconds[.fraction]
$ time (for f in `seq 1 10`; do builtin sleep 0.1; done)
real    0m1.000s
user    0m0.004s
sys     0m0.004s

Мінус полягає в тому, що завантажувальні файли можуть не надаватися у вашому bashбінарному файлі, тому вам потрібно буде скласти їх самостійно, як показано (хоча для Solaris це не обов'язково буде таким простим, як вище).

Станом наbash-4.4 (вересень 2016 р.) Усі завантажені файли тепер будуються та встановлюються за замовчуванням на платформах, які підтримують його, хоча вони побудовані як окремі файли спільного об’єкта та без .soсуфікса. Якщо ваш дистрибутив / ОС не зробили щось креативне, вам слід зробити це:

[ -z "$BASH_LOADABLES_PATH" ] &&
  BASH_LOADABLES_PATH=$(pkg-config bash --variable=loadablesdir 2>/dev/null)  
enable -f sleep sleep

(Сторінка підручника передбачає BASH_LOADABLES_PATH, що встановлюється автоматично, я вважаю, що це не так в офіційному розповсюдженні станом на 4.4.12. Якщо і коли він встановлений правильно, вам потрібно лише enable -f filename commandnameв міру необхідності.)

Якщо це не підходить, наступне найпростіше зробити - це створити або отримати sleepз GNU coreutils, це підтримує необхідну функцію. Команда POSIX sleepмінімальна, старіші версії Solaris реалізовані лише для цього. Solaris 11 sleep робить підтримку дрібних секунд.

В крайньому випадку ви можете використовувати perl(або будь-який інший сценарій, який вам потрібно вручити) із застереженням, яке ініціалізація перекладача може бути порівнянним із запланованим часом сну:

$ perl -e "select(undef,undef,undef,0.1);"
$ echo "after 100" | tclsh

2
Так, оскільки ви використовуєте, expectви, ймовірно, просто можете використовувати " after N", де N - мілісекунди, безпосередньо у вашому сценарії.
mr.spuratic

використовувати, usleepяк @Luis Vazquez та @sebix write
Ilan.K

Apple MacOS має сон BSD, який також підтримує дробові секунди
робологічний

125

Документація для sleepкоманди з coreutils говорить:

Історичні варіанти сну вимагали, щоб це число було цілим числом, і приймав лише один аргумент без суфікса. Однак сон GNU приймає довільні числа з плаваючою комою. Див. Плаваючу точку .

Отже , ви можете використовувати sleep 0.1, sleep 1.0e-1і подібні аргументи.


1
дивіться моє зауваження про SOLARIS OS
yael

Ви переплутати це і НЕ ?
scai

побачити моє оновлення в моїй
касі

1
Яель, я думаю, у твоєму питанні все ще є занадто багато негативів; ви впевнені, що маєте на увазі "не незаконний синтаксис"?
MadHatter

наприклад - я бігаю на Solaris 10 це: # сон 0,1 сон: поганий характер в аргументі, про Linux Linux сон 0,1 працює добре
yael

58

Сон приймає десяткові числа, щоб ви могли розбити це так:

1/2 секунди

 sleep 0.5

1/100 секунди

sleep 0.01

Отже, за мільйон секунди ви хотіли б

sleep 0.001

4
Ви також можете опустити початковий нуль перед десятковою комою. напр. sleep .5
Майк Каузер


Поговоріть про всіх інших, що надто ускладнюють це ...
Мартін,

1
@MikeCauser веде нулі набагато легше читати і сигналізує про намір читача коду пізніше. також краще, коли ви насправді займаєтеся математикою.
Олександр Міллс


8

Ви можете просто використовувати usleep. В якості параметра потрібні мікросекунди (= 1е-6 секунд), тому для сну 1 мілісекунда ви введете:

usleep 1000

1
$ usleep No command 'usleep' found, did you mean: Command 'sleep' from package 'coreutils' (main) usleep: command not found
Bulletmagnet

Ні, я маю на увазі usleepчастину initscriptsпакету, яка є стандартною принаймні у всіх дистрибутивах Red Hat; включаючи принаймні RHEL, CentOS, Fedora, Mageia / Mandriva та SuSE. Ось приклад: `` ``
Луїс Васкес

1
Ось приклад ілюстрації, запущеної в CentOS 7: `` $ $ usleep / usr / bin / usleep $ rpm -qf / usr / bin / usleep initscripts-9.49.37-1.el7_3.1.x86_64 `` `Підсумувати : - sleep(from coreutils ) працює з секундами - usleepinitscripts ) працює з мікросекундами
Luis Vazquez

4

У мене була така ж проблема (жодна оболонка не спить на Solaris), тому я написав свою:

  #include "stdio.h"
  int main(int argc, char **argv) {
     if(argc == 2) { usleep(atoi(argv[1])); }
     return 0;
}

Не перевіряє аргументи - я б рекомендував правильно записаний, якщо ви хочете його зберегти, але це (gcc usleep.c -o usleep) виведе вас із лунки.


1
Ви можете принаймні змінити цей голий usleep()виклик, щоб if(argc == 1) { usleep(atoi(argv[1])); }уникнути індексування поза межами масиву, що може призвести до будь-якої кількості несподіваних поведінок.
CVn

@aCVn Це насправді if (argc == 2) { usleep(atoi(argv[1])); }...
Дзвінок Ø

Також зауважте, що usleepодиниця становить μs, тому, щоб зачекати 1 секунду, вам потрібно надати аргумент 1000000.
Кільце Ø

@ RingØ Праворуч. Дурна помилка, хороший улов.
CVn

atoi()це жахливий вибір для перетворення рядка в int. Що atoi( "STRING" )повертається? atoi()не має можливості повернути будь-яку помилку.
Ендрю Генле

0

Мені подобається затишна ідея, але я не можу коментувати її. Оскільки це допомогло мені допомогти, я сподіваюся, що моя пропозиція може покращити ідею сплячого.

https://github.com/fedora-sysv/initscripts/blob/3c3fe4a4d1b2a1113ed302df3ac9866ded51b01b/src/usleep.c є фактичним вихідним кодом usleep.c в екосистемі redhat.

Спробуйте скласти це у своєму Solaris. Напевно, вам знадобиться https://www.opencsw.org/packages/libpopt0/ .

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