Como detectar o ambiente da área de trabalho em um script bash?

24

Estou escrevendo um bashscript que precisa saber qual ambiente de área de trabalho (XFCE, Unity, KDE, LXDE, Mate, Cinnamon, GNOME2, GNOME3, ...) está em execução.

Como posso obter essas informações?

Serge Stroobandt
fonte
11
isso é difícil, porque mesmo que você esteja em uma sessão do GNOME e tenha iniciado um programa do KDE, como o kwrite, toda a infraestrutura do KDE, como o daemon do KDE e o kdeinit, estará em execução.
Thorsten Staerk
3
Você praticamente não pode, não de forma confiável. Por que você precisa saber? Isso parece um problema XY .
Gilles 'SO- stop be evil'
@ Gilles Boa pergunta. Estou escrevendo um script de especialidade xplanete gostaria de atualizar automaticamente o plano de fundo da área de trabalho com comandos específicos para o ambiente da área de trabalho. Se você deseja postar uma resposta para esse problema , siga o link.
Serge Stroobandt

Respostas:

11

O principal problema ao verificar o DESKTOP_SESSIONé que ele é definido pelo gerenciador de exibição e não pela sessão da área de trabalho e está sujeito a inconsistências. Para o lightdmDebian, os valores vêm dos nomes dos arquivos em /usr/share/xsessions/. DESKTOP_SESSIONreflete o ambiente da área de trabalho se uma seleção específica é feita no logon, no entanto, lightdm-xsessionsempre é usada a sessão padrão.

GDMSESSIONé outra opção, mas parece ter uma situação semelhante (é o mesmo valor que DESKTOP_SESSIONpara mim).

XDG_CURRENT_DESKTOPparece uma boa escolha, no entanto, atualmente não está no padrão XDG e, portanto, nem sempre é implementado. Veja aqui uma discussão sobre isso. Esta resposta mostra seus valores para diferentes distros / desktops. Também posso confirmar que atualmente não está disponível para mim no XFCE.

O fallback razoável por XDG_CURRENT_DESKTOPnão existir seria tentar XDG_DATA_DIRS. Desde que os arquivos de dados para o ambiente da área de trabalho sejam instalados em um diretório com seu nome, essa abordagem deve funcionar. Espero que este seja o caso de todas as distros / desktops!

Os seguintes testes (com GNU grep) para XFCE, KDE e Gnome:

echo "$XDG_DATA_DIRS" | grep -Eo 'xfce|kde|gnome'

Compatível com POSIX:

echo "$XDG_DATA_DIRS" | sed 's/.*\(xfce\|kde\|gnome\).*/\1/'

Para combinar com a verificação XDG_CURRENT_DESKTOP:

if [ "$XDG_CURRENT_DESKTOP" = "" ]
then
  desktop=$(echo "$XDG_DATA_DIRS" | sed 's/.*\(xfce\|kde\|gnome\).*/\1/')
else
  desktop=$XDG_CURRENT_DESKTOP
fi

desktop=${desktop,,}  # convert to lower case
echo "$desktop"
Graeme
fonte
Eu gosto disso. De acordo com esta visão geral , haverá apenas um problema com o Canela. No entanto, isso pode ser resolvido com a abertura de um relatório de erro com o Linux Mint.
Serge Stroobandt
@ on4aa O MATE não está na lista, é provável que tenha o mesmo problema. apt-filetambém é uma boa ferramenta para ver onde os vários desktops se instalam.
Graeme
11
Esta solução ainda está inclinada para as distribuições baseadas no Debian. Nenhum dos métodos discutidos funciona em nenhuma das distros baseadas no Red Hat às quais tenho acesso (Fedora, CentOS, etc.).
slm
@ SLM interessante, XDG_DATA_DIRSnão existe ou apenas não contém nada de útil?
Graeme
11
@ SLM muito verdadeiro, acho que o OP provavelmente está melhor tentando fazer o que ele quer fazer para cada desktop em um ||estilo. Ainda esta pergunta foi feita em outros sites de SE, acho que temos o melhor conjunto de respostas.
Graeme
10

Método # 1 - $ DESKTOP_SESSION

Eu acho que você pode descobrir interrogando a variável de ambiente $DESKTOP_SESSION. Não tenho muita certeza de quão amplamente isso é suportado, mas em meus testes limitados parece estar disponível no Fedora e Ubuntu.

$ echo $DESKTOP_SESSION
gnome

Outra opção é a $XDG_SESSION_DESKTOPvariável.

Método # 2 - wmctrl

Também existe esse método que faz uso wmctrl.

$ wmctrl  -m
Name: GNOME Shell
Class: N/A
PID: N/A
Window manager's "showing the desktop" mode: N/A

Referências

slm
fonte
11
@ on4aa - $GDMSESSIONme deixa nervosa, pois provavelmente é voltada apenas para o DE que está usando o DE baseado no GDM ou no GNOME. GDM = Gerenciador de exibição do GNOME.
slm
11
@ on4aa DESKTOP_SESSIONno xfce.
Graeme
11
em xfce, meu DESKTOP_SESSION é default(hortelã 15)
Glenn Jackman
11
O Debian também mostrou defaultisso. Uma instalação padrão do GNOME 3.
slm
11
$DESKTOP_SESSIONmostra defaultpara o KDE no Fedora 20.
Matthew Cline
5

Você pode usar esse script bash . Ele pode detectar o nome e a versão do ambiente da área de trabalho.

#!/bin/bash

function detect_gnome()
{
    ps -e | grep -E '^.* gnome-session$' > /dev/null
    if [ $? -ne 0 ];
    then
    return 0
    fi
    VERSION=`gnome-session --version | awk '{print $2}'`
    DESKTOP="GNOME"
    return 1
}

function detect_kde()
{
    ps -e | grep -E '^.* kded4$' > /dev/null
    if [ $? -ne 0 ];
    then
        return 0
    else    
        VERSION=`kded4 --version | grep -m 1 'KDE' | awk -F ':' '{print $2}' | awk '{print $1}'`
        DESKTOP="KDE"
        return 1
    fi
}

function detect_unity()
{
    ps -e | grep -E 'unity-panel' > /dev/null
    if [ $? -ne 0 ];
    then
    return 0
    fi
    VERSION=`unity --version | awk '{print $2}'`
    DESKTOP="UNITY"
    return 1
}

function detect_xfce()
{
    ps -e | grep -E '^.* xfce4-session$' > /dev/null
    if [ $? -ne 0 ];
    then
    return 0
    fi
    VERSION=`xfce4-session --version | grep xfce4-session | awk '{print $2}'`
    DESKTOP="XFCE"
    return 1
}

function detect_cinnamon()
{
    ps -e | grep -E '^.* cinnamon$' > /dev/null
    if [ $? -ne 0 ];
    then
    return 0
    fi
    VERSION=`cinnamon --version | awk '{print $2}'`
    DESKTOP="CINNAMON"
    return 1
}

function detect_mate()
{
    ps -e | grep -E '^.* mate-panel$' > /dev/null
    if [ $? -ne 0 ];
    then
    return 0
    fi
    VERSION=`mate-about --version | awk '{print $4}'`
    DESKTOP="MATE"
    return 1
}

function detect_lxde()
{
    ps -e | grep -E '^.* lxsession$' > /dev/null
    if [ $? -ne 0 ];
    then
    return 0
    fi

    # We can detect LXDE version only thru package manager
    which apt-cache > /dev/null 2> /dev/null
    if [ $? -ne 0 ];
    then
    which yum > /dev/null 2> /dev/null
    if [ $? -ne 0 ];
    then
        VERSION='UNKNOWN'
    else
        # For Fedora
        VERSION=`yum list lxde-common | grep lxde-common | awk '{print $2}' | awk -F '-' '{print $1}'`
    fi
    else    
    # For Lubuntu and Knoppix
    VERSION=`apt-cache show lxde-common /| grep 'Version:' | awk '{print $2}' | awk -F '-' '{print $1}'`
    fi
    DESKTOP="LXDE"
    return 1
}

function detect_sugar()
{
    if [ "$DESKTOP_SESSION" == "sugar" ];
    then
    VERSION=`python -c "from jarabe import config; print config.version"`
    DESKTOP="SUGAR"
    else
    return 0
    fi
}


DESKTOP="UNKNOWN"
if detect_unity;
then
    if detect_kde;
    then
    if detect_gnome;
    then
        if detect_xfce;
        then
        if detect_cinnamon;
        then
            if detect_mate;
            then
            if detect_lxde;
            then
                detect_sugar
            fi
            fi
        fi
        fi
    fi
    fi
fi


if [ "$1" == '-v' ];
then
    echo $VERSION
else
    if [ "$1" == '-n' ];
    then
    echo $DESKTOP
    else
    echo $DESKTOP $VERSION
    fi
fi
alexeevdv
fonte
Funciona no Arch Linux
Colin Keenan
Eu roubei sua idéia de verificar apenas o Xfce no meu script:ps -e | grep -E '^.* xfce4-session$' > /dev/null (($? == 0)) && ...
Colin Keenan
11
isso não funcionou para mim, GNOME Shell 3.26.2eu cheguei UNKNOWN. Nenhuma saída do gnome-session --versiontrabalho para mim é que gnome-shell --version | awk '{print $3}'eu também não recebi nada ps -e | grep -E '^.* gnome-session$'. Isso parece ser por causa de -bno final de gnome-session-b. Removendo os $trabalhos ou simplesmente ps -e | grep 'gnome-session'. Com isso, o script está funcionando. Eu receboGNOME 3.26.2
nath
1

Isso provavelmente depende da situação. Se você souber qual gerenciador de exibição é usado, pode ser que este coloque essas informações em uma variável de ambiente.

Se não for esse o caso, acho que você deve verificar todos os DEs que deseja identificar. Todos eles devem apresentar suas próprias variáveis ​​de ambiente.

Hauke ​​Laging
fonte
Eu estou querendo saber se echo ${DESKTOP_SESSION:0:1}faria o truque? Tanto quanto pude testar, ele retorna upara o Unity e xpara o XFCE. Esperamos que algumas pessoas entrem em sintonia com o KDE e outros desktops.
Serge Stroobandt 23/02
11
@ on4aa É echo ${DESKTOP_SESSION} kde-plasma-safepara o meu KDE. Por que "seguro" ...
Hauke ​​Laging 23/02
Existem alguns usuários do Linux Mint Mate / Cinnamon aqui? E17, LXDE, etc. também são bem vindos ...
Serge Stroobandt
1

Se a variável ambiental XDG_CURRENT_DESKTOPestiver disponível, você deve informar.

# echo $XDG_CURRENT_DESKTOP
KDE
Matthew Cline
fonte
11
Não é uma surpresa, mas apenas os outros estão cientes de que passam por estas perguntas e respostas: não existe no GNOME DE.
slm
De fato, com ênfase em "se disponível". Veja também esta resposta do Askubuntu .
Serge Stroobandt
1

Você pode procurar por Xorgprocessos em execução . O pai disso deve ser seu gerente de exibição. Seus descendentes devem fornecer uma indicação do ambiente de área de trabalho em execução. No meu sistema, o gerenciador de exibição se executa (com parâmetros diferentes). Isso então gera o x-session-managerque está vinculado xfce4-session. Isso pode ser suficiente, mas todos os filhos disso estão relacionados ao meu ambiente de área de trabalho. Encontrá-los através da árvore de processos deve ser a melhor maneira de excluir elementos de outros sistemas de janelas iniciados por vários programas (ou talvez deliberadamente).

Meu primeiro pensamento foi que seria melhor procurar o gerenciador de janelas associado ao seu ambiente de área de trabalho, mas geralmente um diferente pode ser configurado para ser executado (por exemplo, xmonadno Gnome), para que isso não seja robusto. O melhor a procurar é provavelmente aquele que gerencia a área de trabalho real, por exemplo, xfdesktopou qualquer elemento do ambiente de área de trabalho que você realmente precise para que seu script funcione :)

Exemplo

Aqui está um exemplo usando procps-ng ( -Ce --ppidnão é POSIX). Ele assume que é apenas uma instância de Xorg.

Este é apenas um exemplo que funciona na área de trabalho do xfce. Um exemplo de trabalho completo requer uma investigação dos processos que cada sistema de desktop usa, assim como a maioria das outras soluções requer investigação sobre como as variáveis ​​ambientais são definidas em vários outros sistemas de desktop.

X=Xorg

search_descendants ()
{
  ps h -o comm --ppid $1 |
    grep -E '^(xfdesktop|another_desktop_process)$' &&
    return 0

  for pid in $(ps h -o pid --ppid $1)
  do
    search_descendants $pid && return 0
  done

  return 1
}

dm_pid=$(ps h -o ppid -C "$X")

case "$(search_descendants $dm_pid)" in
  xfdesktop)
    desktop=xfce
    ;;
  another_desktop_process)
    desktop=another_desktop
    ;;
  *)
    desktop=unknown
    ;;
esac

echo $desktop
Graeme
fonte
Isso retorna unknownno Ubuntu.
Serge Stroobandt
@ on4aa, não era para ser uma solução completa. Era para ser um exemplo que funciona na área de trabalho do xfce. Um exemplo de trabalho completo requer uma investigação dos processos que cada sistema de desktop usa. Eu pensei que isso seria óbvio ao ler o código.
Graeme
@ Greame Você está certo; Eu fui um pouco rápido demais e negligenciei o another_desktopresultado inacabado .
Serge Stroobandt
1

De todas as experiências relatadas nos inúmeros comentários, acho que é meu dever como OP chegar a uma resposta de consenso. (Tenha certeza, ficaria feliz em revisar esta resposta caso dados contrastantes se tornem disponíveis.)

Por enquanto, parece melhor assumir a liderança $XDG_CURRENT_DESKTOPquando essa variável é definida. Caso contrário, $XDG_DATA_DIRSpoderá fornecer as informações desejadas, mais do que a primeira letra de ${DESKTOP_SESSION:0:1}.

Serge Stroobandt
fonte
Eu não tenho XDG_CURRENT_DESKTOP. Eu acho que o principal problema com essas variáveis ​​é que elas são definidas pelo gerenciador de exibição e não pelo ambiente de desktop e, portanto, há alguma inconsistência. Quando eu escolher uma sessão padrão (xfce) com LightDM echo $DESKTOP_SESSIONlightdm-xsessiono que é uma amálgama de lightdme x-session-manager, o processo usado para iniciar o meu desktop (ligada simbolicamente a xfce4-session). Eu imagino a instalação com uma sessão padrão diferente só vai usar um link simbólico diferente e produzir o mesmoDESKTOP_SESSION
Graeme
Notavelmente, se eu escolher especificamente o XFCE ou o Gnome no gerenciador de exibição, DESKTOP_SESSIONna verdade vou dizer xfceougnome
Graeme
11
Esta solução ainda está inclinada para as distribuições baseadas no Debian. Nenhum dos métodos discutidos funciona em nenhuma das distros baseadas no Red Hat às quais tenho acesso (Fedora, CentOS, etc.).
slm
1

Isso funciona no Ubuntu 18.10 (cósmico) [tipo lxqt] e no Mint 19 (tara) [tipo canela]:

$  set | grep XDG_CURRENT_DESKTOP | tr '[:upper:]' '[:lower:]' | cut -d'=' -f2

Capture o resultado em uma variável e execute o código necessário adicional por meio de lógica analítica capaz (case stmt, if / then) que inclui todos / todos os tipos reconhecidos a partir daí; e / ou funcionam normalmente quando tipos não reconhecidos estão em uso.

odoncaoa
fonte
Funciona também com o Xubuntu LTS 18.04.
Serge Stroobandt