这是我当前的 bash,它只是一个循环
while true ; do
python3 /Users/Name/Desktop/pythoncode.py
done
pythoncode.py
如果 2 分钟内没有向终端输出任何内容,我想终止
答案1
和zsh
:
zmodload zsh/system
(
echo $sysparam[pid]
exec python3 /Users/Name/Desktop/pythoncode.py
) | {
read pid
if sysread -o 1 -s 1 -t120; then
cat
else
kill -s PIPE $pid 2> /dev/null
fi
}
使用bash
,您可以执行类似的操作:
(
echo "$BASHPID"
exec python3 /Users/Name/Desktop/pythoncode.py
) | {
read pid
if LC_ALL=C IFS= read -rd '' -n1 -t120 byte; then
if [ -n "$byte" ]; then
printf %s "$byte"
else
printf '\0'
fi
cat
else
kill -s PIPE "$pid" 2> /dev/null
fi
}
这些检查该脚本是否将任何内容写入标准输出,而不是专门写入终端。
如果您还想在命令已写入内容时停止,但停止并且在两分钟内没有输出任何内容,或者换句话说,在 2 分钟不活动后终止命令,那么您可以使用socat
:
socat -T120 'exec:python3 /Users/Name/Desktop/pythoncode.py' -
或者与zsh
:
zmodload zsh/system
(
echo $sysparam[pid]
exec python3 /Users/Name/Desktop/pythoncode.py
) | {
read pid
while
sysread -o 1 -t 120; ret=$?
(( ret == 0 ))
do continue; done
# 5 means EOF
(( ret == 5 )) || kill $pid
}
答案2
使用bash
,您可以使用进程替换和重定向以及while
带超时的循环read
-t
。当while
循环由于超时而退出时(这意味着当 python 脚本没有输出,看起来不活动,持续 2 分钟),子 shell 将不再存在。
while IFS= read -r -t120 x; do
printf "%s\n" "$x"
done < <(python3 script.py)
注意:我假设本示例中是面向行的输出(或者是逐个字符的输出)read
。printf
这种结构与使用管道的区别在于我们这里有一个命令。当该命令退出时,从文件描述符的文件输入结束,子shell中写入该描述符的命令也结束。所以python脚本被杀死了超时后。
当像这样管道时:
python3 script.py | {
while IFS= read -r -t120 x; do
printf "%s\n" "$x"
done
}
我们执行两个命令,如果第二个命令退出(由于超时),第一个命令将继续运行,直到再次尝试写入管道。当发生这种情况时,由于管道损坏,它将终止,不再写入任何内容。所以这里python脚本被杀死了超时后尝试再次写入时。
答案3
如果可接受的精度是~1 秒,您可以用它date +%s
来收集实际时间并检查脚本没有输出的时间(将其收集为 shell 变量):
ELAPSED_T=0 # the time that has passed since last output
LAST_OUT_T=`date +%s` # avoid to stop if the first iteration has empty output
while [ "$ELAPSED_T" -lt 120 ]; do # continue if the last output was printed less than 120 seconds ago
OUT=`python3 /Users/Name/Desktop/pythoncode.py` # run the script and collect the output
echo "$OUT" # print the output on screen
if [ -n "$OUT" ]; then # if the output is not empty, update the last output time
LAST_OUT_T=`date +%s`
else # otherwise, evaluate how much time has passed since last output
NOW_T=`date +%s`
ELAPSED_T=$((NOW_T - LAST_OUT_T))
fi
done
答案4
您可能想查看 GNUtimeout
命令。它将持续时间作为参数,后跟命令。这是一个简单的调用:
timeout 5s ping www.website.com
从它的联机帮助页来看:
TIMEOUT(1) User Commands TIMEOUT(1)
NAME
timeout - run a command with a time limit
SYNOPSIS
timeout [OPTION] DURATION COMMAND [ARG]...
timeout [OPTION]
DESCRIPTION
Start COMMAND, and kill it if still running after DURATION.
...
您还可以指定在超时结束时发送到进程的信号类型(如 HUP、9、SIGTERM 等)。
HTH。