【问题标题】:Introduce timeout in a bash for-loop在 bash for 循环中引入超时
【发布时间】:2013-09-27 16:39:53
【问题描述】:

我有一个非常适合 bash for 循环的任务。但情况是,一些迭代似乎没有终止。我正在寻找的是一种引入超时的方法,如果 command 的迭代在例如之后没有终止。两个小时它将终止,并继续进行下一次迭代。

粗略的轮廓:

for somecondition; do
   while time-run(command) < 2h do
     continue command
   done
done

【问题讨论】:

标签: bash shell for-loop scripting timeout


【解决方案1】:

如果我正确地理解了您的要求,那么您有一个需要运行的流程,但您想确保它在卡住时继续运行,对吗?我不知道这是否会完全帮助你,但这是我前一段时间写的一些类似的东西(我已经改进了一点,但我目前只能获得一个要点,我会以后用更好的版本更新)。

#!/bin/bash

######################################################
# Program:      logGen.sh
# Date Created: 22 Aug 2012
# Description:  parses logs in real time into daily error files
# Date Updated: N/A
# Developer:    @DarrellFX
######################################################
#Prefix for pid file
pidPrefix="logGen"
#output direcory
outDir="/opt/Redacted/logs/allerrors"
#Simple function to see if running on primary
checkPrime ()
{
  if /sbin/ifconfig eth0:0|/bin/grep -wq inet;then isPrime=1;else isPrime=0;fi
}


#function to kill previous instances of this script
killScript ()
{
  /usr/bin/find /var/run -name "${pidPrefix}.*.pid" |while read pidFile;do
    if [[  "${pidFile}" != "/var/run/${pidPrefix}.${$}.pid" ]];then
      /bin/kill -- -$(/bin/cat ${pidFile})
      /bin/rm ${pidFile}
    fi
  done
}


#Check to see if primary
#If so, kill any previous instance and start log parsing
#If not, just kill leftover running processes


checkPrime
if [[ "${isPrime}" -eq 1 ]];then
  echo "$$" > /var/run/${pidPrefix}.$$.pid
  killScript
  commands && commands && commands #Where the actual command to run goes. 
else
  killScript
  exit 0
fi

然后我将此脚本设置为每小时在 cron 上运行一次。每次运行脚本时,它都会

  • 创建一个以描述包含该脚本实例的 pid 的脚本的变量命名的锁定文件
  • 调用函数killScript:
    • 使用 find 命令查找该脚本版本的所有锁定文件(这允许将多个这些脚本设置为一次在 cron 中运行,用于不同的任务)。对于它找到的每个文件,它都会杀死该锁定文件的进程并删除锁定文件(它会自动检查它是否没有杀死自己)
  • 开始做我需要运行的任何事情,而不是卡住(我省略了它,因为这是我在 python 中重做的可怕的 bash 字符串操作)。

如果这不能让你明白,请告诉我。


一些注意事项:

  • checkPrime 函数做得不好,应该返回一个状态,或者只是退出脚本本身
  • better 方法可以创建锁定文件并确保其安全,但到目前为止这对我有用(著名的遗言)

【讨论】:

  • 使用flock 实用程序来锁定文件,在大多数 Unix 系统上都可用。
【解决方案2】:

一种(乏味的)方法是在后台启动进程,然后启动另一个后台进程,在固定超时后尝试杀死第一个进程。

timeout=7200   # two hours, in seconds
for somecondition; do
    command & command_pid=$!
    ( sleep $timeout & wait; kill $command_pid 2>/dev/null) &  sleep_pid=$!
    wait $command_pid
    kill $sleep_pid 2>/dev/null   # If command completes prior to the timeout

done

wait 命令阻塞直到原始命令完成,无论是自然的还是因为它在 sleep 完成后被杀死。紧跟在sleep 之后的wait 用于防止用户尝试中断进程,因为sleep 会忽略大多数信号,但wait 是可中断的。

【讨论】:

    猜你喜欢
    • 2022-06-13
    • 1970-01-01
    • 2021-11-03
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    • 2022-10-24
    • 1970-01-01
    • 2022-01-07
    相关资源
    最近更新 更多