我的桌面是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 上阅读。