Вопрос или проблема
Я пишу скрипт на bash
, который должен знать, какая среда рабочего стола (XFCE, Unity, KDE, LXDE, Mate, Cinnamon, GNOME2, GNOME3 и т. д.) запущена.
Как я могу получить эту информацию?
Основная проблема при проверке DESKTOP_SESSION
заключается в том, что она устанавливается менеджером дисплея, а не сессией рабочего стола и подвержена несоответствиям. Для lightdm
на Debian значения берутся из имен файлов в /usr/share/xsessions/
. DESKTOP_SESSION
отражает среду рабочего стола, если на входе сделан определенный выбор, однако lightdm-xsession
всегда используется по умолчанию.
GDMSESSION
— это другой вариант, но, похоже, у него такая же проблема (это то же значение, что и DESKTOP_SESSION
для меня).
XDG_CURRENT_DESKTOP
выглядит как хороший выбор, однако в настоящее время он не входит в стандарт XDG и, следовательно, не всегда реализован. См. здесь для обсуждения этого вопроса. Этот ответ показывает его значения для различных дистрибутивов/рабочих столов, я также могу подтвердить, что он в настоящее время недоступен для меня в XFCE.
Разумным запасным вариантом, если XDG_CURRENT_DESKTOP
не существует, было бы попытаться использовать XDG_DATA_DIRS
. Если файлы данных для среды рабочего стола установлены в директории с ее именем, этот подход должен сработать. Надеюсь, это будет актуально для всех дистрибутивов/рабочих столов!
Следующий (с GNU grep) тестирует XFCE, KDE и Gnome:
echo "$XDG_DATA_DIRS" | grep -Eo 'xfce|kde|gnome'
Совместимо с POSIX:
echo "$XDG_DATA_DIRS" | sed 's/.*\(xfce\|kde\|gnome\).*/\1/'
Чтобы объединить с проверкой 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,,} # преобразовать в строчные буквы
echo "$desktop"
Метод #1 – $DESKTOP_SESSION
Я думаю, вы можете узнать, опросив переменную окружения $DESKTOP_SESSION
. Я не совсем уверен, насколько широко это поддерживается, но в моем ограниченном тестировании это оказалось доступным на Fedora и Ubuntu.
$ echo $DESKTOP_SESSION
gnome
Другой вариант – переменная $XDG_SESSION_DESKTOP
.
Метод #2 – wmctrl
Существует также этот метод, который использует wmctrl
.
$ wmctrl -m
Name: GNOME Shell
Class: N/A
PID: N/A
Режим "показать рабочий стол" менеджера окон: N/A
Ссылки
Вы можете использовать этот скрипт bash. Он может обнаружить имя и версию среды рабочего стола.
#!/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
# Мы можем обнаружить версию LXDE только через менеджер пакетов
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
# Для Fedora
VERSION=`yum list lxde-common | grep lxde-common | awk '{print $2}' | awk -F '-' '{print $1}'`
fi
else
# Для Lubuntu и 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
Стандарты сильно изменились с момента, когда вопрос был задан в 2014 году.
На 2021 год, моя рекомендация такова: используйте только официальную $XDG_CURRENT_DESKTOP
.
Будьте осторожны, поскольку официально это разделенный двоеточием список (как $PATH
), так что не предполагается, что он содержит только одно значение, даже если это так в большинстве DE. Например, в Unity от Ubuntu он установлен на Unity:Unity7:ubuntu
.
Если вы предпочитаете обрабатывать одно значение, используйте $XDG_SESSION_DESKTOP
.
Официальные стандарты:
-
XDG_CURRENT_DESKTOP, определенный в Спецификации записи рабочего стола с ее версии 1.2
-
XDG_SESSION_DESKTOP, лучше всего описанный в
systemd
‘s PAM
Другие связанные переменные окружения теперь следует считать устаревшими.
Функция bash, которая правильно проверяет заданную строку относительно текущей среды рабочего стола:
# Инкапсулирует беспорядок, которым была, есть или когда-либо будет детекция DE...
# Без аргументов проверяет, есть ли вообще среда рабочего стола
# Подсистема сделана намеренно, чтобы нам не нужно было сохранять/восстанавливать IFS
# Сравнение без учета регистра
is_desktop_environment() (
local de=${1:-}
local DEs=${XDG_CURRENT_DESKTOP:-}
# Упрощение: если de пусто, проверьте, пустое ли DEs
if [[ -z "$de" ]]; then if [[ "$DEs" ]]; then return; else return 1; fi; fi
# Приведите оба к нижнему регистру
de=${de,,}; DEs=${DEs,,}
# Проверьте de с каждым компонентом DEs
IFS=:; for DE in $DEs; do if [[ "$de" == "$DE" ]]; then return; fi; done
# Не найдено
return 1
)
Тестирование:
for de in "" Ubuntu Gnome KDE Unity; do
if is_desktop_environment "$de"; then
echo "Да, это ${de:-DE}"
else
echo "Нет, это не ${de:-DE}"
fi
done
Да, это DE
Да, это Ubuntu
Нет, это не Gnome
Нет, это не KDE
Да, это Unity
Это, вероятно, зависит от ситуации. Если вы знаете, какой менеджер дисплея используется, то может быть, что именно он помещает эту информацию в переменную окружения.
Если это не так, то я полагаю, вам придется проверять каждую среду рабочего стола, которую вы хотите идентифицировать. Все они должны вводить свои собственные переменные окружения.
Если переменная окружения XDG_CURRENT_DESKTOP
доступна, она должна сообщить вам.
# echo $XDG_CURRENT_DESKTOP
KDE
Вы можете искать выполняющиеся процессы Xorg
. Родитель этого процесса должен быть вашим менеджером дисплея. Его потомки должны дать представление о том, какая среда рабочего стола запущена. В моей системе менеджер дисплея выполняет себя (с разными параметрами). Это затем порождает x-session-manager
, который связан с xfce4-session
. Этого может быть достаточно, но все дочерние процессы связаны с моей средой рабочего стола. Находить их через дерево процессов — это лучший способ исключить элементы других оконных систем, запущенных различными программами (или, возможно, намеренно).
Моя первая мысль заключалась в том, что лучше всего искать менеджер окон, связанный с вашей средой рабочего стола, но часто можно настроить запуск другого (например, xmonad
в Gnome), так что это не надежно. Наверное, лучше всего искать тот, который управляет фактическим рабочим столом, например, xfdesktop
или любой другой элемент, который вам действительно нужен для работы вашего скрипта 🙂
Пример
Вот пример использования procps-ng (-C
и --ppid
не являются POSIX). Он предполагает, что имеется только один экземпляр Xorg
.
Это просто пример, который работает для рабочего стола xfce. Полный рабочий пример требует исследования процессов, используемых каждой системой рабочего стола, так же как и большинство других решений требует исследования того, как устанавливаются переменные окружения в различных других системах рабочего стола.
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
После всех проведенных экспериментов, о которых сообщалось в многочисленных комментариях, я считаю своим долгом как ОП прийти к консенсусному ответу. (Не сомневайтесь, я был бы рад пересмотреть этот ответ, если появятся контрастные данные.)
На данный момент, похоже, лучше всего опираться на $XDG_CURRENT_DESKTOP
, когда эта переменная определена. Если нет, $XDG_DATA_DIRS
может предоставить желаемую информацию, больше чем первая буква ${DESKTOP_SESSION:0:1}
.
Это работает как на Ubuntu 18.10 (cosmic) [тип lxqt], так и на Mint 19 (tara) [тип cinnamon]:
$ set | grep XDG_CURRENT_DESKTOP | tr '[:upper:]' '[:lower:]' | cut -d'=' -f2
Захватите результат в переменную и выполните дальнейший необходимый код с помощью аналитической логики (инструкция case, if/then), которая включает любые/все распознанные типы, начиная с этого; и/или функционируйте корректно, когда используются незнакомые типы.
Ответ или решение
Определение окружения рабочего стола в bash-скрипте
При написании bash-скрипта, который нуждается в идентификации текущего окружения рабочего стола (например, XFCE, Unity, KDE, LXDE, Mate, Cinnamon и так далее), часто возникает необходимость обратиться к переменным окружения. Однако, не все версии различных дистрибутивов Linux поддерживают одни и те же переменные. В данном ответе я рассмотрю наиболее распространенные подходы к определению рабочего окружения и предложу пример скрипта для их использования.
Основные переменные окружения
-
XDG_CURRENT_DESKTOP: Это наиболее предпочтительная переменная, так как она предназначена для обозначения текущего окружения рабочего стола согласно стандартам Freedesktop.org. Однако, будьте внимательны: в некоторых дистрибутивах она может не поддерживаться или содержать список значений, разделенных двоеточием.
echo "$XDG_CURRENT_DESKTOP"
-
DESKTOP_SESSION и XDG_SESSION_DESKTOP: Эти переменные также могут давать информацию о текущем сеансе рабочего стола. Однако, как вы правильно заметили, они являются более подверженными изменениям и могут не всегда точно отражать текущее окружение.
echo "$DESKTOP_SESSION" echo "$XDG_SESSION_DESKTOP"
-
XDG_DATA_DIRS: Если переменная XDG_CURRENT_DESKTOP недоступна, вы можете обращаться к XDG_DATA_DIRS для выдачи информации о доступных управляющих файлах для различных окружений.
-
wmctrl: Этот инструмент может быть использован для получения информации о запущенных сеансах рабочего окружения.
wmctrl -m
Пример скрипта
Вот пример bash-скрипта, который использует перечисленные переменные для определения текущего окружения рабочего стола:
#!/bin/bash
detect_desktop_environment() {
local desktop=""
# Проверяем XDG_CURRENT_DESKTOP
if [ -n "$XDG_CURRENT_DESKTOP" ]; then
desktop="$XDG_CURRENT_DESKTOP"
# Падбораем значение из XDG_DATA_DIRS, если предыдущая переменная недоступна
else
desktop=$(echo "$XDG_DATA_DIRS" | grep -Eo 'xfce|kde|gnome|unity|mate|cinnamon' | head -n 1)
fi
# Приводим к нижнему регистру
desktop=${desktop,,}
# Выводим результат
echo "Текущее окружение рабочего стола: $desktop"
}
# Вызов функции
detect_desktop_environment
Советы по улучшению
-
Проверка процессов: В дополнение к проверке переменных окружения, вы можете посмотреть на запущенные процессы для более точного определения окружения:
ps -e | grep -E 'xfce4-session|gnome-session|kded4|cinnamon'
-
Пользовательские функции: Создайте функции для проверки конкретных окружений рабочего стола, как показано в более сложных примерах.
-
Обработка ошибок и исключений: Убедитесь, что ваш скрипт корректно обрабатывает ситуации, когда ни одна из переменных не установлена.
Заключение
В итоге, для определения окружения рабочего стола в bash-скрипте лучше всего использовать переменную XDG_CURRENT_DESKTOP, если она доступна. Если нет — можно обратиться к переменной XDG_DATA_DIRS или использовать команду wmctrl для получения информации о текущем рабочем окружении. Подходы должны быть проверены в зависимости от конкретной конфигурации и использования дистрибутива.