Shell:是否可以在不使用 `sleep` 的情况下延迟命令?

use*_*697 23 linux shell bash sleep shell-script

是否有任何替代品、替代品或 bash 技巧可以在不使用的情况下延迟命令sleep?例如,在不实际使用睡眠的情况下执行以下命令:

$ sleep 10 && echo "This is a test"
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 32

使用bash内置函数,您可以执行以下操作:

coproc read -t 10 && wait "$!" || true
Run Code Online (Sandbox Code Playgroud)

休眠 10 秒而不使用sleep. 该coproc是让让read的标准输入就是任何事都不能出来的管道。|| true是因为wait的退出状态将反映 SIGALRM 传递,如果errexit设置了该选项,这将导致 shell 退出。

在其他外壳中:

mksh并且ksh93sleep内置的,在那里使用其他任何东西都没有意义(尽管它们都支持read -t)。

zsh也支持read -t,但也有一个内置的包装器select(),所以你也可以使用:

zmodload zsh/zselect
zselect -t 1000 # centiseconds
Run Code Online (Sandbox Code Playgroud)

如果您想要的是安排从交互式 shell 会话中运行的内容,另请参阅 中的zsh/sched模块zsh

  • @JeffSchaller 我会避免它,因为这是一个繁忙的循环。 (6认同)
  • @NormanGray,`/dev/zero` 是一个包含无限量数据(NUL 字节)的文件。所以`read`会在这10秒内尽可能多地读取。值得庆幸的是,对于不支持在其变量中存储 NUL 字节的 `bash`,它不会占用任何内存,但仍会占用 CPU 资源。 (6认同)
  • 你会考虑`read -t 10 < /dev/zero || 真的`? (2认同)
  • @NormanGray,如果从终端运行,`/dev/stdout` 将是 tty 设备,所以它会产生副作用(比如在后台运行时停止脚本),并且如果用户按下回车键就会返回。[`read -t 10 /dev/stdout | :`](/a/222609) 可以在 Linux 上运行,但只能在 Linux 上运行,而无论操作系统如何,`coproc` 都可以运行。 (2认同)

ss_*_*iwe 19

您有以下选择sleep:它们是atcron。与sleep这些相反,您需要提供您需要它们运行的​​时间。

  • atd通过执行确保服务正在运行service atd status
    现在假设日期是 UTC 时间上午 11:17;如果您需要在 UTC 时间 11:25 执行命令,则语法为:echo "This is a test" | at 11:25
    现在请记住,atd默认情况下不会记录作业的完成情况。有关更多信息,请参阅此链接。您的应用程序最好有自己的日志记录。

  • 您可以在 中安排作业cron,有关更多信息,请参阅:man cron查看其选项或crontab -e添加新作业。/var/log/cron可以检查有关作业执行的信息。

仅供参考,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

  • 这不是真的,你可以安排一个 at 工作,比如现在 +1 分钟,在一分钟内运行 (7认同)

ste*_*eve 9

一些其他的想法。

top -d10 -n2 >/dev/null

vmstat 10 2 >/dev/null

sar 10 1 >/dev/null

timeout 10s tail -f /dev/null
Run Code Online (Sandbox Code Playgroud)


mos*_*svy 7

由于有建议使用 的非标准-t delay选项的答案read,这里有一种在标准 shell 中进行超时读取的方法:

{ ss=`stty -g`; stty -icanon min 0 time 20; read foo; stty "$ss"; }
Run Code Online (Sandbox Code Playgroud)

的论点stty time是十分之一秒。


Jef*_*ler 6

使用 bash 内置变量$SECONDS和繁忙循环:

for((target=$((SECONDS + 10)); SECONDS < target; true)); do :; done
Run Code Online (Sandbox Code Playgroud)

  • 一个很好的加热方法。 (7认同)
  • 不会是我第一次被指责充满热空气!:) (7认同)
  • 这实际上会暂停 9 到 10 秒之间的持续时间(由于 [`bash` 中的错误](http://gnu-bash.2382.n7.nabble.com/minor-quot-precision -quot-of-SECONDS-td17094.html);`zsh` 和 `mksh` 有类似的问题,但已经修复) (2认同)

Psy*_*aut 5

回到运行 BASIC 的微型计算机的时代,延迟通常是通过一个空循环来完成的:

FOR I = 1 TO 10000:NEXT

可以使用相同的原理在 shell 脚本中插入延迟:

COUNTER=0; while [ $COUNTER -lt 10000 ]; do :; let COUNTER=COUNTER+1; done

当然,这种方法的问题在于延迟的长度会因机器的处理器速度而异(甚至在不同负载下的同一台机器上)。与 不同sleep,它可能还会最大限度地利用您的 CPU(或其核心之一)。

  • 一个很好的加热方法。 (2认同)
  • 延迟循环对于任何可以运行类 Unix 操作系统的现代 CPU 上的非常短的睡眠(几纳秒或设备驱动程序中的时钟周期)之外的任何事情来说都是一个糟糕的想法。即睡眠时间太短,您无法在等待时有效地让 CPU 做任何其他事情,例如安排另一个进程或在定时器中断唤醒之前进入低功耗睡眠状态。动态 CPU 频率甚至无法校准每秒计数的延迟循环,除非最小延迟可能在低时钟速度下休眠更长的时间,然后再上升。 (2认同)