SSHで長いタスクが完了したら警告を送信する方法は?

SSHで長いタスクが完了したら警告を送信する方法は?

notify-send私のデスクトップはUbuntuで、デスクトップに警告を表示する便利なプログラムがあります。また、以下の便利なエイリアスが組み込まれています。

$ 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サーバーに接続すると、状況が少し難しくなります。 1つの方法は次のとおりです。

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

これはある程度動作しますが、各コマンドの後で終了することは通常私が望むものではありません。

マイコンピュータにスピーカーはありません。ビープ音が鳴ります。

答え1

私が考える最も簡単な方法は、2番目のSSHセッションを使用して名前付きFIFOを渡すことです。私はtmp/あなたのホームディレクトリに1つがあると仮定します。 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 &

その後、実際のタスクを実行するために、2番目の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 -iFIFOに内容を反映して置き換えられます。

これは、リモートシステムで最小限のツールセット(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バスバスを起動し、通常環境変数を設定し、セッション内のプログラムが正しいバスを見つけるように調整します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

もう1つ行うべきことは、認証Cookieをリモートコンピュータにコピーすることです。

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

X11 Cookieとは異なり、D-Bus Cookieはサーバーの存続期間中に変更されることがあります。実際、私の実験では、不規則な間隔で、時にはわずか数分後にのみ変化するように見えました。

私が知っている限り、最新バージョンのGnomeライブラリだけがCookieファイルを読みます。notify-sendGnome 3.14を含むFreeBSD 10.1では読み取ることができますが、Gnome 3.4を含むDebian wheezyでは読み取れません。

関連情報