命令期间超时后采取行动 运行
Taking action after timeout during the command running
这是我在后台用于 运行 命令并计算指定时间段后执行操作所需时间的脚本。如果我比我计划的更早终止主脚本,还有一些陷阱会终止在后台启动的长 运行 命令。
#!/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:
#
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
总的来说它按预期工作我只想澄清三件事:
- 为什么我收到关于 PID 7572、7578、7579 的错误?这些 PID 属于哪个进程?
- 这种方法可行还是有更好的方法?
- 如何将
func_trap
和 func_action
移动到脚本末尾而不 bash 抱怨未知命令?
PS: 我第一次想到 timeout
命令,但似乎它只能在指定时间段后发送终止信号并且不执行任何其他操作。
我怀疑这是一个 bash
错误。虽然陷阱处理程序是 运行,但它似乎认为它从主循环(继续打印 "Long running command" 的那个)中断的 sleep 1
是一个待处理的作业。
而不是kill $(jobs -p)
,你应该kill $BKGRD_CMD_PID
。
这是我在后台用于 运行 命令并计算指定时间段后执行操作所需时间的脚本。如果我比我计划的更早终止主脚本,还有一些陷阱会终止在后台启动的长 运行 命令。
#!/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:
#
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
总的来说它按预期工作我只想澄清三件事:
- 为什么我收到关于 PID 7572、7578、7579 的错误?这些 PID 属于哪个进程?
- 这种方法可行还是有更好的方法?
- 如何将
func_trap
和func_action
移动到脚本末尾而不 bash 抱怨未知命令?
PS: 我第一次想到 timeout
命令,但似乎它只能在指定时间段后发送终止信号并且不执行任何其他操作。
我怀疑这是一个 bash
错误。虽然陷阱处理程序是 运行,但它似乎认为它从主循环(继续打印 "Long running command" 的那个)中断的 sleep 1
是一个待处理的作业。
而不是kill $(jobs -p)
,你应该kill $BKGRD_CMD_PID
。