问题描述
每当一个运行时间超过15秒的命令在交互式shell中完成时,我想要一个桌面通知。
换句话说,我希望所有命令都包含在这样的东西中
start=$(date +%s);
ORIGINAL_COMMAND;
[ $(($(date +%s) - start)) -le 15 ] || notify-send "Long running command finished"
什么是在bash中实现这一目标的最佳方法?
最佳解决方案
您需要https://launchpad.net/undistract-me(可以从带有sudo apt-get install undistract-me
的Ubuntu存档中安装),它可以满足您的要求,包括自动工作(即,无需记住为潜在的long-running命令添加额外内容)。
次佳解决方案
据我所知,你想要一个wrapper。并且您希望通过它使用命令,以便在命令的运行时间超过15秒时为您提供所需的通知。所以这就是它。
wrapper(){
start=$(date +%s)
"$@"
[ $(($(date +%s) - start)) -le 15 ] || notify-send "Notification" "Long\
running command \"$(echo $@)\" took $(($(date +%s) - start)) seconds to finish"
}
在~/.bashrc
中复制此功能,并将源~/.bashrc
复制为,
. ~/.bashrc
使用率
wrapper <your_command>
如果超过15秒,您将获得描述命令及其执行时间的desktop-notification。
例
wrapper sudo apt-get update
第三种解决方案
在~/.bashrc
中,别名为alert
,定义如下:
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
可用于通知命令执行完成。
用法:
$ the_command; alert
例如
$ sudo apt-get update; alert
您可以根据自己的需要和愿望自定义别名。
第四种方案
除了像souravc建议的包装外,在bash中没有任何好的方法可以做到这一点。您可以使用DEBUG陷阱和PROMPT_COMMAND来破解它。每当运行命令时都会触发DEBUG陷阱,并且在写入提示之前运行PROMPT_COMMAND。
所以~/.bashrc
的东西就像这样
trap '_start=$SECONDS' DEBUG
PROMPT_COMMAND='(if (( SECONDS - _start > 15 )); then notify-send "Long running command ended"; fi)'
这是一个黑客,所以如果你遇到奇怪的side-effects,不要感到惊讶。
第五种方案
编辑
长话短说:在.inputrc
中创建自动完成快捷方式,并在.bashrc
中运行。像往常一样运行命令,键入,但不是ENTER
,而是按.inputrc
中指定的快捷方式
在这个问题上放置赏金的人说:
“All of the existing answers require typing an additional command after the command. I want an answer that does this automatically.”
在研究这个问题的解决方案时,我偶然发现了来自stackexchange的this问题,它允许将Ctrl
J
绑定到一系列命令:Ctrl
a
(移至行首),将”mesure”字符串放在您输入的命令前面,Ctrl
m
(执行)
因此,你获得了auto-completion的功能和单独的ENTER
命令来测量时间,同时坚持我发布的第二个功能的原始目的。
截至目前,这是我的~/.inputrc
文件的内容:
"\C-j": "\C-a measure \C-m"
这里是.bashrc
的内容(注意,我没有永远使用bash – 我使用mksh作为我的shell,因此这就是你在原帖中看到的。功能仍然是相同的)
PS1=' serg@ubuntu [$(pwd)]
================================
$ '
function measure ()
{
/usr/bin/time --output="/home/xieerqi/.timefile" -f "%e" $@
if [ $( cat ~/.timefile| cut -d'.' -f1 ) -gt 15 ]; then
notify-send "Hi , $@ is done !"
fi
}
原帖
这是我的想法 – 在.bashrc
中使用一个函数。基本原理 – 使用/usr/bin/time
来测量命令完成所需的时间,如果超过15秒,则发送通知。
function measure ()
{
if [ $( /usr/bin/time -f "%e" $@ 2>&1 >/dev/null ) -gt 15 ]; then
notify-send "Hi , $@ is done !"
fi
}
这里我将输出重定向到/dev/null
但是要查看输出,也可以重定向到文件。
一个更好的方法,恕我直言,是将时间输出发送到您的主文件夹中的某个文件(这样您就不会使用时间文件污染您的系统,并且始终知道在哪里查看)。这是第二个版本
function measure ()
{
/usr/bin/time --output=~/.timefile -f "%e" $@
if [ $( cat ~/.timefile | cut -d'.' -f1 ) -gt 15 ]; then
notify-send "Hi , $@ is done !"
fi
}
这是第一版和第二版的截图,按顺序排列
第一个版本,没有输出
第二个版本,带输出
第六种方案
我最近建立了一个用于此目的的工具。它既可以作为包装器运行,也可以通过shell集成自动运行。在这里查看:http://ntfy.rtfd.io
要安装它:
sudo pip install ntfy
要将它用作包装器:
ntfy done sleep 3
要自动收到通知,请将其添加到.bashrc
或.zshrc
:
eval "$(ntfy shell-integration)"