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

eck*_*art 67 linux shell ubuntu

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

例如:

minute-command 5-minutes ping www.google.com
Run Code Online (Sandbox Code Playgroud)

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

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

Gom*_*dor 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
Run Code Online (Sandbox Code Playgroud)


Tob*_*ght 68

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

姓名

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
Run Code Online (Sandbox Code Playgroud)

比较:

/-----------------------------+------------+----------------\
|            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)       |
\-----------------------------+------------+----------------/
Run Code Online (Sandbox Code Playgroud)

笔记:

  1. timeout始终SIGKILL用作其最后的信号。
  2. timeout 当子程序这样做时,没有任何功能可以通过信号退出。

这两个程序的退出状态不同,但很难清楚地概括,因此我建议您自己查阅手册页。

由于timeout默认安装在更多系统上(coreutils在许多发行版中是标准包),我建议您使用它,除非您需要timelimit.

  • 为什么要使用一种而不是另一种? (10认同)
  • @BriceM.Dempsey 在我的本地机器上,超时存在,但 timelimit 不存在(尽管它可以从 repo 中获得)。所以,如果其中一个是预先安装的......除此之外,只要查看方法签名,我就可以看到它们做不同的事情,并且有不同的用例。 (2认同)

Has*_*tur 17

bash内置,没有coreutils

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

YourCommand & read -t 300 ;  kill $!                           # 1st version
YourCommand & read -t 300 || kill $!                           # 2nd version 
Run Code Online (Sandbox Code Playgroud)

说明:像往常一样,当您在后台使用 发送命令时&,其 PID 存储在内部变量中$!(存在于dash, csh, bash, tcsh, zsh...的现代版本中)。
真正使 shell 有所不同的是内置命令read[ 2 ]和选项的存在-t。在第一个版本中,如果用户在指定的秒数之前未完成一行输入,则指令将终止并生成错误返回代码。

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

第二个版本与第一个版本相同,但您只需按 即可中止终止超时enter
实际上,or 运算符仅在命令以非零的返回码退出时才||执行该kill语句read,例如超时到期时。如果您enter在那一刻之前按下,它将返回 0,并且不会终止您之前的命令。


Coreutils 解决方案[ 1 ]

coreutils的是你的系统,你有没有需要保存的时间和资源来调用外部程序, timeoutsleep并达到你的目标两者的完美方式。

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

timeout 5m YourCommand                                         # 3rd version 
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

说明

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

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

参考

  • [ 1 ] Coreutils
  • [ 2 ] Bash 初学者指南
  • [ 3 ] BashFAQ

  • “通过睡眠,您可以使用您的幻想或获得一些灵感 [链接到 Bash 常见问题解答]”+1 #thatsenoughinternetfortoday (2认同)

Tob*_*ght 11

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

ping -c 300 host.example.com
Run Code Online (Sandbox Code Playgroud)

有关更通用的解决方案,请参阅其他答案。

  • 我的印象是 OP 刚刚为具体示例提供了 `ping`。他不想要针对每个不同程序的逐案解决方案。 (7认同)

Mar*_*iae 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
Run Code Online (Sandbox Code Playgroud)

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

对(不常见的?)bash 表达式的解释$@:...:位置参数, ( $*, $@, "$*", "$@") 承认以下额外规范,例如:

"${@:START:COUNT}"
Run Code Online (Sandbox Code Playgroud)

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


use*_*118 5

既然你ping在你的例子中提到; 此命令有几个选项可以在特定时间后停止:

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

man ping