让命令运行5分钟的简单方法是什么?[重复]


66

这个问题已经在这里有了答案:

有没有一种简单的方法可以让特定命令(只能通过终止Ctrl-C)自动运行5分钟?

例如:

minute-command 5-minutes ping www.google.com

或任何其他不会终止的命令。

我希望能够指定一个时限,而不仅仅是5分钟。

Answers:


67

有(至少)两个程序提供此功能:

名称

timelimit —有效地限制了流程的绝对执行时间

概要

timelimit [-pq] [-S killsig] [-s warnsig] [-T killtime] [-t warntime] command [arguments ...]

名称

timeout -运行有时间限制的命令

概要

timeout [OPTION] DURATION COMMAND [ARG]...
timeout [OPTION]

它们的包装如下:

$ dlocate `which timeout timelimit`
timelimit: /usr/bin/timelimit
coreutils: /usr/bin/timeout

比较:

/-----------------------------+------------+----------------\
|            Feature          |  timelimit |     timeout    |
+=============================+============+================+
|   time to run               | -t time    | first argument |
+-----------------------------+------------+----------------+
|   terminate signal          | -s signal  | -s signal      |
+-----------------------------+------------+----------------+
|   grace period              | -T time    | -k time        |
+-----------------------------+------------+----------------+
|   kill signal               | -S signal  | (note 1)       |
+-----------------------------+------------+----------------+
|   propagate signals         | -p         | (note 2)       |
\-----------------------------+------------+----------------/

笔记:

  1. timeout始终将SIGKILL其用作最后一个信号。
  2. timeout 子程序这样做时,没有任何功能可以退出并带有信号。

这两个程序的退出状态有所不同,但是很难一目了然,因此我建议您自己查阅手册页。

由于timeout默认情况下已安装在更多系统上(coreutils在许多发行版中是标准软件包),因此除非您需要所提供的额外功能,否则我建议您使用它timelimit


10
为什么要使用一个而不是另一个?
Brice M. Dempsey

2
@ BriceM.Dempsey在我的本地计算机上,存在超时,但没有超时(尽管可以从存储库中获得)。因此,如果其中之一是预安装的...除此之外,仅查看方法签名,我就可以看到它们执行不同的操作,并具有不同的用例。
Benubird

请注意,至少存在两种​​的实现timelimit。请参阅如何杀死进程,并确保没有重复使用PID以获得有关它们和GNU超时的更多信息。
sch 2016年

1
@ BriceM.Dempsey timeout包含在GNU coreutils中timelimit没有。您可以没有安装任何一个,或者两个都没有安装。对于第二个时间,报告了时间限制执行命令,并在给定时间后使用给定信号终止生成的过程。首先发送“警告”信号,然后在超时后发送 “ kill”信号,类似于init(8)在关机时进行操作。因此,中间行为甚至有所不同。
Hastur

由于GNU coreutils已预先安装在每个GNU / Linux上,因此timeout是一种解决方法。
rexkogitans '16

87

实际上,这timeout是为了:

TIMEOUT(1)                          User Commands                         TIMEOUT(1)

NAME
       timeout - run a command with a time limit

SYNOPSIS
       timeout [OPTION] DURATION COMMAND [ARG]...
       timeout [OPTION]

DESCRIPTION
       Start COMMAND, and kill it if still running after DURATION.

lx@lxtp:~$ dpkg -S /usr/bin/timeout
coreutils: /usr/bin/timeout

16

bash内置,无coreutils

我发现该解决方案可以bash依靠内置命令运行而无需调用外部可执行文件。它适用于最终甚至没有安装coreutils [ 1 ]的系统

YourCommand & read -t 300 ;  kill $!                           # 1st version
YourCommand & read -t 300 || kill $!                           # 2nd version 

说明:像往常一样,当你在后台发送一个命令&,它的PID被存储到内部变量$!(存在于现代版的dashcshbashtcshzsh...)。
外壳之间真正有所不同的是内置命令read[ 2 ]和option的存在-t。在第一个版本中,如果用户在指定的秒数内未完成输入行,则该指令将终止并生成错误返回码。

-t TIMEOUT 如果超时时间内未读取完整的输入行,则导致读取超时并返回失败。

第二个版本与第一个版本相同,但是您可以按来终止终止超时enter
的确,仅当命令以返回码(不为零)退出(如超时到期)时,or运算符才||执行kill语句read。如果您enter在那一刻之前按下,它将返回0,并且不会终止您先前的命令。


Coreutils解决方案[ 1 ]

coreutils存在于您的系统中时,您无需节省时间和资源来调用外部程序, timeout并且sleep这两者都是实现目标的完美方法。

timeout的使用timeout很简单。
最终,-k如果第一个失败,您也可以考虑使用该选项发送附加的终止信号。

timeout 5m YourCommand                                         # 3rd version 

sleepsleep您一起可以使用自己的幻想或获得一些启发[ 3 ]。请注意,您可以将命令保留在后台或前台(例如,top通常需要放在前台)。

YourCommand & sleep 5m; kill $!                                # 4th Background
YourCommand & pid=$! ; (sleep 5m; kill $pid;) &                # 5th Background

bash -c '(sleep 5m; kill $$) & exec YourCommand'               # 6th Foreground
(cmdpid=$BASHPID; (sleep 5m; kill $cmdpid) & exec YourCommand) # 7th Foreground

说明

  • 在第4版中,您在后台执行,YourCommand然后在shell中执行sleep5分钟。完成后,最后的后台进程($!)将被终止。您停止外壳。
  • 在第5版中,您在后台执行,YourCommand然后立即将该PID存储在变量中$pid。然后,您在后台执行5分钟的小睡及其随后的命令,该命令将杀死存储的PID。由于您是在后台发送这组命令的,因此您不会停止外壳程序。您需要将PID存储在变量中,因为的值$!可以通过最终在后台执行另一个程序来更新。简而言之,您可以避免杀死错误的过程或根本没有任何过程的风险。
  • 在第6版中,它称为新的bash shell,它将在5分钟内通过自杀$$,然后执行您保留在前台的命令。
  • 在第7版中,它被调用一个子外壳(),该子外壳将其PID存储在变量(cmdpid)中,并在后台执行中发送的另一个子外壳中杀死自己,然后在前台运行YourCommand。

当然,在每个版本中,您都可以发送所需的kill信号,从默认的信号到极端的信号 kill -9,仅在真正需要时才使用。

参考文献

  • [ 1 ] Coreutils
  • [ 2 ] Bash入门指南
  • [ 3 ] BashFAQ

2
“睡觉时,您可以幻想或从中得到启发[链接到Bash FAQ]” +1 #thatsenoughinternetforday
joeytwiddle16年

11

对于您的特定情况,大多数ping支持实施-c--count在特定数量的ping之后终止:

ping -c 300 host.example.com

有关更一般的解决方案,请参见其他答案。


7
我得到的印象OP仅是ping为一个具体示例提供的。他不想为每个不同的程序提供个案解决方案。
user1717828 '16

8

您可以使用以下简单脚本来完成此操作:

#!/bin/bash

#
# $1 is the time to let the program run, and $2, $3, ... are the command itself.
#

"${@:2}" &
PID=$!
sleep "${@:1:1}"
kill -2 $PID

(信号SIGINT = 2,根据下面的评论中Matija Nalis的建议使用)。

bash表达式的解释(不常见?)$@:...:位置参数($*, $@, "$*", "$@")接受以下额外说明,例如:

"${@:START:COUNT}"

这意味着:在所有参数中,取COUNT个,第一个作为STARTth位置的参数;如果省略COUNT,则将它们全部取到最后,从STARTth位置开始。请记住,这$0是程序名称。如果START为负,则从末尾开始计数,并记住COUNT 不能为负,因此最后一个参数为"${@:-1}"。同样,几乎总是在双引号中包含位置参数。


1
我可能将脚本设计为以时间作为第一个或最后一个arg,然后将所有其他args作为命令运行。让bash单词拆分$1非常困难。另外,您也可以sleep "$1"在中输入内容countdown
彼得·科德斯

1
@PeterCordes根据您的意愿完成。
MariusMatutiae '16

您可以使用first arg中的时间执行操作time=$1; shift,然后不需要位置参数的数组切片语法。但是,是的,这要简单得多。
彼得·科德斯

1
@PeterCordes同意,但是您问我是否知道我知道一种更安全的方法来做到这一点,而我只是懒惰,还是只是一无所知。大声笑。
MariusMatutiae '16

如发帖人特别询问可以中断的程序,ctrl-c最好尝试kill -INT而不是尝试尝试kill -9(或至少-9在几秒钟后尝试,如果第一个程序不成功-它使程序有机会干净退出而不留下临时文件)等等)
Matija Nalis 2016-2-26

5

自从您ping在示例中提到;此命令有几个选项可以在特定时间后停止:

  • w 期限 指定ping退出之前的超时时间(以秒为单位),无论发送或接收了多少个数据包。在这种情况下,在发送计数数据包后ping不会停止,它会等待截止日期到期或直到响应计数探测或网络中的某些错误通知为止。
  • W timeout 等待响应的时间,以秒为单位。该选项仅在没有任何响应的情况下影响超时,否则ping将等待两个RTT。

-man ping

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.