A seguir estão outras perguntas que acho que preciso saber:
De uma sessão não X? (o que significa que o root não está logado no X)
Se várias pessoas estivessem logadas no X, eu poderia detectar automaticamente quem estava em qual tela e, assim, detectar programaticamente em qual tela preciso iniciar o aplicativo?
Posso iniciar o aplicativo como usuário? (ok, tenho 99,999% de certeza de que isso é um sim)
Posso detectar se os usuários do grupo X estão conectados ao X?
Para iniciar um programa gráfico na área de trabalho de um usuário, você precisa encontrar duas coisas: qual tela a área de trabalho do usuário está (o endereço) e qual cookie de autorização usar (a senha).
O comando a seguir deve listar as exibições locais nas quais o usuário está conectado (um por linha) na maioria das unidades:
who | awk -v user="$target_user" '$1 == user && $2 ~ "^:" {print $2}'
Encontrar o cookie de autorização é um pouco mais difícil. Você deve procurar o arquivo de cookie do usuário, que é ~/.Xauthority
por padrão (tudo o que você precisa é o local do arquivo de cookies, não é necessário extrair o cookie). Isso funciona em muitos sistemas, mas não em todos; depende do gerenciador de exibição e de como é configurado, e em particular o Gdm (o padrão no Ubuntu) não usou o local padrão pela última vez que olhei. Não consigo pensar em uma maneira portátil de descobrir o arquivo X cookie real. A maneira mais precisa de descobrir é descobrir o detalhe do processo X e procurar o argumento para o -auth
opção. Outra maneira é encontrar um processo em execução no servidor X e pegar sua variável XAUTHORITY
environmentemnt. Se você tiver problemas para encontrar o arquivo de cookie, consulte Abra uma janela em um monitor X remoto (por que "Não é possível abrir o monitor")?
Depois de ter as duas informações, coloque a exibição escolhida na variável de ambiente DISPLAY
, o arquivo de cookie de autoridade X escolhido na variável de ambiente XAUTHORITY
e você estará definido. Não importa em qual usuário o programa é executado; combine com su
se quiser.
Não posso tentar isso completamente, pois todas as minhas máquinas têm o root desativado.
Para descobrir em qual tela o usuário está, você pode usar o comando who
. A última coluna de saída é geralmente o DISPLAY no qual o usuário está conectado. Algo assim pode ser usado para capturar apenas a tela (provavelmente existe uma maneira muito mais eficiente de fazer isso, fique à vontade para oferecer edições):
who | grep -m1 ^username.*\( | awk '{print $5}' | sed 's/[(|)]//g'
Em seguida, para ativar um comando gráfico X nessa exibição:
DISPLAY=:0 firefox &
onde: 0 seria substituído por qualquer exibição que você encontrasse no primeiro comando e o firefox seria substituído pelo comando que você deseja executar. Você pode colocar isso em um script do Shell e apenas usar uma variável.
A próxima parte é a parte que não testei, mas não vejo por que não deveria ser possível:
su username -c "DISPLAY=:0 firefox"
para iniciar o comando X como esse usuário.
Você pode ver como isso é acido. Por exemplo. quando emite comandos xscreensaver ou apaga a tela de cada usuário que executa a sessão X ou X.
Por exemplo, no Ubuntu, este arquivo contém itens relacionados:
/etc/acpi/lid.sh
Contém este loop:
for x in /tmp/.X11-unix/*; do
displaynum=`echo $x | sed s#/tmp/.X11-unix/X##`
getXuser;
if [ x"$XAUTHORITY" != x"" ]; then
export DISPLAY=":$displaynum"
grep -q off-line /proc/acpi/ac_adapter/*/state
if [ $? = 1 ]
then
if pidof xscreensaver > /dev/null; then
su $user -c "xscreensaver-command -unthrottle"
fi
fi
if [ x$RADEON_LIGHT = xtrue ]; then
[ -x /usr/sbin/radeontool ] && radeontool light on
fi
if [ `pidof xscreensaver` ]; then
su $user -c "xscreensaver-command -deactivate"
fi
su $user -c "xset dpms force on"
fi
done
Uma extensão da resposta de Gilles é como encontrar o arquivo de cookie. Uma maneira de fazer isso pode ser depois que você definir a variável de ambiente DISPLAY
(conforme descrito por Gilles), use strace
para encontrar os arquivos xhost
access. Eu posso pensar em algo assim no BASH:
# Set the DISPLAY variable first
DISPLAY = :0.0
# Use strace on xhost
strace xhost 2>&1 | grep access
A saída do código acima será semelhante a:
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
access("/home/someuser/.Xauthority", R_OK) = 0
Como você pode ver claramente, o arquivo de cookie aparecerá diretamente aqui.
Em minha pesquisa para encontrar uma maneira elegante de exibir tarefas GUI ou X em ambientes limitados, como regras do udev ou do superusuário, criei recentemente uma ferramenta para se ajustar a ela ( para obter mais detalhes ).
xpub
é um script do Shell para obter as variáveis do ambiente de exibição do X relacionadas ao TTY atual ou a um determinado TTY.
Este é um exemplo com uma regra do udev:
IMPORT{program}="/usr/bin/xpub", \
RUN+="/bin/su $env{XUSER} -c '/usr/bin/notify-send Hello'"
$env{ENV}
: se o usuário atual do tty iniciar o X, remova-o.
O princípio é o mesmo para uma linha de comando usando export
:
export $(xpub) ; su ${XUSER} -c 'notify-send Hello'