Como obter a lista de todas as sessões X ativas e proprietários delas

4

Estou implementando a notificação de plug and unplug do USB (veja a pergunta relacionada ), e preciso executar algo como notify-send "device plugged" "My Device Title" . O problema é que, para fazer esse comando funcionar, eu deveria primeiro definir DISPLAY , assim:

export DISPLAY=":0.0"

E, em segundo lugar, esse comando deve ser chamado pelo usuário apropriado. Diga, para o usuário dimon :

su dimon -c "notify-send 'device plugged' 'My Device Title'"

Portanto, preciso obter a lista de todas as sessões X ativas e os usuários apropriados e chamar notify-send para cada usuário em seu DISPLAY .

Eu tentei usar w para isso, exemplo de saída no 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

Portanto, temos o nome de usuário e a exibição. Eu decidi analisá-lo assim:

declare -a logged_users=('w |grep -vP "^(USER| )" |awk '{if (NF==8){print $1" "$3} else {print $1" :0"}}' |sort |uniq')

Agora, tenho a matriz logged_users : [0] contém dimon e [1] contém :0 . Isso seria ótimo, mas infelizmente não funciona em todos os lugares. Digamos que no Ubuntu 12.04 com lightdm nós tenhamos este w output:

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

Não há ideia de por que não há valor FROM para gnome-session . E pior ainda, no xubuntu:

USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
nui      tty7                      15:50   31:07  52.55s  0.13s /bin/sh /etc/xd

Nenhuma exibição! Se outro usuário estiver logado, nenhum display é especificado para ele também (mas na verdade é :1.0 )

Então, estou procurando outra abordagem. Eu também sei que temos uma lista de todas as sessões X ativas aqui: /tmp/.X11-unix , e eu posso pegar a lista delas assim:

cd /tmp/.X11-unix && for x in X*; do echo ":${x#X}"; done

Mas não sei como recuperar usuários.

Então, como obter a lista de todas as sessões X ativas e usuários apropriados?

    
por Dmitry Frank 26.02.2014 / 17:04

2 respostas

3

Esta é uma solução para os usuários de servidores X locais (ignorando clientes X locais com servidores X remotos ou virtuais).

Você determina o PID do gerenciador de exibição (que é o PID pai do Xorg), determina os PIDs de seus filhos e determina o usuário de todos os processos que têm um deles como pai:

#! /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}'
    
por 26.02.2014 / 19:27
2

Eu tive o mesmo problema de enviar notificações.

Este método (também publicado aqui ) usa as informações de ambiente que ps e fornece. ps e -u username | sed -rn 's/.* DISPLAY=(:[0-9]*).*//p' mostra uma lista de todos os números do DISPLAY nos ambientes de todos os processos do usuário username .

Se houver uma janela de propriedade raiz em sua área de trabalho, o root também terá alguns processos com o mesmo número de DISPLAY, mas, de outro modo, um DISPLAY só deverá ser associado a um usuário. (Não o contrário - agora estou logado em dois minutos com duas sessões X, então estou usando os dois: 0 e: 1.)

Este código irá mostrar todos os DISPLAYs usados atualmente (daí todas as sessões X) de todos os usuários atualmente logados. (root é ignorado)

Observe o sudo no comando ps : permissões de root são necessárias para visualizar os ambientes dos processos de outros usuários. Claro que se o script for executado por root, é desnecessário.

Os nomes de usuário e os números de exibição são usados como os índices de matrizes associativas para manter apenas valores exclusivos.

#!/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]*).*//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

A última linha comentada mostra como notificar-enviar pode ser chamado.

    
por 10.09.2016 / 04:33