USBプラグ/アンプラグ通知(ここでは 関連する質問 )を実装しています。notify-send "device plugged" "My Device Title"
のようなものを実行する必要があります。問題は、このコマンドを機能させるために、最初にDISPLAY
を次のように設定する必要があることです。
export DISPLAY=":0.0"
次に、このコマンドは適切なユーザーが呼び出す必要があります。たとえば、ユーザーdimon
の場合:
su dimon -c "notify-send 'device plugged' 'My Device Title'"
したがって、すべてのアクティブなXセッションと適切なユーザーのリストを取得し、DISPLAY
の各ユーザーに対してnotify-send
を呼び出す必要があります。
そのためにw
を使用しようとしましたが、Linux Mint 13 MATEでの出力例:
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
dimon tty8 :0 Sun15 3days 1:38m 1.95s x-session-manager
dimon pts/0 :0 Sun15 0.00s 0.20s 0.00s tmux
したがって、ユーザー名とディスプレイの両方があります。私はそれをそのように解析することにしました:
declare -a logged_users=(`w |grep -vP "^(USER| )" |awk '{if (NF==8){print $1" "$3} else {print $1" :0"}}' |sort |uniq`)
現在、配列logged_users
があります。[0]
にはdimon
が含まれ、[1]
には:0
が含まれます。これはすばらしいことですが、残念ながらどこでも機能するわけではありません。たとえば、Ubuntu 12.04でlightdmを使用すると、次のw
出力が得られます。
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
nui tty7 18:22 35:56 1.66s 0.11s gnome-session -
nui pts/0 :0.0 18:55 5.00s 0.20s 0.00s w
gnome-session
にFROM値がない理由はわかりません。さらに悪いことに、xubuntuで:
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
nui tty7 15:50 31:07 52.55s 0.13s /bin/sh /etc/xd
何も表示されません!他のユーザーがログインしている場合、そのユーザーのディスプレイも指定されていません(実際には:1.0
です)
だから、私は別のアプローチを探しています。また、ここにはすべてのアクティブなXセッションのリストがあることも知っています:/tmp/.X11-unix
、これらのリストは次のように取得できます。
cd /tmp/.X11-unix && for x in X*; do echo ":${x#X}"; done
しかし、その後、ユーザーを取得する方法がわかりません。
では、すべてのアクティブなXセッションと適切なユーザーのリストを取得するにはどうすればよいでしょうか。
これはlocal Xサーバーのユーザー向けのソリューションです(リモートまたは仮想Xサーバーを持つローカルXクライアントは無視されます)。
ディスプレイマネージャーのPID(Xorgの親PID)を決定し、その子のPIDを決定し、それらの1つを親として持つすべてのプロセスのユーザーを決定します。
#! /bin/bash
xorg_pid=$(pidof -s /usr/bin/Xorg)
test -n "$xorg_pid" || exit 1
dm_pid=$(ps -eo pid,ppid,args | \
awk -v xorg_pid=$xorg_pid '$1 == xorg_pid {print $2}')
pid_list="$(ps -eo pid,ppid,cmd | \
awk -v dm_pid=$dm_pid '$2 == dm_pid {if (matchnr == 0) '\
'{ printf "%s%d ","$2 == ",$1; matchnr++;} '\
'else printf "%s%d ","|| $2 == ",$1;}')"
ps -eo pid,ppid,user,cmd | awk "$pid_list"'{print $3}'
同じ通知送信問題がありました。
このメソッド(また掲載 ここ )は、_ps e
_が提供する環境情報を使用します。 ps e -u username | sed -rn 's/.* DISPLAY=(:[0-9]*).*/\1/p'
は、すべてのユーザーusernameのプロセスの環境におけるすべてのDISPLAY番号のリストを出力します。
デスクトップにルート所有のウィンドウがある場合、ルートにも同じDISPLAY番号を持ついくつかのプロセスがありますが、それ以外の場合、1つのDISPLAYは1人のユーザーにのみ関連付けられます。 (逆ではありません-現在、2つのttyで2つのXセッションでログインしているため、:0と:1の両方を使用しています。)
このコードは、現在ログインしているすべてのユーザーの現在使用されているすべてのDISPLAY(つまり、すべてのXセッション)を出力します。 (ルートはスキップされます)
Sudo
コマンドのps
に注意してください。他のユーザーのプロセスの環境を表示するには、root権限が必要です。もちろん、スクリプトがrootで実行される場合は不要です。
ユーザー名と表示番号は、一意の値のみを保持するために、連想配列のインデックスとして使用されます。
_#!/bin/bash
declare -A disps usrs
usrs=()
disps=()
for i in $(users);do
[[ $i = root ]] && continue # skip root
usrs[$i]=1
done # unique names
for u in "${!usrs[@]}"; do
for i in $(Sudo ps e -u "$u" | sed -rn 's/.* DISPLAY=(:[0-9]*).*/\1/p');do
disps[$i]=$u
done
done
for d in "${!disps[@]}";do
echo "User: ${disps[$d]}, Display: $d"
#Sudo -u "${disps[$d]}" DISPLAY="$d" notify-send "Title" "Message"
done
_
最後のコメント化された行は、notify-sendを呼び出す方法を示しています。