回答:
コマンドウォールを使用して、すべてのコンソールにメッセージを送信できます。
Xで通知を送信するには、現在のディスプレイで現在のユーザーに通知を送信するnotify-sendがあります。(あなたの質問から、あなたはすでにこれを知っていると思います。)これに基づいて、bashスクリプトを作成できます。基本的に、どのユーザーがどのX-Displaysを使用しているかを調べる必要があります。この情報を取得したら、次のようにnotify-sendを使用できます。
DISPLAY=:0 sudo -u fschmitt notify-send "Message"
fschmittはディスプレイ0のユーザーです。「who」コマンドの出力を解析して、すべてのユーザーとそのディスプレイを見つけることができます。出力は次のようになります
[edinburgh:~]$ who
markmerk3 tty7 2010-09-23 10:59 (:0)
markmerk3 pts/1 2010-09-30 13:30 (:0.0)
fschmitt pts/2 2010-10-08 11:44 (ip-77-25-137-234.web.vodafone.de)
markmerk3 pts/0 2010-09-29 18:51 (:0.0)
seamonkey pts/6 2010-09-27 15:50 (:1.0)
markmerk3 pts/5 2010-09-27 14:04 (:0.0)
seamonkey tty8 2010-09-27 15:49 (:1)
markmerk3 pts/13 2010-09-28 17:23 (:0.0)
markmerk3 pts/3 2010-10-05 10:40 (:0.0)
Xセッションを実行している2人のユーザー、ディスプレイ0のmarkmerk3とディスプレイ1のseamonkeyがいることがわかります。 -9。] *)コンソールログインを取り除き、括弧内の文字列から表示IDを抽出します。
who
は、誰がログインしていて、どのXにそのログインが表示されているかを示します。多少フィルタリングする必要があるかもしれません。
who | awk '/\(:[0-9]+\)/ {gsub("[:|(|)]","");print "DISPLAY=:"$5 " sudo -u " $1 " notify-send \"Message\""}' | bash
。また、unix.stackexchange.com / questions / 1596
このスレッドは少し古いですが、申し訳ありませんが、このトピックに役立つものを追加できることを願っています。(また、Josef Kufnerは素敵なスクリプトを作成しましたが、私の好みには少し長すぎました。PHPを使用しています)
元の質問で説明されているツールも必要でした(すべてのアクティブなXユーザーにメッセージを送信するため)。そして、ここでの回答に基づいて、アクティブなXユーザー(「who」を使用)を検索し、すべてのアクティブなユーザーに対してnotify-sendを実行するこの小さなbash専用スクリプトを作成しました。
そして最高:私のスクリプトを「notify-send」とまったく同じように、すべてのパラメーターとともに使用できます!;-)
通知送信:
#!/bin/bash
PATH=/usr/bin:/bin
XUSERS=($(who|grep -E "\(:[0-9](\.[0-9])*\)"|awk '{print $1$5}'|sort -u))
for XUSER in $XUSERS; do
NAME=(${XUSER/(/ })
DISPLAY=${NAME[1]/)/}
DBUS_ADDRESS=unix:path=/run/user/$(id -u ${NAME[0]})/bus
sudo -u ${NAME[0]} DISPLAY=${DISPLAY} \
DBUS_SESSION_BUS_ADDRESS=${DBUS_ADDRESS} \
PATH=${PATH} \
notify-send "$@"
done
上記のコードを「notify-send-all」という名前のファイルにコピーし、実行可能にし、(必要に応じて)/ usr / local / binまたは/ usr / binにコピーします。次に、たとえば次のようなコンソールセッションでrootとして実行します。
notify-send-all -t 10000 "Warning" "The hovercraft is full of eels!"
数ヶ月間、別のマシンで使用していますが、今のところ問題はありませんでした。MATEおよびCinnamonデスクトップでテストしました。また、cronおよびanacron内で正常に実行されます。
このスクリプトはArchLinux向けに作成しましたので、別のLinuxディストリビューションやデスクトップで問題が発生している場合は教えてください。
|egrep
?egrepはコマンドですか?
awk '{print $1$5}'
を使用する方が適切です。これによりawk '{print $1$NF}'
、日付がスペースでフォーマットされているロケール(たとえばJun 3
、2017-06-03
)で壊れないようになります。また、すべてのユーザーではなく特定のユーザーに通知するバージョンもあります:gist.github.com/shvchk/ba2f0da49bf2f571d6bf606d96f289d7
grep -E
して追加/bin
した後、Ubuntu上で見事に動作します(編集を参照)。あなたがオブジェクトの場合は元に戻す気軽
システム全体の通知にもこれが必要でした。これが私の解決策です。/ procをスキャンしてすべてのセッションバスを見つけ、各バスでnotify-sendを実行します(バスごとに1回)。すべての引数は変更されずに実際の通知送信に渡されます。
#!/bin/bash
/bin/grep -sozZe '^DBUS_SESSION_BUS_ADDRESS=[a-zA-Z0-9:=,/-]*$' /proc/*/environ \
| /usr/bin/php -r '
$busses = array();
array_shift($argv);
while($ln = fgets(STDIN)) {
list($f, $env) = explode("\0", $ln, 2);
if (file_exists($f)) {
$user = fileowner($f);
$busses[$user][trim($env)] = true;
}
}
foreach ($busses as $user => $user_busses) {
foreach ($user_busses as $env => $true) {
if (pcntl_fork()) {
posix_seteuid($user);
$env_array = array("DBUS_SESSION_BUS_ADDRESS" => preg_replace("/^DBUS_SESSION_BUS_ADDRESS=/", "", $env));
pcntl_exec("/usr/bin/notify-send", $argv, $env_array);
}
}
}
' -- "$@"
Ubuntu 16.04では、crontabからrootとして実行されているスクリプトからの通知が必要でした。環境変数を設定した後sudo -u $user
、何らかの理由で動作しませんでしたsh -c "..." $user
が、動作します。
そこで、この関数を使用します。
notify_all() {
local title=$1
local msg=$2
who | awk '{print $1, $NF}' | tr -d "()" |
while read u d; do
id=$(id -u $u)
. /run/user/$id/dbus-session
export DBUS_SESSION_BUS_ADDRESS
export DISPLAY=$d
su $u -c "/usr/bin/notify-send '$title' '$msg'"
done
}
DBUS_SESSION_BUS_ADDRESS変数を見つける方法は、おそらくディストリビューションに依存します。Ubuntu 16.04では、にありますが/run/user/$UID/dbus-session
、これは単純に入手できます。id -u
が返すユーザー名からUIDを取得するために上記の関数で使用されwho
ます。
Andyのスクリプトの更新は次のとおりですDBUS_SESSION_BUS_ADDRESS
。Centos7では動作を決定する方法が機能しません。また、who
何らかの理由でコマンドが一部のセッションをリストしなかったため、ps aux
代わりに出力を解析します。このスクリプトは、ユーザーがX2GO(nxagent
)を使用してログインしていることを前提としていますが、他のケースに合わせて簡単に調整できるはずです。
#!/bin/bash
PATH=/usr/bin:/bin
NOTIFY_ARGS='-u critical "Shutdown notice" "THE SYSTEM IS GOING DOWN TODAY AT 23:00.\nWe recommend you to save your work in time\!" -i /usr/share/icons/Adwaita/32x32/devices/computer.png -t 28800000'
function extract_displays {
local processes=$1
processes=$(printf '%s\n' "$processes" | grep -P "nxagent.+:\d+")
ids=$(printf '%s\n' "$processes" | grep -oP "\W\K:(\d)+")
echo $ids
}
function find_dbus_address {
local name=$1
PID=$(pgrep 'mate-session' -u $name)
if [ -z "$PID" ]; then
PID=$(pgrep 'gnome-session' -u $name)
fi
if [ -z "$PID" ]; then
PID=$(pgrep 'xfce4-session' -u $name)
fi
exp=$(cat /proc/$PID/environ | grep -z "^DBUS_SESSION_BUS_ADDRESS=")
echo $exp
}
PROCESSES=$(ps aux)
DISPLAY_IDS=$(extract_displays "$PROCESSES")
echo "Found the following DISPLAYS: $DISPLAY_IDS"
for DISPLAY in $DISPLAY_IDS; do
NAME=$(printf '%s\n' "$PROCESSES" | grep -P "nxagent.+$DISPLAY" | cut -f1 -d ' ')
DBUS_ADDRESS=$(find_dbus_address $NAME)
echo "Sending message to NAME=$NAME DISPLAY=$DISPLAY DBUS_ADDRESS=$DBUS_ADDRESS"
echo "NOTIFY_ARGS=$NOTIFY_ARGS"
eval sudo -u ${NAME} DISPLAY=${DISPLAY} ${DBUS_ADDRESS} PATH=${PATH} notify-send $NOTIFY_ARGS
done