在终端中每x时间间隔重复一次命令?


142

如何在每个时间间隔内重复执行命令,以便可以运行命令来检查监视 目录?

不需要脚本,我只需要在终端中执行一个简单的命令即可。

Answers:


219

您可以使用 watch命令,watch用于定期运行任何指定的命令。

打开终端并输入:

watch -n x <your command>

x更改为所需的时间(以秒为单位)。

有关使用watch命令及其选项的更多帮助,请运行man watch或访问此链接

例如:以下将每60秒在同一终端上列出Desktop目录的内容,以便您知道是否进行了任何更改:

watch -n 60 ls -l ~/Desktop

34
+1,但使用扩展时要小心。例如,尝试watch -n 1 'echo $COLUMNS'watch -n 1 echo $COLUMNS调整终端大小之间的区别-前者每秒扩展一次,而后者 watch启动仅扩展一次。
l0b0

它像一个魅力!Ty nux

我对此解决方案的问题是,您不能将监视作为一个进程运行,而只能使其在后台运行(例如,使用&disown)
Cestarian 2015年

2
有什么方法可以watch与“启用历史记录”类型的命令一起使用吗?我喜欢使用watch,但有时我也希望查看以前执行的日志,而不仅仅是最后一个。是的,我知道我可以使用脚本(while true)来完成此操作,但是使用watch实用程序会更加干净!
rinogo

这对于较简单的命令有效,但是对于管道命令链接而言,这对我不起作用。grep“通话” | wc -l
Sudip Bhandari 2016年

90

除了nux的答案,您还可以在终端中使用此命令:

while true; do <your_command>; sleep <interval_in_seconds>; done

while true; do ls; sleep 2; done

此命令将以ls2秒的间隔打印输出。

使用Ctrl+ C停止该过程。

有几个缺点 watch

  • 它不能使用任何别名命令。
  • 如果任何命令的输出都非常长,则滚动无法正常工作。
  • 设置最大时间间隔超过一定值会有些麻烦。
  • watch将使用-c--color选项解释通过转义字符的ANSI颜色序列。例如,输出pygmentize会起作用,但会失败ls --color=auto

在上述情况下,这可能是一个更好的选择。


watch为此而存在,我会说这没用
Bruno Pereira 2014年

14
我并不是说这个答案应该首先使用。watch在大多数情况下是好的。这就是为什么我一开始提到“除了nux的答案”。但是存在一些问题,watch例如,不能将任何别名命令与一起使用watch。以ll哪个为别名ls -laF但不能与一起使用为例watch。同样,如果任何命令的输出很长,则在使用滚动时会遇到麻烦watch。在这几种特殊情况下,此答案可能是一个更好的选择。
souravc 2014年

@souravc我的版本watch至少允许-c--color选项用于彩色输出。
莉莉·钟

8
while sleep x更好-更容易杀死。
d33tah 2014年

3
这是一个不错的选择,并且不同于watch,它保留了命令历史记录。
adelriosantiago

34

只是想了解souravcnux的答案:

  1. 虽然watch可以在Ubuntu上完美运行,但是如果希望“ Unix-fu”是纯净的,则可能要避免-例如,在FreeBSD上,watch是“监听另一个tty行”的命令。
  2. while true; do command; sleep SECONDS; done还有一个警告-使用CTR + C可能更难以杀死您的命令。您可能想首选while sleep SECONDS; do command; done-它不仅更短,而且更易于打扰。需要注意的是,它将首先休眠,然后运行您的命令,因此您需要等待一些时间SECONDS才能首次出现该命令。

2
希望它可以作为回答而不是评论来接受-我想在这里展示另一种解决方案,而评论实际上会减少我的注意力。
d33tah 2014年

到底为什么它很重要,你把sleepwhile循环?我找不到任何区别,无论如何,Ctrl + C都会立即中断循环。
甜点

@dessert:取决于您想从我想突破的东西。通常,ctrl + c只会杀死您commandsleep并且只有在您杀死时才会中断true
d33tah

11

听起来像是cron守护程序的理想任务,它允许运行定期命令。运行crontab -e命令以开始编辑用户的cron配置。其格式记录在crontab(5)中。基本上,您有五个与时间相关的,以空格分隔的字段,后跟一个命令:

The time and date fields are:

       field          allowed values
       -----          --------------
       minute         0-59
       hour           0-23
       day of month   1-31
       month          1-12 (or names, see below)
       day of week    0-7 (0 or 7 is Sunday, or use names)

例如,如果您想在每个星期二的上午11点运行Python脚本:

0 11 * * 1 python ~/yourscript.py

还有一些特殊的名称可以代替时间,例如@reboot。如果您需要创建一个临时目录,这将非常有帮助。从我的crontab(以列出crontab -l):

# Creates a temporary directory for ~/.distcc at boot
@reboot ln -sfn "$(mktemp -d "/tmp/distcc.XXXXXXXX")" "$HOME/.distcc"

4
问题询问如何在终端中定期运行某些内容。 cron跑在幕后而不是在终点站
布拉德利北部,2014年

5

如果您正在监视文件系统,那将inotifywait非常出色,并且无疑会增加系统负载。

范例:

第一终端输入以下命令:

$ inotifywait .

然后在第二终端中,任何会影响当前目录的命令,

$ touch newfile

然后在原始终端中,inotifywait将唤醒并报告事件

./ CREATE newfile2

或循环

$ while true ; do inotifywait . ; done
Setting up watches.  
Watches established.
./ OPEN newfile2
Setting up watches.  
Watches established.
./ OPEN newfile2
Setting up watches.  
Watches established.
./ DELETE newfile
Setting up watches.  
Watches established.
./ CREATE,ISDIR newdir
Setting up watches.  
Watches established.

用户告诉你,没有脚本,也许他不希望监视什么
马钱

3
我没有告诉他写脚本,我建议如果他们为了观察特定的文件系统事件而循环,那么inotifywait是有用的,并且比重复命令使用更少的资源。我经常在命令行上运行几个命令,例如grep something InALogFile|less,这是一个脚本吗?
X天

它是一个很好的答案,尝试编辑它看起来更简单。
马钱

3
有什么比.我不能遗漏命令更简单的了。
X天

感谢@XTian,一个很棒的命令。现在,我还在手册页中看到您可以添加它-m以进行连续监视而没有循环。
yoniLavi 2014年

4

您可以repeat按照以下步骤创建自己的命令:学分在这里

首先,打开.bash_aliases文件:

$ xdg-open ~/.bash-aliases

其次,将这些行粘贴到文件的底部并保存:

repeat() {
n=$1
shift
while [ $(( n -= 1 )) -ge 0 ]
do
    "$@"
done
}

第三,关闭并再次打开终端,或键入:

$ source ~/.bash_aliases

等等!您现在可以像这样使用它:

$ repeat 5 echo Hello World !!!

要么

$ repeat 5 ./myscript.sh

xdg-open〜/ .bash-aliases行中有一个小的错字。应该是:xdg-open〜/ .bash_aliases(即下划线)
ssinfod

4

您可以使用crontab。运行命令crontab -e并使用您喜欢的文本编辑器将其打开,然后添加此行

*/10 * * * *  /path-to-your-command

这将每10分钟运行一次命令

* */4 * * *  /path-to-your-command

这将每4小时运行一次命令

另一种可能的解决方案

$ ..some command...; for i in $(seq X); do $cmd; sleep Y; done

X次重复。

时间等待重复。

范例:

$ echo; for i in $(seq 5); do $cmd "This is echo number: $i"; sleep 1;done

为什么会有改善?您只是通过将命令另存为变量来添加了一个多余的步骤。这样做的唯一的事情是我),使其不再Ⅱ型),迫使你只能使用简单的命令,没有任何管道或重定向等
terdon

删除额外的变量
Maythux,2015年

3

上面提出的“监视”方法的另一个问题是它仅在完成处理后才显示结果。“ date; sleep 58; date”仅在59秒后才会显示2个日期...如果您开始运行4分钟的内容,它会缓慢显示多页内容,那么您将不会真正看到它。

另一方面,“ while”方法的问题在于它没有考虑任务持续时间。

while true; do script_that_take_between_10s_to_50s.sh; sleep 50; done

这样,脚本将每分钟运行一次,有时可能需要1分40秒。因此,即使cron能够每分钟运行一次,在这里也不会。

因此,要在外壳程序生成时查看其输出并等待确切的请求时间,您需要查看之前和之后的时间,并使用while循环。

就像是:

while ( true ); do
  echo Date starting `date`
  before=`date +%s`
  sleep `echo $(( ( RANDOM % 30 )  + 1 ))`
  echo Before waiting `date`
  after=`date +%s`
  DELAY=`echo "60-($after-$before)" | bc`
  sleep $DELAY
  echo Done waiting `date`
done

这将输出以下内容:

如您所见,该命令每分钟运行一次:

Date starting Mon Dec 14 15:49:34 EST 2015
Before waiting Mon Dec 14 15:49:52 EST 2015
Done waiting Mon Dec 14 15:50:34 EST 2015

Date starting Mon Dec 14 15:50:34 EST 2015
Before waiting Mon Dec 14 15:50:39 EST 2015
Done waiting Mon Dec 14 15:51:34 EST 2015

因此,只需将“ sleep echo $(( ( RANDOM % 30 ) + 1 ))”命令替换为您想要的任何内容,即可在终端/外壳上每分钟运行一次。如果您需要其他时间表,只需将“ 60”秒更改为所需的时间即可。

没有调试行的较短版本:

while ( true ); do
  before=`date +%s`
  sleep `echo $(( ( RANDOM % 30 )  + 1 ))` # Place you command here
  after=`date +%s`
  DELAY=`echo "60-($after-$before)" | bc`
  sleep $DELAY
done

回复我自己...如果您的命令花费的时间超过了您配置的延迟,则$ DELAY将获得负值,并且sleep命令将失败,因此脚本将立即重新启动。需要意识到这一点。
jmspaggi 2015年
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.