2016-11-15 42 views
1

我有一個makeself腳本,我期望以root身份運行;這是一個桌面安裝程序。有腳本檢測gnome會話

在腳本結尾處,最近安裝到文件系統的軟件嘗試在用戶空間中啓動。

這種運作良好,使用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產生什麼而XTermgnome-terminal都得到GNOME_DESKTOP_SESSION_ID

如何在安裝程序腳本中保留此GNOME_DESKTOP_SESSION_ID變量而無需用戶將諸如-E參數之類的內容傳遞給sudo命令?請注意,儘管GtkLookAndFeel是Linux的主要外觀,但我更願意不對export JAVA_OPTS進行硬編碼,但我更願意繼續回退到Oracle的檢測技術以獲得支持,延長壽命和可擴展性的原因。

更新:在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 shell中沒有幫助,也沒有任何(樂觀)嘗試在​​。

回答

1

事實證明,這是一個兩步的過程...

  1. /proc/$pid/environ
  2. 然後export UPSTART_SESSION閱讀用戶的UPSTART_SESSION環境變量,並調用initctl --user get-env GNOME_DESKTOP_SESSION_ID

爲了使這個更容易擴展到其他變量,我已經把它包裝到一個bash幫助函數中。這個函數也應該幫助獲取其他用戶環境變量。 謹慎的話,如果變量的值在名稱中有空格,它將不起作用。

在下面的例子中,只需要UPSTART_SESSIONGNOME_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

@QZSupport,是的,答案已更新。 – Dyorgio

+0

邏輯有幫助,但它不能解決問題。建議的修復似乎沒有幫助,除非我註釋掉'rm -f'行,硬編碼文件名並再次運行安裝程序。這是一個已經具有root權限的安裝程序,本身已經在'sudo'調用​​中。在附註中......根據sudoers的'README',你應該在調用echo之前使用'umask 0337',但它似乎已經設置得太晚了。安裝程序已經使用'sudo'啓動並且環境變量丟失(我假設)。 – tresf