让脚本检测 gnome 会话
Have script detect gnome session
我有一个 makeself
脚本,我希望它是 运行 作为 root;这是一个桌面安装程序。
在脚本末尾,最近安装到文件系统的软件尝试在用户 space 中启动。
使用 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
.
如何在不要求用户向 sudo
命令传递 -E
参数的情况下从安装程序脚本中获取此 GNOME_DESKTOP_SESSION_ID
变量?
请注意,尽管 GtkLookAndFeel
is the primary look and feel for Linux, I prefer not to hard-code the 两者都有,但出于支持、寿命和可扩展性的原因,我更愿意继续使用 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
.
您需要在 /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
原来这是一个两步过程...
- 从
/proc/$pid/environ
读取用户的UPSTART_SESSION
环境变量
- 然后
export UPSTART_SESSION
并调用 initctl --user get-env GNOME_DESKTOP_SESSION_ID
为了使其对其他变量更具可扩展性,我将其包装到 bash 辅助函数中。此功能还应有助于获取其他用户环境变量。 注意,如果变量的值在名称中包含 space,它将不起作用。
在下面的例子中,只需要 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 }')
# Replace null delimiters with newline for grep
envt=$(cat "/proc/$pid/environ" |tr '[=10=]' '\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
}
我有一个 makeself
脚本,我希望它是 运行 作为 root;这是一个桌面安装程序。
在脚本末尾,最近安装到文件系统的软件尝试在用户 space 中启动。
使用 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
.
如何在不要求用户向 sudo
命令传递 -E
参数的情况下从安装程序脚本中获取此 GNOME_DESKTOP_SESSION_ID
变量?
请注意,尽管 GtkLookAndFeel
is the primary look and feel for Linux, I prefer not to hard-code the
更新:在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
.
您需要在 /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
原来这是一个两步过程...
- 从
/proc/$pid/environ
读取用户的 - 然后
export UPSTART_SESSION
并调用initctl --user get-env GNOME_DESKTOP_SESSION_ID
UPSTART_SESSION
环境变量
为了使其对其他变量更具可扩展性,我将其包装到 bash 辅助函数中。此功能还应有助于获取其他用户环境变量。 注意,如果变量的值在名称中包含 space,它将不起作用。
在下面的例子中,只需要 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 }')
# Replace null delimiters with newline for grep
envt=$(cat "/proc/$pid/environ" |tr '[=10=]' '\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
}