【问题标题】:How to sleep a random fraction of a second in POSIX shell?如何在 POSIX shell 中随机休眠几分之一秒?
【发布时间】:2011-12-07 03:40:59
【问题描述】:

以下内容不起作用:

/bin/sleep $(printf ".%02ds" $(( $RANDOM % 100 )))
  1. POSIX sleep 仅支持整数秒
  2. 没有$RANDOM

我可以通过以下方式随机模拟:

RAND255=$(od -An -N1 -t u1 /dev/urandom)

另一种选择是编写一个小的 C 程序,该程序利用 usleep()*rand*() 的建议,如 @dmckee@Keith Thompson 所建议的那样。部署这样的程序可能并不总是可行的。

有没有更好的方法,即在 POSIX 中,除了手写 C 程序之外,有没有一种可以接受几分之一秒的睡眠替代方法,是否有更好的方法来模拟 $RANDOM除了od?

【问题讨论】:

标签: shell random posix sleep sh


【解决方案1】:

在您的第一个命令中,例如,如果$RANDOM % 100 为6,它将调用/bin/sleep .6s;你想要/bin/sleep .06s

在第二个命令中,od -An -N1 -t u1 /dev/random 似乎打印了一个 0..255 范围内的数字——如果/dev/random 耗尽熵,命令本身可能会延迟很长时间。请改用/dev/urandom

我会编写一个调用usleep() 的小型C 程序(假设编译它并部署可执行文件是可行的)。

编辑

据我所知,您(更新后的)问题的答案是否定的。

POSIX 不保证 /dev/urandom,因此您的 od 命令不能移植到所有 POSIX 系统。我不相信 POSIX 指定任何可以休眠小数秒的命令。它确实指定了nanosleep() 函数,但是如果您不一定部署一个没有帮助的C 程序。 POSIX awk 没有睡眠功能。 Perl 不是 POSIX。

您的选择是:(1) 仅睡眠整秒,或 (2) 使用非便携式方法。

你需要这个用于什么环境?

【讨论】:

  • 0.6 与 0.06 在这种情况下无关紧要。我已将/dev/random 替换为/dev/urandom(似乎/dev/urandom/dev/random 所在的任何地方都可用)。部署 C 程序可能是可行的。
  • 如果 0.6 与 0.06 无关紧要,那么您并没有真正在随机的几分之一秒内睡觉。您能说明一下您的要求吗?
  • @Keith Thompson:标准规定sleep 的参数是一个整数。标准sleep 无法休眠几分之一秒。
  • @DarkDust:我知道。问题中的代码使用sleep 的版本,它接受.6s 之类的参数。
  • @J.F. Sebastian:如果你快速连续调用上面的 awk 解决方案,它会打印相同的数字。看起来 srand() 每秒只更改一次。
【解决方案2】:

Perl 有 usleep,但在加载的系统上,加载时间可能比短暂的睡眠时间更重要。

【讨论】:

  • 不保证 Perl 可用。
【解决方案3】:

Cliff 随机数生成器是一个非常简单的随机数生成器,它“通过不显示结构的随机性噪声球测试”。它很容易编程,不到 10 行 awk 代码:

 # cliff_rand.awk --- generate Cliff random numbers



 BEGIN { _cliff_seed = 0.1 }

 function cliff_rand()
 {
     _cliff_seed = (100 * log(_cliff_seed)) % 1
     if (_cliff_seed < 0)
         _cliff_seed = - _cliff_seed
     return _cliff_seed
 }

此算法需要初始“种子”为 0.1。每个新值都使用当前种子作为计算的输入。如果内置的 rand() 函数(请参阅数值函数)不够随机,您可以尝试使用此函数。

取自here

【讨论】:

  • 这正是我正在寻找的awk 'BEGIN { srand(); sleep(rand()) }'。但是POSIX awk 没有sleep() 功能。
  • 所以随机数生成部分没问题吧?只有睡眠有问题吗?
  • 你不能以某种方式使用 system() 睡觉吗?...只是我脑海中的一个想法/
  • /bin/sleep $(awk 'BEGIN { srand(); print rand() }')s 工作正常,但 POSIX sleep 仅支持整数秒。
【解决方案4】:

此解决方案通过轮询单调计数器 /proc/uptime 在 linux 上运行 - 它甚至可以在慢速系统上运行 1/100 秒:

#!/bin/sh

WAIT=567        # 5.67 sec

get_up()
{
        read -r UP REST </proc/uptime
        export UP=${UP%.*}${UP#*.}
}

get_up; START=$UP
while :; do get_up; test $((UP-START)) -ge $WAIT && break; done

这里有一个快速而肮脏的单行线(复制/粘贴!):

W=567;x(){ read U R </proc/uptime;U=${U%.*}${U#*.};};x;S=$U;while :;do x;test $((U-S)) -ge $W && break;done

【讨论】:

猜你喜欢
  • 2011-05-10
  • 2015-05-07
  • 2022-06-15
  • 2019-03-07
  • 2021-11-20
  • 2018-12-28
  • 1970-01-01
  • 2015-04-14
  • 2013-02-15
相关资源
最近更新 更多