gpt4 book ai didi

bash - 为 bash 命令和函数实现超时的优雅解决方案

转载 作者:行者123 更新时间:2023-11-29 09:02:47 26 4
gpt4 key购买 nike

我写了一个函数来运行命令,它需要两个参数第一个是命令第二个以秒为单位的超时:

#! /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

该功能工作正常,但我不确定这是一个优雅的解决方案,我想了解以下的替代方案

  1. 我必须将退出状态存储在文件中:(eval "$cmd";echo $? > $exitfile)
  2. 我正在关闭并重新打开 STDERR:exec 2<&- and exec 2>$stderrfile

我正在关闭 STDERR,因为我在终止命令时无法避免该消息:

test.sh: line 3: 32323 Terminated ( eval "$cmd"; echo $? > $exitfile )

PS:我知道timeoutexpect但它们不适用于函数。

最佳答案

也许这符合您的需要。我更改了调用签名以避免使用 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
)
}

示例,显示退出状态:

$ 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 杀死了错误的进程。

关于bash - 为 bash 命令和函数实现超时的优雅解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24412721/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com