I have a makeself
script which I expect to be run as root; It's a desktop installer.
At the end of the script, the software which was recently installed to the filesystem tries to launch in user-space.
This works well using sudo -u $(logname) /path/to/application
(or alternately sudo -u $SUDO_USER ...
in Ubuntu 16.04) however a critical environmental variable from the user is missing:
GNOME_DESKTOP_SESSION_ID
I need GNOME_DESKTOP_SESSION_ID
because the child process belongs to Java and Java uses this environmental variable for detecting the GtkLookAndFeel.
However attempts to use sudo -i
have failed.
From some basic tests, the GNOME_DESKTOP_SESSION_ID
doesn't appear to be a natural environmental variable when this users logs in. For example, if I CTRL+ALT+F1
to a terminal, env |grep GNOME
yields nothing whereas XTerm
and gnome-terminal
both yield GNOME_DESKTOP_SESSION_ID
.
How can I get a hold of this GNOME_DESKTOP_SESSION_ID
variable from within the installer script without requiring users to pass something such as the -E
parameter to the sudo
command?
Note, although GtkLookAndFeel
is the primary look and feel for Linux, I prefer not to hard-code the export JAVA_OPTS
either, I prefer to continue to fallback onto Oracle's detection techniques for support, longevity and scalability reasons.
Update: In Ubuntu, GNOME_DESKTOP_SESSION_ID
lives in /usr/share/upstart/sessions/xsession-init.conf
initctl set-env --global GNOME_DESKTOP_SESSION_ID=this-is-deprecated
Which leads to using initctl get-env
to retrieve it. Unfortunately this does not help within a new sudo
shell, nor does any (optimistic) attempt at dbus-launch
.
It turns out this is a two-step process...
UPSTART_SESSION
environmental variables from /proc/$pid/environ
export UPSTART_SESSION
and call initctl --user get-env GNOME_DESKTOP_SESSION_ID
To make this a bit more scalable to other variables, I've wrapped this into a bash helper function. This function should assist fetching other user-environment variables as well. Word of caution, it won't work if the variable's value has a space in the name.
In the below example, only UPSTART_SESSION
and GNOME_DESKTOP_SESSION_ID
are required to answer the question.
Once sudo_env
is called, the next call to sudo -u ...
must be changed to sudo -E -u ...
. The -E
will import the newly exported variables for use by a child process.
# 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
}