ksh 中的“idql”命令超时

ksh 中的“idql”命令超时

下面是我的代码片段。

idql -n $REPOSITORY_NAME.$cs -Udmadmin -P"" -R$DM_SCRIPTS/test.api > /dev/null 2>&1
    if [ $? != 0 ]; then
      echo "   \c"
      echo "ERROR: Cannot connect to: $REPOSITORY_NAME.$cs on $HOST"
    else
      echo "   Successfully connected to: $REPOSITORY_NAME.$cs"
    fi

这是我们用于监控服务的主要逻辑。但我们经常看到我们的服务被挂起,因此上面代码片段的第一行被挂起,之后就不再继续了。因此,我们无法捕获这种“服务挂起”的情况。

最重要的是,我们必须保留对现有条件的检查(在 if-else 条件语句中指定),此外,我们还必须检查“挂起”状态。如果命令idql耗时超过 5 秒,我们可以假设它已挂起。

答案1

我想你想要timeout命令,它是您系统的一部分coreutils并且应该在您的系统上可用

要在 5 秒后终止该命令,请更改为:

timeout 5 iqdl -n $REPOSITORY_NAME.$cs ...

如果你没有coreutils,您可以从这里下载、构建并安装它:http://www.gnu.org/software/coreutils/

也可以看看:https://stackoverflow.com/questions/687948/timeout-a-command-in-bash-without-unnecessary-delay

答案2

我能够修改解决方案http://h30499.www3.hp.com/t5/System-Administration/Capturing-hung-command-in-a-script/td-p/5662103以满足我的要求。

我测试过,这对我来说是完美的。我感谢你的所有帮助。

#!/bin/ksh

WAITTIME=5

# run the idql command in the background, discarding any output
idql -n $REPOSITORY_NAME -Udmadmin -P"" -R"$DM_SCRIPTS/test.api" >/dev/null 2>&1 &
IDQL_PID=$!

# set up a timeout that will kill the idql command when 
# $WAITTIME seconds has passed, unless it has completed before that.
(sleep $WAITTIME; kill $IDQL_PID 2>/dev/null) &
TIMEOUT_PID=$!

# wait for the idql command to either complete or get killed; read its return status
wait $IDQL_PID
RESULT=$?

# if the timeout is still running, stop it (ignore any errors)
kill $TIMEOUT_PID 2>/dev/null

# read the return status of the timeout process (we don't need it 
# but running the wait function prevents it from remaining as a 
# zombie process)
wait $TIMEOUT_PID

if [ $RESULT -eq 1 ];then
    echo "something is wrong with $REPOSITORY_NAME, It seems to be down. Result - $RESULT"
elif [ $RESULT -eq 143 ];then
    echo "Attention!!! ***$REPOSITORY_NAME seems to be HUNG*** Result - $RESULT"
else
    echo "$REPOSITORY_NAME seems to be OK. Result - $RESULT"
fi

答案3

如果idql在挂起时在循环中使用 CPU 时间,则可以对其总 CPU 时间进行限制:

( ulimit -t 5;
  idql -n $REPOSITORY_NAME.$cs -Udmadmin -P"" -R$DM_SCRIPTS/test.api > /dev/null 2>&1 )

如果idql由于其他原因(例如死锁)而阻塞,则必须按照挂钟时间进行超时。这是一个解决方案,由于史蒂芬·希门尼斯,稍作修改以获取命令的退出状态idql

ret=$(sh -ic '{ { idql -n "$REPOSITORY_NAME.$cs" -Udmadmin -P"" -R"$DM_SCRIPTS/test.api" > /dev/null 2>&1;
                  echo $? >&3;
                  kill 0; } |
                { sleep 5; kill 0; } }' </dev/null 3>&1 2>/dev/null)
if [ -z "$ret" ]; then
  echo "timed out"
elif [ "$ret" -ne 0 ]; then
  echo "error $ret"
else
  echo "ok"
fi

解释:

  • 启动交互式 shell ( sh -i)。由于这个 shell 是交互式的,所以它有自己的进程组
  • 子 shell 运行通过管道连接在一起的两个命令。这允许两个命令在同一进程组内并行执行。
  • 这两个命令都以 结尾kill 0,这会杀死进程组内的所有命令。无论哪个命令先结束(idqlsleep),都会杀死另一个命令。
  • idql打印文件描述符 3的返回状态,这样它就不会通过管道。文件描述符 3 被重定向到外壳中的文件描述符 1,以便命令替换捕获该 fd 上的输出。
  • 重定向交互式 shell 的标准错误,以免/dev/null从内 shell 中显示任何“已终止”消息。如果您想查看 的错误输出idql,则需要重定向它(idql 2>&4而不是idql 2>/dev/null, 并在of4>&2之前添加)。2>/dev/nullsh -i
  • 重定向交互式 shell 的标准输入,以便在您按+/dev/null时它不会最终从终端读取命令。CtrlC

相关内容