Как мне спать в течение миллисекунды в Bash или Ksh


128

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

# wait one second please 
sleep 1

но какая альтернатива, если мне нужно подождать всего 0,1 секунды или от 0,1 до 1 секунды?

  • примечание: на linux или OS X sleep 0.XXXработает нормально, а на солярисе 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 мсек, не меньше этого - :)
Яэль

Ответы:


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

(Подразумевается, что страница man 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 - миллисекунды, прямо в вашем скрипте.
Мистер Спуратик

используйте usleepкак @Luis Vazquez и @sebix write
Ilan.K 20.02.16

Apple MacOS имеет режим
ожидания

125

Документация для sleepкоманды из coreutils гласит:

Исторические реализации sleep требовали, чтобы число было целым числом, и принимали только один аргумент без суффикса. Тем не менее, GNU Sleep принимает произвольные числа с плавающей запятой. Смотрите с плавающей точкой .

Следовательно , вы можете использовать sleep 0.1, sleep 1.0e-1и подобные аргументы.


1
см. мое замечание по поводу ОС SOLARIS
yael

Вы перепутать это и не ?
Scai

см. мое обновление в моей статье
yael

1
Яэль, я думаю, в твоем вопросе еще слишком много негативов; Вы уверены, что имеете в виду "не незаконный синтаксис"?
MadHatter

например - я запускаю на солярисе 10 вот это: # сон 0.1 сон: плохой символ в аргументе, про linux сон 0.1 работает нормально
яэль

58

Сон принимает десятичные числа, чтобы вы могли разбить его следующим образом:

1/2 секунды

 sleep 0.5

1/100 секунды

sleep 0.01

Так что за миллисекунду вы хотели бы

sleep 0.001

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


Поговорите о том, что все остальные слишком усложняют ...
Мартин,

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


8

Вы можете просто использовать usleep. Это занимает микросекунды (= 1e-6 секунд) в качестве параметра, поэтому, чтобы спать 1 миллисекунду, вы должны ввести:

usleep 1000

1
$ usleep No command 'usleep' found, did you mean: Command 'sleep' from package 'coreutils' (main) usleep: command not found
Пулевой магнит

Нет, я имею в виду 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(из coreutils ) работает с секундами - usleep(из initscripts ) работает с
Луис Васкес

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единица измерения - мкс, поэтому для ожидания 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.