Shell:是否可以不使用sleep来延迟命令?


21

是否有替代品,替代品或bash技巧来延迟不使用命令sleep?例如,执行以下命令而不实际使用sleep:

$ sleep 10 && echo "This is a test"

42
这有什么错sleep
muru

5
除了好奇心外,没有其他真正的原因。我认为学习一些替代解决方案会很有趣。我想at可能是一个,但是我找不到任何用法示例。
user321697 '18

1
@ user321697“ at”用于计划单个作业。它们由atd服务执行,因此它们不会暂停您的Shell脚本。at的一个用例是让它在指定时间执行操作(异步)并在完成时创建标记文件,而脚本正在等待该文件出现在while循环中。您可以通过安排作业向脚本发送SIGCONT然后通过向自己发送SIGSTOP冻结脚本来达到类似的效果。
Grega Bremec '18

1
我来这里是希望每个人都提出一个自旋锁。我为所有答案感到惊讶。
达恩·范·霍克

3
回复:“好奇心”-在unix.stackexchange.com/help/dont-ask中,请注意以下要求:“您只能根据所面临的实际问题提出切实可行的问题。 -尽管对该准则提出了质疑,但仍收到了该报告,这是一个非常罕见的例外。
查尔斯·达菲

Answers:


17

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

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

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

FYI sleep system call 暂停当前​​执行并安排传递给它的参数。

编辑:

作为@Gaius提到的,你还可以添加分钟时间atcommand.But可以说,时间是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


7
这是不正确的,您可以安排一个工作,例如现在+1分钟,以便在一分钟内运行
Gaius

29

bash内建函数,您可以执行以下操作:

coproc read -t 10 && wait "$!" || true

不使用睡10秒钟sleep。该coproc是让让read的stdin是一个管道,在那里什么都不会出来。|| true这是因为wait的退出状态将反映SIGALRM交付,如果errexit设置了该选项,则将导致外壳退出。

在其他shell中:

mkshksh93sleep内置功能,因此在那里使用其他任何东西都没有意义(尽管它们都支持read -t)。

zsh还支持read -t,但周围也有内置包装器select(),因此您还可以使用:

zmodload zsh/zselect
zselect -t 1000 # centiseconds

如果要调度从交互式Shell会话中运行的程序,请参见中的zsh/sched模块zsh


你会考虑read -t 10 < /dev/zero || true吗?
杰夫·谢勒

5
@JeffSchaller我会避免它,因为这是一个繁忙的循环。
斯特凡Chazelas

@StéphaneChazelas我不希望这是一个繁忙的循环–我希望read可以使用select(2)或类似的东西来实现任何shell (这意味着超时读取将很好地解决这个问题)。我表示惊讶而不是与您矛盾,但是您能指出对此进行进一步讨论吗?
诺曼·格雷

5
@NormanGray /dev/zero是一个包含无限量数据(NUL字节)的文件。因此read,在这10秒钟内将尽可能多地阅读。值得庆幸的是,在bash不支持将NUL字节存储在其变量中的情况下,它不会占用任何内存,但仍会占用CPU资源。
斯特凡Chazelas

1
@NormanGray如果从终端运行,/dev/stdout将是tty设备,因此会产生副作用(例如,如果在后台运行则停止脚本),并且例如在用户按下Enter键时返回。read -t 10 /dev/stdout | :可以在Linux上运行,但只能在Linux上运行,而coproc与操作系统无关。
斯特凡Chazelas

7

其他一些想法。

top -d10 -n2 >/dev/null

vmstat 10 2 >/dev/null

sar 10 1 >/dev/null

timeout 10s tail -f /dev/null

1
您“偷走”了我的时间限制/超时的想法。...+1
Rui F Ribeiro

1
哦,我的,谢谢,我当时处在无法入睡的状态,顶极了!
Fire-Dragon-DoL

6

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

{ ss=`stty -g`; stty -icanon min 0 time 20; read foo; stty "$ss"; }

的论点以stty time十分之一秒为单位。


5

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

for((target=$((SECONDS + 10)); SECONDS < target; true)); do :; done

2
这实际上会暂停一段时间不等秒9和10之间的某个地方,虽然(由于中的错误bash ; zshmksh有类似的问题,但一直以来固定)
斯特凡Chazelas

7
加热的好方法。
ctrl-alt-delor

6
不会是我第一次被指控充满热气!:)
杰夫·谢勒

4

书中最古老的把戏:

read && echo "This is a test"

只需点击Enter,它将继续!


如果流程需要在无交互的情况下运行或在后台运行,这不会吗?
ss_iwe

正确:但这不是原始问题所要求的OP的要求之一,因此仍然是有效的答案... ;
Fabby 18'Nov

1
OP专门给出了一个示例(带有sleep),并要求提供一个不带一个等效选项。所以read不解析,对不起。;)
AnoE

@AnoEStéphane的答案当然是最好的,我的才是最古老的--- press «enter» to continue --- ;-)
Fabby

4

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

FOR I = 1 TO 10000:NEXT

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

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

当然,这种方法的问题在于,延迟的长度会根据机器的处理器速度(甚至在不同负载下的同一台机器上)而在机器之间变化。与不同sleep,它可能还会使您的CPU(或其内核之一)达到最大。


2
加热的好方法。
ctrl-alt-delor

2
对于任何可以运行类似Unix操作系统的现代CPU而言,除了最短的睡眠时间(设备驱动程序中的几个纳秒或时钟周期)之外,延迟循环对于任何事物而言都是一个可怕的主意。也就是说,睡眠时间太短,以至于在等待定时器中断之前,CPU无法在等待时进行其他任何事情,例如安排另一个进程或进入低功耗睡眠状态。动态的CPU频率使它甚至无法校准每秒计数的延迟循环,除非是最小延迟,否则在加速之前可能会以低时钟速度睡眠更长的时间。
彼得·科德斯

古代计算机的功耗很少依赖于工作负载。现代CPU需要尽可能多地动态关闭芯片的不同部分以使其不熔化(例如,当仅运行整数代码时,关闭FPU或SIMD执行单元的部分,或者至少将时钟信号选通到部分芯片不需要切换)。而且,闲置时进入低功耗睡眠状态(而不是进入无限循环以等待计时器中断)比您提到的古老计算机更新。
彼得·科德斯

有关CPU历史记录的更多信息,请参见《现代微处理器90分钟指南》!- lighterra.com/papers/modernmicroprocessors
彼得·科德斯

3

没有内置功能,其功能与之相同sleep(除非sleep是内置功能)。但是,还有其他一些命令将等待。

一些包括。

  • atcron:用于在特定时间安排任务。

  • inotifywait:用于等待文件,或文件被修改/删除/添加/等


谢谢你 您能否提供一个示例来执行预定的任务(从现在开始10秒)at
user321697 '18

1
编辑和支持! ;-)
Fabby

cron将任务存储在中crontab,对吗?at计划的数据存储在哪里?
user321697 '18

@ user321697已在此处
Fabby

对不起,您的编辑恢复回问:你改这将作废的所有......最简单的答案OP的问题的主要目的¯\ _(ツ)_ /¯
Fabby

3

Windows和批处理领域的经典著作:

ping -c 11 localhost >/dev/null && echo "This is a test"

防火墙或名称系统配置错误可能会带来严重的额外延迟。
光谱

1
127.0.0.1 ... @spectras
AnoE

1
幸运的是,由于Windows现在支持本地睡眠,因此不再需要。
Baldrickk

1
@AnoE>解决名称系统部分,而不是防火墙部分。尽管不常见,但可以将其配置为在本地接口上静默删除ping。这将导致ping等待更长的时间。
光谱

为“喜欢的”记忆+1
AC

0

如果要交互式地等待文件中的新行,则

tail -f

等待文件系统上的更改?然后使用例如

inotify / inoticoming

还有其他选择,具体取决于您对“等待”的含义。

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.