Obtenha o número de exibição para um determinado tty

3

Como posso descobrir se o X está sendo executado em um determinado TTY em uma máquina Debian e, nesse caso, recuperar o número de exibição (valor de DISPLAY)?

Edit: O TTY pode ser um console inativo, não necessariamente o ativo. Estou tentando implementar a função

Display()
{
    local tty="$1"
    ...
}
    
por August Karlstrom 28.02.2017 / 16:04

6 respostas

4

Não conheço uma maneira fácil de resolver o mapeamento de /dev/ttyNN to $DISPLAY . No entanto, isso é possível. No meu sistema baseado em Debian, isso retornará o local DISPLAY value :0 para uma sessão X em execução em /dev/tty7 :

xtty=/dev/tty7
xpid=$(lsof "$xtty" 2>/dev/null | awk '$1 == "Xorg" {print $2}')
test -n "$xpid" && ps -fp "$xpid" | awk '$2 == xpid {print $9}' xpid="$xpid"    # → :0

Os estágios intermediários são os seguintes.

  1. O lsof retorna todos os processos abertos no terminal tty fornecido. O awk seleciona o ID do processo para o processo denominado Xorg . YMMV se você não estiver executando esse servidor de exibição X em particular.

    lsof /dev/tty7 2>/dev/null
    COMMAND PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
    Xorg    695 root    8u   CHR    4,7      0t0 1059 /dev/tty7
    
  2. A combinação ps | awk fornece detalhes suficientes do processo Xorg correspondente para entregar o nome DISPLAY :

    ps -fp 695
    UID        PID  PPID  C STIME TTY          TIME CMD
    root       695   639  0 Jan23 tty7     00:01:44 /usr/bin/X :0 -seat seat0 -auth /var/run/lightdm
    
por 28.02.2017 / 16:18
4

Assumindo uma máquina Linux e ferramentas GNU, isso deve funcionar:

#!/bin/bash

## Get Xorg's tty
xorgTTY="$(ps -o tty= "$(pgrep Xorg)")"
## Get the DISPLAY from a process running on that tty
while read pid; do
    display="$(grep -aoP 'DISPLAY=\K[^
#!/bin/bash

## Get Xorg's tty
xorgTTY="$(ps -o tty= "$(pgrep Xorg)")"
## Get the DISPLAY from a process running on that tty
while read pid; do
    display="$(grep -aoP 'DISPLAY=\K[^%pre%]+' /proc/"$pid"/environ)" && break
done < <(pgrep -t "$xorgTTY")
echo "$display"
]+' /proc/"$pid"/environ)" && break done < <(pgrep -t "$xorgTTY") echo "$display"
    
por 28.02.2017 / 16:24
4

Você pode pesquisar por nome do processo. E então, olhe os sockets do domínio unix (possivelmente abstratos) abertos pelo processo para determinar o número de exibição.

pid=$(pgrep -xt "$tty" Xorg) &&
  lsof -aUp "$pid" | sed '\|.*X11-unix/X\([0-9]\{1,\}\) .*|!d;s///;q'

Esse lsof teria que ser executado como root.

Ou você pode extrair o número de exibição dos argumentos da linha de comando, se estiver sempre lá:

pgrep -axt "$tty" Xorg | sed -n 's/.*:\([0-9]\{1,\}\).*//p'
    
por 28.02.2017 / 16:20
2

Algo parecido com isso pode funcionar, supondo que bash seja o shell.

TTY="pts/20"
BASH_PID="$(ps -t $TTY|awk '$4 == "bash" {print $1;exit}')"
TTY_DISPLAY=$(tr '
TTY="pts/20"
BASH_PID="$(ps -t $TTY|awk '$4 == "bash" {print $1;exit}')"
TTY_DISPLAY=$(tr '%pre%0' '\n' < /proc/$BASH_PID/environ|awk -F'=' '$1 == "DISPLAY" {print $2}')
0' '\n' < /proc/$BASH_PID/environ|awk -F'=' '$1 == "DISPLAY" {print $2}')

Estamos especificando um TTY, pegando o primeiro bash pid que encontrarmos e depois extraindo o DISPLAY var de /proc/pid/environ .

    
por 28.02.2017 / 16:21
1

Em uma máquina usando o systemd-logind (que deve incluir o Debian 8), você pode consultar o logind da seguinte forma:

DisplayName()
{
  local ttynr="$1"
  declare -A property
  for session in $(loginctl --no-legend list-sessions | awk '{ print $1 }' ); do
    while IFS="=" read key value ; do
      property[$key]="$value"
    done < <(loginctl show-session $session)

    if [ "${property[VTNr]}" = "$ttynr" ] && [ -n "${property[Display]}" ]; then
      echo "${property[Display]}"
      return 0
    fi
  done
  return 1
}
    
por 01.03.2017 / 08:52
0

No meu sistema Debian 8, todos os processos X recebem o terminal virtual (por exemplo, vt1 ) e o nome de exibição (por exemplo, :0 ) como argumentos. No entanto, dependendo se uma sessão X foi iniciada por um gerenciador de exibição ou a partir do console, a posição dos argumentos será diferente. Inspirado pela resposta do roaima escrevi a seguinte função de shell:

DisplayName()
{
    local ttyNr="$1"

    ps -ef | awk -v ttyNr="$ttyNr" \
        '$8 == "/usr/bin/X" {
            for (i = 9; i <= NF; i++) {
                if ($i == "vt" ttyNr) {
                    isMatch = 1
                } else if ($i ~ "^:[0-9]+$") {
                    display = $i
                }
            }
            if (isMatch) {
                print display
                exit
            }
        }'
}
    
por 28.02.2017 / 21:12

Tags