我想检测某个进程何时卡住,但它没有给我任何有关此事的线索。我所知道的是,如果它在给定的超时时间内(比如 30 秒)没有产生任何输出,则意味着它可能被阻止了。
我知道 coreutils 的timeout程序,但它基于完整的程序退出时间,而不是最后一行的输出时间。如果这样的事情有效,我会很高兴:
timeout --stdout --stderr 30s my-program
Run Code Online (Sandbox Code Playgroud)
那么有没有办法做到这一点?我该怎么做?
将其另存为tkill(使其可执行并PATH根据需要进行调整):
#!/bin/bash
_terminate_children() {
trap "exit 143" SIGTERM && kill -- "-$$"
}
trap _terminate_children SIGINT SIGTERM
tout="$1"
shift
eval "$@" | tee >(while :; do
read -t "$tout"
case $? in
0) : ;;
1) break ;;
*) _terminate_children ;;
esac
done)
exit "${PIPESTATUS[0]}"
Run Code Online (Sandbox Code Playgroud)
tkill 30 some_command
Run Code Online (Sandbox Code Playgroud)
第一个参数(30此处)是以秒为单位的超时时间。
tkill期望some_command生成文本(不是二进制)输出。tkillstdout给定命令的探测。stderr像下面的最后一个高级示例一样包含重定向。这些是有效的例子:
tkill 9 foo -option value
tkill 9 "foo -option value" # equivalent to the above
tkill 5 "foo | bar"
tkill 5 'foo | bar'
tkill 5 'foo | bar | baz' # tkill monitors baz
tkill 5 'foo | bar' | baz # baz reads from tkill
tkill 3 "foo; bar"
tkill 6 "foo && bar || baz"
tkill 7 "some_command 2>&1"
Run Code Online (Sandbox Code Playgroud)
在这些引号中使用 Bash 语法。
some_command自己退出,那么它的退出状态将被重用作为tkill;的退出状态。tkill 5 true返回0;tkill 5 false返回1;tkill 5 "true; false"返回1。tkill得到由中断SIGINT或SIGTERM再退出状态会143。eval 使高级示例成为可能。tee允许我们进行分析,stdin同时仍将其副本传递给stdout.read -t 负责应用超时,其退出状态用于确定下一步要做什么。eval使高级示例成为可能,但您需要记住它是通过评估其参数来实现的。示例(有点人为):如果您有一个字面命名的文件|,则将在当前 shell 中tkill 9 ls *展开*,|将显示为 的参数,eval并将被解释为管道运算符。在这种情况下tkill 9 'ls *'更好(但请注意,它不会在当前 shell 中展开任何内容)。它类似于watch(我的意思是例如watch ls *vs watch 'ls *')。tee,它不会直接写入终端。某些命令会根据其标准输出是否为终端来改变其行为。他们可以将其输出着色和/或列化到终端,但不能将其输出到常规文件或管道。例如ls --color=auto并tkill 9 'ls --color=auto'给出不同的输出。| 归档时间: |
|
| 查看次数: |
618 次 |
| 最近记录: |