为bash命令和函数实现超时的优雅解决方案
发布时间:2020-12-15 19:03:30 所属栏目:安全 来源:网络整理
导读:我编写了一个运行命令的函数,它以两个args为第一个命令,以秒为单位的第二个超时: #! /bin/bashfunction run_cmd { cmd="$1"; timeout="$2" grep -qP "^d+$" "$timeout" || timeout=10 stderrfile=$(readlink /proc/$$/fd/2) exec 2- exitfile=/tmp/exit_$(
我编写了一个运行命令的函数,它以两个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因为我在杀死命令时无法避免该消息: test.sh:第3行:32323终止(eval“$cmd”; echo $?> $exitfile) PS:我知道超时和期望,但他们不适用于功能.
也许这适合您的需求.我更改了呼叫签名,以避免使用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会杀死错误的进程. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |