bash命令结束时发出声音

bash命令结束时发出声音,bash,shell,command-line,notifications,Bash,Shell,Command Line,Notifications,在bash中启动长命令时,需要在命令完成时发出信号 如何在.bashrc中生成所有长命令 我还喜欢听声音 在google中搜索而不显示结果。您可以构建一个包装器来完成此操作: #!/bin/bash # Play sound if the command takes longer than this many seconds. alert_sec=60 # Your system may have a different media player. # Use "man -k player" t

在bash中启动长命令时,需要在命令完成时发出信号

如何在.bashrc中生成所有长命令

我还喜欢听声音


在google中搜索而不显示结果。

您可以构建一个包装器来完成此操作:

#!/bin/bash
# Play sound if the command takes longer than this many seconds.
alert_sec=60
# Your system may have a different media player.
# Use "man -k player" to see what's installed.
play=/usr/bin/play
# Use any sound file here. Look under /usr/share/sounds.
sound=/usr/share/sounds/gnome/default/alerts/bark.ogg
# Start time, in seconds since the epoch.
start=$(date +%s)
# Send the remainder of the command line to bash.
"$@"
end=$(date +%s)
# Calculate how long the command ran.
run_sec=$((end - start))
# Decide whether to alert.
if ((run_sec > alert_sec)); then
    $play $sound >&/dev/null
fi
让我们调用脚本
notify
。将它复制到
$PATH
中的一个目录中,这样bash就会找到它,并使用
chmod+x notify使其可执行。现在,您可以执行如下命令:

notify ls -l /var/log  # Shorter than 60 seconds, so no alarm.
notify sleep 70        # Longer than 60 seconds, so alarm.
trap '_T=${_T:-$SECONDS}' DEBUG
PROMPT_COMMAND='
    ((SECONDS - _T > 10)) &&
        { play ~/done.wav &disown;}&>/dev/null;
    unset _T
'

如果您还想要视觉警报,请查看。

这里有一个不完美的解决方案,您可以将其放入bash配置文件中:

_PREVT=$(date +%s)
PROMPT_COMMAND='[[ -n $_PREVT ]] && ((_PREVT<$(date +%s)-60)) && mplayer /usr/share/sounds/pop.wav;_PREVT=$(date +%s)'
\u PREVT=$(日期+%s)

PROMPT_COMMAND='[-n$_PREVT]]&(_PREVT我也有同样的问题,多亏@rici的回答,我才想出了一个有效的解决方案。如果需要,您可以将PROMPT_命令合并到一行中,或者像这样保留它:

notify ls -l /var/log  # Shorter than 60 seconds, so no alarm.
notify sleep 70        # Longer than 60 seconds, so alarm.
trap '_T=${_T:-$SECONDS}' DEBUG
PROMPT_COMMAND='
    ((SECONDS - _T > 10)) &&
        { play ~/done.wav &disown;}&>/dev/null;
    unset _T
'
每当命令行需要10秒以上才能完成时,这种设置组合将播放
~/done.wav
。它不会仅通过让终端处于空闲状态来播放声音

在OS X上,播放声音的命令是
afplay
,在
/System/Library/sounds

但是上面的版本无法区分长时间运行的批处理命令(我们需要声音)和交互式命令(例如您选择的终端编辑器、手册页、
| less
)等)

以下是一个版本,通过检查带有常见交互程序或管道列表的regexp的最后一条命令行,99%的情况下都能说明问题:

trap '_T=${_T:-$SECONDS}' DEBUG
PROMPT_COMMAND='
    if ((SECONDS - _T > 10)); then 
        l=$(history 1);
        [[ ! ${l:7} =~ (^vim|^man|^ssh|less$) ]] && 
        { play ~/done.wav &disown;}&>/dev/null;
    fi;
    unset _T
'
您应该调整regexp以适应口味。同样,如果需要,您可以将PROMPT_命令合并到一行中,我将
放在一行中

这仍然是有效的,因为:

  • shell在评估任何一个钩子时都不会产生任何外部进程(除了在后台启动的明显的声音播放)
  • 调试钩子非常快;我相信它甚至不会在每个命令行中访问超过两次的“magic variable”$SECONDS(这可能会强制系统调用获取当前时间),在第一次调试和提示符_命令中比较值
  • 仅当命令花费的时间超过N秒时,才会执行历史记录检查和regexp

它的工作原理

要了解其工作原理,可以设置以下调试打印:

trap 'echo DEBUG' DEBUG
PROMPT_COMMAND='echo PROMPT_COMMAND'
然后注意他们被呼叫的时间:

PROMPT_COMMAND
$ sleep 2; sleep 2
DEBUG
  (1st sleep takes its time)
DEBUG
  (2nd sleep takes its time)
DEBUG
PROMPT_COMMAND
$ (user waits before pressing enter)
DEBUG
PROMPT_COMMAND
$
有鉴于此,我的上述设置:

  • 每当在
    $prompt\u命令的末尾向用户显示提示时,取消设置
  • 如果未设置_T,这发生在每个命令行的第一个
    DEBUG
    中,就在按enter键之后;然后将其设置为当前时间(使用
    $SECONDS
    ,这比启动外部
    日期
    进程更有效)
  • 在下一个提示下,比较当前时间并在需要时播放声音,在后台启动播放命令并放弃任何输出(包括
    [1]PID
    和其他与工作相关的信息)

非常好的解决方案!但是如何在~/.bashrc中为所有命令添加它呢?只要它在
.bashrc
路径中,就不需要它了。如果你真的想要它,你可以将它声明为一个函数。OP想要一个自动的解决方案,以避免在长时间运行程序之前必须记住键入
notify
事实证明这是可能的,而且在实践中效果很好。请看我的答案。