2016-11-15 2 views
1

У меня есть сценарий makeself, который, как я ожидаю, будет выполняться как root; Это настольный установщик.Есть сценарий обнаружения гном сессии

В конце сценария программное обеспечение, которое недавно было установлено в файловую систему, пытается запустить в пользовательском пространстве.

Это хорошо работает с использованием sudo -u $(logname) /path/to/application (или попеременно sudo -u $SUDO_USER ... in Ubuntu 16.04), однако критической экологической переменным от пользователя отсутствует:

GNOME_DESKTOP_SESSION_ID 

мне нужно GNOME_DESKTOP_SESSION_ID, потому что дочерний процесс принадлежит Java и Java использует эти переменные среды для обнаружения GtkLookAndFeel.

Однако попытки использования sudo -i потерпели неудачу.

Из некоторых основных испытаний, GNOME_DESKTOP_SESSION_ID не кажется, естественными переменным окружение, когда это пользователи регистрируются в. Например, если я CTRL+ALT+F1 к терминалу, env |grep GNOME ничего не дает, тогда как XTerm и gnome-terminal оба дают GNOME_DESKTOP_SESSION_ID.

Как я могу получить эту переменную GNOME_DESKTOP_SESSION_ID из сценария установщика, не требуя от пользователя передать что-то вроде -E в команду sudo?

Обратите внимание, что хотя я и предпочитаю использовать код export JAVA_OPTS, я предпочитаю не использовать жесткий код export JAVA_OPTS. Я предпочитаю продолжать использовать методы обнаружения Oracle для поддержки, долговечности и масштабируемости.

Update: В Ubuntu GNOME_DESKTOP_SESSION_ID живет в /usr/share/upstart/sessions/xsession-init.conf

initctl set-env --global GNOME_DESKTOP_SESSION_ID=this-is-deprecated 

что приводит к использованию initctl get-env для его получения. К сожалению, это не помогает в новой раковине sudo, а также (оптимистичная) попытка в dbus-launch.

ответ

1

Оказывается, это двухступенчатый процесс ...

  1. Читать UPSTART_SESSION переменные окружения пользователя из /proc/$pid/environ
  2. Тогда export UPSTART_SESSION и вызвать initctl --user get-env GNOME_DESKTOP_SESSION_ID

Чтобы сделать это немного более масштабируемым для других переменных, я завернул его в вспомогательную функцию bash.Эта функция также должна помогать извлекать другие переменные пользовательской среды. Осторожно, это не сработает, если значение переменной имеет пробел в имени.

В приведенном ниже примере для ответа на вопрос требуются только UPSTART_SESSION и GNOME_DESKTOP_SESSION_ID.

После того, как вызывается sudo_env, следующий звонок по номеру sudo -u ... необходимо изменить на sudo -E -u .... -E импортирует вновь экспортированные переменные для использования дочерним процессом.

# Provide user environmental variables to the sudo environment 
function sudo_env() { 
    userid="$(logname 2>/dev/null || echo $SUDO_USER)" 
    pid=$(ps aux |grep "^$userid" |grep "dbus-daemon" | grep "unix:" |awk '{print $2}') 
    # Replace null delimiters with newline for grep 
    envt=$(cat "/proc/$pid/environ" |tr '\0' '\n') 

    # List of environmental variables to use; adjust as needed 
    # UPSTART_SESSION must come before GNOME_DESKTOP_SESSION_ID 
    exports=("UPSTART_SESSION" "DISPLAY" "DBUS_SESSION_BUS_ADDRESS" "XDG_CURRENT_DESKTOP" "GNOME_DESKTOP_SESSION_ID") 

    for i in "${exports[@]}"; do 
     # Re-set the variable within this session by name 
     # Careful, this technique won't yet work with spaces 
     if echo "$envt" | grep "^$i=" > /dev/null 2>&1; then 
      eval "$(echo "$envt" | grep "^$i=")" > /dev/null 2>&1 
      export $i > /dev/null 2>&1 
     elif initctl --user get-env $i > /dev/null 2>&1; then 
      eval "$i=$(initctl --user get-env $i)" > /dev/null 2>&1 
      export $i > /dev/null 2>&1 
     fi 

     echo "$i=${!i}" 
    done 
} 
+0

Я хотел бы конкретно упомянуть об этой помощи @ dyorgio. Он предоставил мне логику '/ proc/$ pid/environ' на другом справочном форуме, который составляет 50% от вышеуказанного решения. Благодаря! – tresf

0

Вам нужно создать новый файл на /etc/sudoers.d с этим содержимым:

Defaults env_keep+=GNOME_DESKTOP_SESSION_ID 

Но есть проблема, если вы уже внутри Суды, это не было снова читать.

Таким образом, полное решение является использование Sudo внутри вашего скрипта, чтобы создать этот файл, а затем выполнить вашу команду в другой Sudo:

#!/bin/bash 
# ignore sudo 
if [[ -z $SUDO_USER ]]; then 
    #save current dir 
    DIR="$(pwd)" 
    #generate random string (file name compatible) 
    NEW_UUID=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) 
    #create env_keep file 
    sudo -i -- <<EOF0 
     echo "Defaults env_keep+=GNOME_DESKTOP_SESSION_ID" > /etc/sudoers.d/"$NEW_UUID"_keep_java_laf 
    EOF0 
    sudo -u YOUR_USER -i -- <<EOF 
     #go to original directory 
     cd "$DIR" 
     #execute your java command 
     java YOUR_COMMAND 
    EOF 
    #clean file 
    sudo rm -f /etc/sudoers.d/"$NEW_UUID"_keep_java_laf 
else 
    echo "sudo not allowed!";exit 1; 
fi 
+0

Спасибо! Как это будет работать в сочетании с 'sudo -u foo'? – tresf

+0

@QZПоддержка, да, ответ обновлен. – Dyorgio

+0

Логика помогает, но это не устраняет проблему. Предлагаемое исправление, похоже, не поможет, если я не прокомментирую строку 'rm -f', не переустанавливаю имя файла и не запускаю установщик во второй раз. Это установщик, который уже имеет права root и сам уже находится в вызове 'sudo'. На боковой ноте ... в соответствии с sudoers 'README', вы должны использовать' umask 0337' перед вызовом эха, но, похоже, он становится слишком запоздалым. Установщик уже запущен с 'sudo', и переменная окружения теряется (я полагаю). – tresf

Смежные вопросы