我如何在bash或ksh中睡眠一毫秒


128

sleep是一个非常流行的命令,我们可以从1秒开始睡眠:

# wait one second please 
sleep 1

但是如果我只需要等待0.1秒或等待0.1到1秒,该怎么办?

  • 备注:在linux或OS X上sleep 0.XXX工作正常,但在solaris sleep 0.1sleep 0.01-非法语法上

2
请问为什么要睡1ms?
Tom O'Connor 2013年

1
是的,当然可以,在我的bash脚本中,我在某些行中添加了“ sleep 1”,但是脚本运行非常缓慢,因此,在得出一些结论之后,我计算出sleep 0.1也会带来更好的结果,并且速度更快。关于延迟,我需要按顺序进行延迟为了解决我的bash脚本中的ssh问题,我按期望执行paralel ssh登录到某些机器,并且没有延迟,它将无法正常工作,如您所知,延迟应该适合Linux和Solaris
yael 2013年

3
无论选择哪种解决方案,请记住,shell脚本在计时方面不是很准确。
scai 2013年

如何执行需要很短时间才能执行但无所事事的事情。例如echo "" >/dev/null
Tom O'Connor

好主意,但是此命令需要多少毫秒?,我需要0.1毫秒,不小于-:)
yael 2013年

Answers:


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年9月),所有可加载项现在默认情况下都已构建并安装在支持它的平台上,尽管它们是作为单独的共享库文件构建的,并且没有.so后缀。除非您的发行版/ OS做了一些创造性的工作,否则您应该可以做到:

[ -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为毫秒。
2013年

usleep像@Luis Vazquez和@sebix这样使用
Ilan.K,2016年

苹果MacOS具有BSD睡眠功能,还支持小数秒
roblogic

125

sleep来自coreutils的命令文档说:

睡眠的历史实现要求该数字为整数,并且仅接受不带后缀的单个参数。但是,GNU sleep接受任意浮点数。请参阅 浮点数

因此,你可以使用sleep 0.1sleep 1.0e-1而类似的论据。


1
看到我关于SOLARIS OS的评论
yael 2013年

你混淆了不是
scai 2013年

查看我的最新动态
yael 2013年

1
Yael,我认为您的问题中仍有太多否定因素;您确定您的意思是“非非法语法”吗?
MadHatter

例如-我在solaris 10上运行以下命令:
#sleep

58

睡眠接受十进制数字,因此您可以将其分解为:

1/2秒

 sleep 0.5

1/100秒

sleep 0.01

所以你想要一毫秒

sleep 0.001

4
您还可以在小数点前删除前导零。例如。sleep .5
Mike Causer 2014年


谈论其他人使它过于复杂...
马丁

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
Bulletmagnet

不,我的意思usleepinitscripts包装的一部分,至少在所有从Red Hat发行的发行版中都是标准的;至少包括RHEL,CentOS,Fedora,Mageia / Mandriva和SuSE。下面一个例子:````
路易斯·巴斯克斯

1
这是在CentOS 7中运行的示例ilustration:`$其中usleep / usr / bin / usleep $ rpm -qf / usr / bin / usleep initscripts-9.49.37-1.el7_3.1.x86_64```总结: - sleep(来自的coreutils)可与秒- usleep(从启动脚本)用微秒工作
路易斯Vazquez的

4

我遇到了同样的问题(在Solaris上没有shell睡眠),因此我这样写了自己的问题:

  #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()没有办法返回任何错误。
安德鲁·亨利

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.