我编写了一个运行命令的函数,它以两个args为第一个命令,以秒为单位的第二个超时:
#! /bin/bash function run_cmd { cmd="$1"; timeout="$2" grep -qP "^\d+$" <<< "$timeout" || timeout=10 stderrfile=$(readlink /proc/$$/fd/2) exec 2<&- exitfile=/tmp/exit_$(date +%s.%N) (eval "$cmd";echo $? > $exitfile) & start=$(date +%s) while true; do pid=$(jobs -l | awk '/Running/{print $2}') if [ -n "$pid" ]; then now=$(date +%s) running=$(($now - $start)) if [ "$running" -ge "$timeout" ];then kill -15 "$pid" exit=1 fi sleep 1 else break fi done test -n "$exit" || exit=$(cat $exitfile) rm $exitfile exec 2>$stderrfile return "$exit" } function sleep5 { sleep 5 echo "I slept 5" return 2 } run_cmd sleep5 "6" run_cmd sleep5 "3" echo "hi" >&2
该功能工作正常但我不确定它是一个优雅的解决方案,我想知道以下的替代品
>我必须将退出状态存储在文件中:( eval“$cmd”; echo $?> $exitfile)
>我正在关闭并重新打开STDERR:exec 2<& - 和exec 2> $stderrfile
我正在关闭STDERR因为我在杀死命令时无法避免该消息:
test.sh:第3行:32323终止(eval“$cmd”; echo $?> $exitfile)
PS:我知道超时和期望,但他们不适用于功能.
也许这适合您的需求.我更改了呼叫签名,以避免使用eval.
原文链接:https://www.f2er.com/bash/387182.html# Usage: run_with_timeout N cmd args... # or: run_with_timeout cmd args... # In the second case,cmd cannot be a number and the timeout will be 10 seconds. run_with_timeout () { local time=10 if [[ $1 =~ ^[0-9]+$]]; then time=$1; shift; fi # Run in a subshell to avoid job control messages ( "$@" & child=$! # Avoid default notification in non-interactive shell for SIGTERM trap -- "" SIGTERM ( sleep $time kill $child 2> /dev/null ) & wait $child ) }
$sleep_and_exit() { sleep ${1:-1}; exit ${2:-0}; } $time run_with_timeout 1 sleep_and_exit 3 0; echo $? real 0m1.007s user 0m0.003s sys 0m0.006s 143 $time run_with_timeout 3 sleep_and_exit 1 0; echo $? real 0m1.007s user 0m0.003s sys 0m0.008s 0 $time run_with_timeout 3 sleep_and_exit 1 7; echo $? real 0m1.006s user 0m0.001s sys 0m0.006s 7
如图所示,run_with_timeout的退出状态将是执行命令的退出状态,除非它被超时杀死,在这种情况下它将是143(128 15).
注意:如果设置了一个大的超时和/或运行了一个forkbomb,你可能会以足够快的速度回收pid,kill-child会杀死错误的进程.