有脚本检测gnome会话

时间:2016-11-15 06:28:10

标签: java sudo environment gnome gnome-terminal

我有一个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会产生没有,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中没有帮助,也没有(乐观)尝试dbus-launch

2 个答案:

答案 0 :(得分:1)

事实证明这是一个两步过程...

  1. UPSTART_SESSION
  2. 中读取用户的/proc/$pid/environ个环境变量
  3. 然后export UPSTART_SESSION并致电initctl --user get-env GNOME_DESKTOP_SESSION_ID
  4. 为了使其对其他变量更具可伸缩性,我将其包装成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
    }
    

答案 1 :(得分:0)

您需要在/etc/sudoers.d上使用以下内容创建一个新文件:

Defaults env_keep+=GNOME_DESKTOP_SESSION_ID

但是,有一个问题,如果你已经在sudo内部,它将不会被再次阅读。

因此,完整的解决方案是在脚本中使用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