【问题标题】:Taking action after timeout during the command running命令运行超时后的动作
【发布时间】:2015-07-18 16:58:24
【问题描述】:

这是我用于在后台运行命令并计算指定时间段后执行操作所需时间的脚本。如果我在计划之前终止主脚本,还有一些陷阱会终止在后台启动的长时间运行的命令。

#!/bin/bash
# DESCRIPTION:
# Run long running command in background for number of seconds
# specified in $TIME_TO_RUN. After this period the function
# 'func_action' will be called

func_trap () {
  # FOLLOWING LINE ADDED ACORDING TO Barmar SUGGESTION:
  # http://stackoverflow.com/questions/30112607/taking-action-after-timeout-during-the-command-running
  for pid in $(jobs -p); do ps -p $pid; done

  CHILDREN=$(jobs -p)
  if [ -n "$CHILDREN" ]; then
    echo "Following children will be killed"
    jobs -p
    kill $(jobs -p)
  else
    echo "There are no children running"
  fi
  exit
}

func_action() {
    echo "FUNCTION ACTION CALLED"
}
###################################
trap func_trap INT TERM KILL

LOG_PATH="/tmp/log_file"
TIME_TO_RUN=10
TIME_START=$(date +%s)
TIME_STOP=$(( TIME_START + TIME_TO_RUN ))

# COMMAND RUNNING IN BACKGROUND FOR INFINITE
while true;       do date;    sleep 1; done > "$LOG_PATH" &

# COMMAND RUNNING IN BACKGROUND FOR LONG TIME
# for i in `seq 1 5`; do echo $i; sleep 1; done > "$LOG_PATH" &

BKGRD_CMD_PID=$!

echo "BKGRD_CMD_PID: $BKGRD_CMD_PID"
echo "PID: $BKGRD_CMD_PID IS WRITING TO: $LOG_PATH"
echo "MYPID:         $$"
echo "TIME_START:    $TIME_START"
echo "TIME_STOP:     $TIME_STOP"
echo "jobs -p:       $(jobs -p)"

# TODO: TRY TO USE SLEEP INSTEAD OF LOOP
while true; do
  if [ $(date +%s) -lt $TIME_STOP ]; then
    echo -n "Long running command is still running at time: "
    date +%s
    sleep 1
  else
    kill -s 0 "$BKGRD_CMD_PID" 2>/dev/null && func_action
    kill -s 0 "$BKGRD_CMD_PID" 2>/dev/null && kill "$BKGRD_CMD_PID" && echo "Process with PID: $BKGRD_CMD_PID killed"
    break
  fi
done

当我使用 ctrl+c 终止此脚本时,我收到以下消息:

└──> time_counter.sh
BKGRD_CMD_PID: 7551
PID: 7551 IS WRITING TO: /tmp/log_file
MYPID:         7549
TIME_START:    1431161303
TIME_STOP:     1431161313
jobs -p:       7551
Long running command is still running at time: 1431161303
Long running command is still running at time: 1431161304
Long running command is still running at time: 1431161305
Long running command is still running at time: 1431161306
^C  PID TTY          TIME CMD
 7551 pts/4    00:00:00 time_counter.sh
  PID TTY          TIME CMD
Following children will be killed
7551
7572
7578
7579
/home/wakatana/bin/time_counter.sh: line 16: kill: (7572) - No such process
/home/wakatana/bin/time_counter.sh: line 16: kill: (7578) - No such process
/home/wakatana/bin/time_counter.sh: line 16: kill: (7579) - No such process

总的来说,它按预期工作,我只想澄清三件事:

  1. 为什么我收到关于 PID 7572、7578、7579 的错误?这些 PID 属于哪个进程?
  2. 这种方法可行还是有更好的方法?
  3. 如何将 func_trapfunc_action 移动到脚本末尾而不 bash 抱怨未知命令?

PS:我第一次想到timeout 命令,但似乎它只能在指定时间段后发送终止信号并且不执行任何其他操作。

【问题讨论】:

  • 请参阅stackoverflow.com/questions/13588457/… 了解问题 #3。
  • 尝试将此添加到func_trapfor pid in $(jobs -p); do ps -p $pid; done
  • 嗨,Barmar,在哪里添加这一行在函数的开头或结尾?
  • kill 之前的任何地方——我们想在你试图杀死它之前看看额外的进程是什么。
  • 嗨,Barmar,我已经更新了帖子

标签: bash timeout


【解决方案1】:

我怀疑这是 bash 错误。当陷阱处理程序正在运行时,它似乎认为它从主循环(不断打印“长时间运行命令”的循环)中断的sleep 1 是一项待处理的作业。

您应该使用kill $BKGRD_CMD_PID,而不是kill $(jobs -p)

【讨论】:

  • 是的,这行得通,但是当长时间运行的命令分叉子项时不会有任何问题吗?
  • 为什么? jobs -p 只显示由这个 shell 启动的进程的 PID,而不是它的任何子进程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-13
  • 2020-04-16
  • 1970-01-01
相关资源
最近更新 更多