这是一个远景——我认为这是不可能的,但我想我会问。
我经常运行需要几分钟才能完成的命令,并且在它们运行时我检查我的电子邮件或浏览 Internet。当我记得时,我运行command; finished,finished弹出一个对话框通知我该命令已完成的命令在哪里。但是,我并不总是记得,所以我希望有一些东西可以自动检测命令何时需要超过N几秒钟并finished在过程完成时运行。如果重要的话,我更喜欢使用 zsh 但如果另一个 shell 能够做到这一点,我会切换。
iTerm(OSX 的终端模拟器)有一个类似的功能,当终端空闲或空闲一段时间后产生输出时,它会向您显示通知。如果您知道有任何 Linux 终端模拟器具有此功能,那么它也能正常工作(或更好)。
你能想出什么方法来完成这项工作吗?非常感谢!
您需要一种方法来查找已经运行了一段时间的进程。为此,了解 etime 参数显示自进程启动以来经过的时间(格式为 DD-hh:mm:ss)会很有帮助,其中每个较大的部分都是可选的。所以,你可以做
ps -U sauer -o etime,pid,command
Run Code Online (Sandbox Code Playgroud)
(在 AIX 上,您可以使用ps -U sauer -o "%t,%p,%c")
您可以使用 a-t $( tty)代替-U username来选择当前 tty(也称为当前终端)上的进程。这就是我稍后要做的。另请注意,这样做-o cmd=会抑制列标题,但意味着您需要多个 -o 选项。
因此,您最终会ps -t $(tty) -o etime= -o pid= -o command=显示当前终端上运行的所有进程,显示“经过的挂钟时间”、“进程 ID”和“命令”列,并隐藏列标题。
现在您只需要获取运行时间超过任何秒数的那些。因此,您需要提取第一列并将时间转换为秒。使用 shell 脚本来执行此操作怎么样 (ksh/bash):
ps -t $(tty) -o etime= -o pid= -o command= | while read time pid cmd
do
secs=0
while true
do
part=${time##*:}
secs=$(( secs + ${part#0} ))
[[ "$part" != "$time" ]] || break # only had seconds
time=${time%:$part}
part=${time##*:}
secs=$(( secs + (60 * ${part#0}) ))
[[ "$part" != "$time" ]] || break # only had minutes left
time=${time%:$part}
part=${time##*-}
secs=$(( secs + (60 * 60 * ${part#0}) ))
[[ "$part" != "$time" ]] || break # only had hours left
time=${time%-$part} # all that's left are days-hours
secs=$(( secs + (24 * 60 * 60 * time) ))
break
done
echo "Process '$cmd' (pid '$pid') has been up for '$secs' seconds"
done
Run Code Online (Sandbox Code Playgroud)
有几件事可能需要解释。在${part#0}那里,像“06”秒这样的时间会被转换为“6”,而不是被视为八进制。当然,八进制 06 和十进制 6 是相同的,但八进制 09 无效,shell 有时会抱怨这一点。
另一件事是,${var##*:}计算结果为 $var 与从前面修剪的最大字符串匹配“*:”(一个#是最短匹配,%%/%从末尾进行相同的操作)。如果模式不匹配,则计算结果为$var。因此,我们删除除秒之外的所有内容,将其添加到秒,然后从末尾删除秒。如果我们还有剩余的东西,那就是几分钟。因此,去掉分钟,转换为秒,添加到运行总数中,从末尾删除它。等等。
好吧。从那里开始,现在您只需#!/bin/ksh在顶部放置一个(或 bash,如果必须的话),您就拥有了一个脚本。除此之外,您还需要一种方法来查找运行时间超过 X 秒的 pid。/tmp 中的文件怎么样?让我们用它来代替 echo 命令:
if [[ $secs -gt 120 ]]
then
{ cat /tmp/pids.$$; echo "$pid $cmd"; } 2>/dev/null | sort -u > /tmp/pids.$$.tmp
while read p c
do
if ps -p $p >/dev/null 2>&1
then
# put it back in the list
echo "$p $c" > /tmp/pids.$$
else
echo "Command '$c' exited" | mailx -s "exit report" $USER
fi
done < /tmp/pids.$$.tmp
fi
Run Code Online (Sandbox Code Playgroud)
现在你所要做的就是将整个巨大的东西包裹在一个 while 循环中
while true do # 大 while 循环和 if 语句 sleep 10 done
调用它并在您的 .profile 或 .bash_login 或其他内容中process_monitor.sh粘贴 a 。process_monitor.sh&它会在后台监视该终端中的所有进程,当它发现某个进程运行超过 120 秒时,它会将其添加到要监视的列表中,并在该进程退出时向您发送电子邮件。
我可能会添加一些东西以使其更漂亮,例如捕获 EXIT 信号并在脚本退出时删除临时文件等。但这对您来说是一个练习。我希望这足以让你一路顺利。:)