如何为 shell 脚本引入超时?

Rad*_*dek 41 shell-script timeout

我想运行一个包含循环的 shell 脚本,它可以永远运行,而我不想发生这种情况。所以我需要为整个脚本引入一个超时时间。

如何在 SuSE 下为整个 shell 脚本引入超时?

Mat*_*teo 32

如果 GNUtimeout不可用,您可以使用expect(Mac OS X、BSD、...默认情况下通常没有 GNU 工具和实用程序)。

################################################################################
# Executes command with a timeout
# Params:
#   $1 timeout in seconds
#   $2 command
# Returns 1 if timed out 0 otherwise
timeout() {

    time=$1

    # start the command in a subshell to avoid problem with pipes
    # (spawn accepts one command)
    command="/bin/sh -c \"$2\""

    expect -c "set echo \"-noecho\"; set timeout $time; spawn -noecho $command; expect timeout { exit 1 } eof { exit 0 }"    

    if [ $? = 1 ] ; then
        echo "Timeout after ${time} seconds"
    fi

}
Run Code Online (Sandbox Code Playgroud)

编辑 示例:

timeout 10 "ls ${HOME}"
Run Code Online (Sandbox Code Playgroud)


Tim*_*edy 17

谢谢你的澄清。

完成您所追求的任务的最简单方法是在包装器中使用循环运行脚本,例如timeoutGNU Coreutils 包中的命令。

root@coraid-sp:~# timeout --help            
Usage: timeout [OPTION] DURATION COMMAND [ARG]...
   or: timeout [OPTION]
Start COMMAND, and kill it if still running after DURATION.

Mandatory arguments to long options are mandatory for short options too.
  -k, --kill-after=DURATION
                   also send a KILL signal if COMMAND is still running
                   this long after the initial signal was sent.
  -s, --signal=SIGNAL
                   specify the signal to be sent on timeout.
                   SIGNAL may be a name like 'HUP' or a number.
                   See `kill -l` for a list of signals
      --help     display this help and exit
      --version  output version information and exit

DURATION is an integer with an optional suffix:
`s' for seconds(the default), `m' for minutes, `h' for hours or `d' for days.

If the command times out, then exit with status 124.  Otherwise, exit
with the status of COMMAND.  If no signal is specified, send the TERM
signal upon timeout.  The TERM signal kills any process that does not
block or catch that signal.  For other processes, it may be necessary to
use the KILL (9) signal, since this signal cannot be caught.

Report timeout bugs to bug-coreutils@gnu.org
GNU coreutils home page: <http://www.gnu.org/software/coreutils/>
General help using GNU software: <http://www.gnu.org/gethelp/>
For complete documentation, run: info coreutils 'timeout invocation'
Run Code Online (Sandbox Code Playgroud)

最后,这比编写自己的超时函数要容易得多,shell 往往没有内置超时函数。


Kyl*_*nes 7

如果脚本运行时间过长,则从脚本中启动看门狗进程以终止其父进程。例子:

# watchdog process
mainpid=$$
(sleep 5; kill $mainpid) &
watchdogpid=$!

# rest of script
while :
do
   ...stuff...
done
kill $watchdogpid
Run Code Online (Sandbox Code Playgroud)

该脚本将在五秒后被看门狗终止。

  • 但是每次都必须等待超时。在您的示例中,即使脚本更短,您的脚本也将始终运行 5 秒。您还应该存储看门狗的 PID 并在最后将其杀死。 (6认同)