如何通过 ssh 发出长任务完成时的警报?

如何通过 ssh 发出长任务完成时的警报?

我的桌面是Ubuntu,它有一个方便的程序notify-send,它会在桌面上弹出一个警报。它还内置了以下方便的别名:

$ type alert
alert is aliased to `notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e 's/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//')"'

这意味着您可以运行very-long-running-command; alert,让终端在后台运行,并在任务完成时收到通知。

当您通过 ssh 连接到 CentOS 服务器时,事情会有点棘手。这是一种方法:

localhost$ ssh [email protected]; alert
example.net$ very-long-running-command; exit

这在某种程度上是有效的,但在每个命令后退出通常不是我想要做的。

我的电脑没有扬声器。它可以发出蜂鸣声。

答案1

我能想到的最简单的事情是使用第二个 SSH 会话来转发命名的 FIFO。我假设你tmp/的主目录中有一个;您可以随意将 FIFO 保留在您喜欢的任何地方。

local$ ssh me@remotehost 'mkfifo ~/tmp/alert_fifo ; while cat ~/tmp/alert_fifo ; do : ; done' | \
    while read icon_name text ; do
        notify_send --urgency=low -i "$icon_name" "$text"
    done &

然后,您可以让它在后台运行,同时打开第二个 SSH 会话来完成您的实际工作:

local$ ssh me@remotehost
remote$ alias remote_alert='echo ... >~/tmp/alert_fifo'
remote$ long_running_command; remote_alert

...其中remote_alert是修改后的alert别名,notify_send --urgency=low -i替换为将内容回显到 FIFO。

这将在远程计算机上使用最少的工具集:仅 ssh 和标准 POSIX 实用程序。然而,对于 FIFO,如果您忘记运行您的读取器(或者您的读取器死机),那么您的写入器将会挂起。因此,如果你碰巧有空socat,你可以让这变得更宽容一些:

local$ ssh me@remotehost 'socat UNIX-RECV:~/tmp/alert_socket -' | \
    while read ...
        ...
    done &

local$ ssh me@remotehost
remote$ alias remote_alert='echo ... | socat - UNIX-SEND:~/tmp/alert_socket'

答案2

您可以安装终端仿真器终结器。然后右键单击您的终端并选择“监视活动”或“监视静默”。一旦终端中产生输出或一段时间内没有产生输出,这将分别通知您。如果您的命令不产生输出,您可以; echo "{!1} Done!"在命令末尾附加类似的内容。我构建了一个终止符扩展,每次输出中出现特定关键字时都会通知我。虽然我把密码弄丢了。如果您基于现有扩展构建并且精通 Python,则编程相当简单。额外的好处是,即使您通过 ssh 连接链进行隧道传输,它的工作原理也是一样的。

答案3

这是部分答案。看D-Bus认证和授权对于我坚持的要点。

notify-send发送消息过来D总线。现代桌面环境为每个会话启动一条 D-Bus 总线,并安排会话中的程序找到正确的总线,通常通过设置环境变量来实现DBUS_SESSION_BUS_ADDRESS。 D-Bus 支持多种连接到集中和调度消息的守护进程的方式,包括抽象套接字、unix 套接字和 TCP。

OpenSSH ≥6.7 可以转发 Unix 套接字,但正如我所写,很少有系统运行如此最新的版本。

你可以运行一个监听 TCP 的 D-Bus 守护进程(您可以让它监听多个地址,例如 TCP 和 Unix 套接字)。如果dbus-daemon会话启动脚本以您无法影响的方式启动,则可能很难安排。

您可以使用以下工具通过 TCP 转发 D-Bus 抽象套接字或命名 Unix 套接字网猫或者索卡特。这是一个在 TCP 端口 8004 上设置转发的概念验证脚本。

#!/bin/sh
case $DBUS_SESSION_BUS_ADDRESS in
  '') echo 1>&2 "No local D-Bus instance";;
  unix:abstract=*,guid=*)
    guid=${DBUS_SESSION_BUS_ADDRESS##*[:,]guid=}
    guid=${guid%%,*}
    socket=${DBUS_SESSION_BUS_ADDRESS##*[:,]abstract=}
    socket=ABSTRACT-CONNECT:${socket%%,*}
    ;;
  unix:path=*,guid=*)
    guid=${DBUS_SESSION_BUS_ADDRESS##*[:,]guid=}
    guid=${guid%%,*}
    socket=${DBUS_SESSION_BUS_ADDRESS##*[:,]path=}
    socket=UNIX-CONNECT:${socket%%,*}
    ;;
  *) echo 1>&2 "Unsupported DBUS_SESSION_BUS_ADDRESS";;
esac
socat "TCP-LISTEN:8004,reuseaddr,fork,range=127.0.0.1/32" "$socket"

您现在可以通过 SSH 转发此 TCP 连接。

ssh -R 8004:localhost:8004 [email protected]
[email protected]$ export DBUS_SESSION_BUS_ADDRESS=tcp:host=127.0.0.1,port=8004

您还需要做一件事:将授权 cookie 复制到远程计算机。

rsync -a .dbus-keyrings/org_freedesktop_general [email protected]:.dbus-keyrings/org_freedesktop_general

请注意,与 X11 cookie 不同,D-Bus cookie 可以在服务器的生命周期内更改。事实上,在我的实验中,它似乎以不规则的间隔发生变化,有时只在几分钟后发生变化。

据我所知,只有最新版本的 Gnome 库才会读取 cookie 文件。notify-send可以在带有 Gnome 3.14 的 FreeBSD 10.1 上阅读它,但不能在带有 Gnome 3.4 的 Debian wheezy 上阅读。

相关内容