Xubuntu + Xfce: setting shell environment

System: Ubuntu 12.04 (precise)
Desktop Environment: Xfce 4.10, distributed by Xubuntu

As it often happens, an update or install messes up your system and in the process of fixing it you start researching and learning something new. Which is a good thing. Bad thing is that you sure have other plans when you are forced to work on the fix.

This time it was installation of Ruby enVironment Manager (rvm). Everything went smoothly at the time, but later I’ve noticed that my ~/.bashrc is no longer sourced. It turns out that rvm installed .bash_profile  in my home dir (I did not have it before). Also the instructions suggested to run terminal in the login mode to make sure rvm is working. Now I know what happened and why, but it took me some time to figure it out. Below is what I learned and how I fixed and organized my shell environment in the process.

A bit of theory first. Your shell can be: login/non-login and interactive/non-interactive. These options make 4 possible combinations. Login shell is used when the user is required to login, e.g. via ssh – usually it is also an interactive shell. In desktop environment terminal is normally started as an interactive non-login shell, but it is possible to configure the terminal to start as a login shell (despite the name it does not ask for user/password when it starts). In Xfce: open a terminal and set the option using this path:  Menu -> Edit -> Preferences -> General Tab -> “Run command as login shell”

Here is how bash deals with the 3 files which can be present in the home dir (derived from “man bash”). Interactive login shell searches files in this order (only the first found is executed):

~/.bash_profile
~/.bash_login
~/.profile

Interactive non-login shell uses only this one:
~/.bashrc

To avoid surprises I’ve put all custom settings into ~/.bashrc
and sourced it from ~/.bash_profile
Something like that:

# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
    fi
fi

This way I get the same environment in both login and non-login shells.

After having done this I decided that I also want to have custom environment for the programs launched from the desktop environment (GUI). When Xfce session starts (right after you are authenticated in the initial login screen), Xfce tries to run the script from ~/.config/xfce4/xinitrc, if it is not found, it runs the script located in /etc/xdg/xfce4/xinitrc. Below is the sequence of calls when the user’s script is found:
root: /sbin/init
root: lightdm
root: lightdm –session-child 12 97
user:  /bin/sh/ /home/user/.config/xfce4//xinitrc — /etc/X11/xinit/xserverrc
user: xfce4-session
The last process launches everything related to the desktop environment, and its children inherit the settings provided in xinitrc. To customize the GUI environment you are supposed to copy the system file to your home dir and modify it:

cp /etc/xdg/xfce4/xinitrc ~/.config/xfce4/xinitrc

Here is a part of the modified file:

# run xfce4-session if installed
if which xfce4-session >/dev/null 2>&1; then

  # check if we start xfce4-session with ck-launch-session. this is only
  # required for starting from a console, not a login manager
  if test "x$XFCE4_SESSION_WITH_CK" = "x1"; then
    if which ck-launch-session >/dev/null 2>&1; then
      ck-launch-session xfce4-session
    else
      echo
      echo "You have tried to start Xfce with consolekit support, but"
      echo "ck-launch-session is not installed."
      echo "Aborted startup..."
      echo

      exit 1
    fi
  else
    # set gui environment
    if [ -f "$HOME/.xfcebashrc" ]; then
        source "$HOME/.xfcebashrc"
    fi
    # start xfce4-session normally
    xfce4-session
  fi

  exit 0
fi

The snippet above is almost identical to the original system file, I’ve only inserted these lines:

     # set gui environment
     if [ -f "$HOME/.xfcebashrc" ]; then
         . "$HOME/.xfcebashrc"
     fi

Note that the script is run under sh, not bash, so bash-specific commands like source would not work. In the code above ~/.xfcebashrc is sourced, and I can configure my GUI environment by making it look like this:

# Local Java installation path
PATH=$HOME/bin/jdk1.6.0_31/bin:$PATH
export JAVA_HOME=$HOME/bin/jdk1.6.0_31

# Android tools path
PATH=$PATH:$HOME/bin/android-sdk-linux/tools:\
$HOME/bin/android-sdk-linux/platform-tools
# Android NDK path
PATH=$PATH:$HOME/bin/android-ndk

# Add RVM to PATH for scripting
PATH=$PATH:$HOME/.rvm/bin 

export PATH

Now I have to take care of two files when I want to change shell environment:
~/.xfcebashrc    – for GUI – launched programs and
~/.bashrc          – for the terminal
Having two files I can set these environments independently. Note that the GUI environment will change on the next GUI login.

And in the end some useful commands and resources found on the net.
To see which path (or other environment) is being used by your GUI programs, start “Run Program” from the System menu and run this (it will produce a message containing the GUI path):

xmessage $PATH

To check if the shell is login or non-login:

shopt login_shell

To check environment of a running process with a known PID (replace PID with a number):

xargs --null --max-args=1 echo < /proc/PID/environ

Useful resources:
http://wiki.debian.org/EnvironmentVariables
http://wiki.debian.org/DotFiles

 

One thought on “Xubuntu + Xfce: setting shell environment

Leave a Reply

Your email address will not be published. Required fields are marked *