经过一定时间后运行命令?


24

如果执行的过程很长,有什么方法可以执行一些基于时间的命令?

例如,我正在运行一个非常长的过程,大约需要10分钟。

5分钟后,我想运行一个单独的命令。为了说明起见,单独的命令可以是:echo 5 minutes complete

(注意:我不希望命令完成方面的进展,而只是在指定间隔后执行命令。)

可能吗?


1
在大多数情况下,您并不预先知道一个过程将花费多长时间。
choroba '16

您是什么意思“基于时间的命令”?您要创建进度条吗?根据您当前问题的措辞,您可以将长时间运行的命令放在后台,然后显示系统时钟。请澄清。
通配符

我确实在问题中阐明了@Wildcard。不是进度条。它将在某些时间间隔后执行命令
Aniket Bhattacharyea

1
“ 5分钟完成”是一件很奇怪的事情。不是“已经过去了5分钟”吗?不是“时间是_____”?您是否只想确保从开始长时间运行的命令开始到运行另一个任意命令之前已经过了指定的时间间隔?如果是这样,为什么不跑longcommand & sleep 300 && command-to-do-after-five-minutes?(实际上,这可能正是您要寻找的内容。)请注意,您所做的澄清还不够,因为您马上获得了两个时钟进度条实现。
通配符

Answers:


29

赶紧跑:

long-command & sleep 300; do-this-after-five-minutes

do-this-after-five-minutes五分钟后会得到执行。该long-command会在后台运行。


10
我通常使用sleep 5m && foobar,因此,如果我改变主意,而^ C the sleep,则下一条命令不会运行。
彼得·科德斯

@PeterCordes,当我使用eg sleep 3; ls和进行测试时^C,第二条命令始终无法运行。不太确定为什么,并且在非交互式shell中它可能会有所不同吗?
通配符

1
@PeterCordes不完全-除非每个sh​​ell都不同。当sleep 5m && echo处于睡眠状态时,当您挂起时,仅sleep命令被挂起。命令行的其余部分运行,但是由于sleep被挂起,因此未成功退出,并且之后的部分&&被跳过。尝试将其挂起sleep 5 || echo hello,并hello在按下后立即显示^Z
hdd

1
@hvd:是的,你是对的,我又错了,>。<,使用bash4。显然,自从我决定以&&作为贫民区at(1)sleep 30m && mplayer something.mp3警报提醒之类的东西或sleep 90m && fg以后恢复磁盘密集型命令的方式以来,时间已经太久了。因此,实际上sleep 5m && echo hello很不错,因为在根本不运行以下命令的情况下^Z挂起sleep。如果您希望甚至在睡眠退出之前就可以挂起/恢复整个复合命令,请使用( sleep 2 && echo hello )
彼得·科德斯

@hvd:该&&惯用语可让您绝对确定睡眠运行不会立即终止进程(因为您^Z不能运行该命令,而不会冒风险^C)。这在sleep && fgsleep && bg用例中很有用,因为恢复命令的过程有些缓慢。
彼得·科德斯

5

您可以使用以下脚本:

#!/bin/bash

TEMPFILE="$(mktemp)"
STARTTIME="$(date +%s)"
(./longprocess; rm -f "$TEMPFILE") &
while [ -f "$TEMPFILE" ]; do
    sleep 1s
    NOW="$(date +%s)"
    if (( (NOW-STARTTIME) % 300 == 0 )); then
        echo "$(( (NOW-STARTTIME)/60 )) minute(s) elapsed"
    fi
done
echo "Done!!!"

它执行你longprocesssub-shell生存,然后监视器前面创建的“锁”的文件。


2
检查man bashSECONDS。您可以SECONDS=0在脚本启动时进行设置,仅检查是否等于或大于300,或者在脚本中设置SECONDS=$((date +%s))并忘记date再次使用...

@yeti,感谢您的提示,我不知道。
Serge

@yeti,如果您想sleep 1s一直比现在晚一秒钟之后再依靠时间sleep 1s……那么您就成了程序员相信时间的虚假的受害者。(尽管在这种情况下,您也可能只显示一个哈希标记进度条之类的东西。)
通配符

@Wildcard ...我一点都没提sleep

@yeti,对,你是。感谢您的提示SECONDS!:)
通配符

4

为此有一个衬板:

( ( sleep $TIMEOUT ; echo "5 minutes complete") & $COMMAND )

在您的情况下TIMEOUT = 5m,而COMMAND是长命令。

另请参阅我对这篇文章的回答“服务网络重启”超时


在前台启动子shell,然后执行命令似乎不必要地复杂。我将删除外部括号和exec。
格伦·杰克曼

1
@glennjackman这样,可以杀死将CTRL + C(例如)发送到主(最外)子Shell的整个过程。
coffeMug

1
但是使用exec时,您将不再具有子外壳,而只有命令。该命令的父级是运行脚本的外壳,就像您根本没有使用子外壳一样。
格伦杰克曼(Glenn Jackman)'16

3
#! /bin/bash

( sleep 4 ) & # <-- The long running process.

seconds=1
while jobs %1 &>/dev/null ; do
    echo $((seconds++)) seconds complete
    sleep 1    
done
echo Done.

jobs %1 作业%1停止后失败。

请注意,较长的时间,$ seconds可能与实时不同步。最好存储开始时间并计算与实际时间的差。

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.