【问题标题】:Set timeout for shell script, to make it exit(0) when time is over为shell脚本设置超时,使其在时间结束时退出(0)
【发布时间】:2016-06-30 07:49:00
【问题描述】:

当我设置 Jenkins 作业并发现有关 shell 脚本超时的问题时。

它是这样工作的:

启动 Jenkins → control.sh 启动 → test1.shcontrol.sh 启动

control.sh的部分代码如下:

#!/bin/sh
source func.sh     

export TIMEOUT=30
# set timeout as 30s for test1.sh

( ( sleep $TIMEOUT && function_Timeout ) & ./test1.sh ) 
# this line of code is in a = loop actually
# it will launch test2.sh, test3.sh... one by one
# later, I want to set 30s time out for each of them.

function_Timeout() {
  if [ ! -f test1_result_file]: then
    killall test1.sh
    # the test1_result_file will not 
    # be created if test1.sh is not finished executing.
  fi
}

func.sh 部分如下

#!/bin/sh
function trap_fun() {
  TRAP_CODE=$?
  { if [ $TRAP_CODE -ne 0 ]; then
      echo "test aborted"
    else
      echo "test completed"
  } 2>/dev/null

trap "trap_fun" EXIT

Jenkins作业启动control.sh后,时间到了整个control.sh会被终止,到达killall test1.sh的那一行,Jenkins作业停止并失败。

我猜是因为test1.sh被杀了,退出码不是0,所以才会出现这个问题。

所以我的问题是,有没有办法终止或结束子脚本(由主脚本启动,如我的情况下的control.sh)退出代码0

7 月 1 日更新:

到目前为止感谢您的回答,我尝试了@Leon的建议,但我发现超时杀死动作发送的代码124仍然被陷阱代码捕获 - 陷阱“trap_fun” EXIT,在func.sh中。

我添加了更多细节。我做了很多谷歌工作,但仍然没有找到解决这个问题的正确方法:(

感谢您的帮助!

【问题讨论】:

  • @123 感谢您的回复!你能指定如何在 test1.sh 中捕获它吗?抱歉,我是 Shell 新手
  • - 你为什么使用子shell? - 什么是f_Timeout?我只看到您的示例代码中定义了function_Timeout
  • @Fara 对不起我的错字:(

标签: linux bash shell jenkins


【解决方案1】:

使用来自 coreutilstimeout 实用程序:

#!/bin/sh

timeout 30 ./test1.sh
status=$?
if [ $status -eq 124 ] #timed out
then
    exit 0
fi
exit $status

请注意,这与您的超时处理版本略有不同,如果其中任何一个超时,所有正在运行的test1.sh 实例都将被终止。

【讨论】:

  • 谢谢莱昂!我尝试了你的方法,但我刚刚发现有陷阱“trap_func”退出代码,124代码仍然被陷阱“trap_func”退出:(,詹金斯作业失败并退出。
  • 如果 test1.sh 在超时之前也返回退出代码 124 会发生什么?那么逻辑将失败。我正面临这个问题。
【解决方案2】:

我终于解决了这个问题,我在每个testX.sh中添加了下面的代码。

trap 'exit 0' SIGTERM SIGHUP

就是让test1.sh收到killall信号后正常退出。

感谢大家的帮助!

【讨论】: