我编写了一个运行命令的函数,它以两个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
Run Code Online (Sandbox Code Playgroud)
该功能工作正常,但我不确定它是一个优雅的解决方案,我想知道以下的替代品
(eval "$cmd";echo $? > $exitfile)exec 2<&- and exec 2>$stderrfile我正在关闭STDERR因为我在杀死命令时无法避免该消息:
test.sh: line 3: 32323 Terminated ( eval "$cmd"; echo $? > $exitfile )
PS:我知道的timeout和expect,但他们不会为职能的工作.
也许这适合您的需求.我更改了呼叫签名,以避免使用eval.
# 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
)
}
Run Code Online (Sandbox Code Playgroud)
示例,显示退出状态:
$ 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 Code Online (Sandbox Code Playgroud)
如图所示,退出状态run_with_timeout将是执行命令的退出状态,除非它被超时杀死,在这种情况下它将是143(128 + 15).
注意:如果您设置了一个大的超时和/或运行了一个forkbomb,您可能会以足够快的速度回收pid,以致kill-child杀死了错误的进程.
| 归档时间: |
|
| 查看次数: |
3667 次 |
| 最近记录: |