Xsession in Debian
Xsession is a default way of starting, well, nothing less but X sessions in
Debian. You can read about it in detail by running man xsession
, or read
source code of the script itself: /etc/X11/Xsession. It’s not very
complicated, but because it’s a shell script, it can be a little intimidating
for newcomers. That’s why I’m publishing this small introduction.
Keep in mind that it’s based on Debian Stretch (9.0, stable as of writing this article), so things might be anywhere from “a little different” to “totally irrelevant” for other Debian releases.
Xsession.d
Xsession is itself quite straightforward. It first sets some environment
variables, does a little bookkeeping and then it sources all scripts from
/etc/X11/Xsession.d, one by one, with help of run-parts
. This is the place
where a lot of recommendations for Debian X session management is implemented,
like that a good place to auto start X applications is ~/.xsessionrc.
It is important to remember that all scripts in Xsession.d are sourced,
not executed. This way all variables, functions and flags (global set +e
)
defined before are available for all consecutive scripts.
Some third-party packages may install their own scripts into Xsession.d (for
example flatpak does that). They’re usually transparent to end-user, but
sometimes they can be controlled one way or the other. Common way of adding
simple, user-controllable flags is Xsession.options file. Keep in mind
however that has_option
function is defined by
20x11-common_process-args
so if you want to process options with
help of this function, you have to ensure that your script is sourced after
common_process_args
.
Other scripts in Xsession.d are shipped by default for all Debian installations with X capabilities. These are the important ones, because they define common environment variables and functions which are re-used in other scripts.
20x11-common_process-args
20x11-common_process-args
This is where $STARTUP
variable is initialized. It’s quite important,
because it names a script or program which will be executed later as a
window/session manager.
Users can directly affect executed command by passing a single optional
argument to Xsession and common_process-args
will process it and assign to
$STARTUP
. This argument accepts also some special names, which are handled
differently:
- if it is set to failsafe, x-terminal-emulator will be executed (usually xterm, but it can be changed by update-alternatives mechanism) and processing of further scripts will be terminated;
- if it is set to default, the script won’t set
$STARTUP
, which will result in a deduction of default session manager by50x11-common-determine-startup
.
This script also defines has_option
function, used for parsing of
Xsession.options file.
30x11-common_xresources
, 40x11-common_xsessionrc
These 2 scripts are sourced right after Xsession arguments are processed.
First one merges all system-wide X resources files found in /etc/X11/Xresources and user-specific one from ~/.Xresources.
Second simply sources ~/.xsessionrc file, so all user-defined environment variables found there will be globally available for the whole X session from now on and commands will be executed (note that commands should typically be run in a background to not block execution of Xsession).
35x11-common_xhost-local
This script simply uses xhost to give access to X server to the local user.
50x11-common_determine-startup
50x11-common_determine-startup
If Xsession wasn’t passed any argument, or if passed argument is not
executable, $STARTUP
won’t be set and common_determine-setup
will run the
default discovery mechanism of what should be run instead:
- ~/.xsession and ~/.Xsession are tried (because some users apparently like to start their file names with capital letters).
- default system-wide session manager: x-session-manager
- default system-wide window manager: x-window-manager
- default system-wide terminal emulator: x-terminal-emulator
90x11-common_ssh-agent
This one often confuses a lot of people. Historically, there always was a problem with finding a good and convienient way to run SSH Agent and even today a lot of people run it from their .bashrc every time new shell starts. Debian solved it by binding its start with start of X session.
Anyway, if no previous ssh-agent appears to be running (e.g. gpg-agent with
enabled support of OpenSSH Agent Protocol), $STARTUP
will be wrapped with
ssh-agent call and executed as agent’s subprocess.
99x11-common_start
Finally we execute our session manager, as common_start
is typically the last
file sourced by Xsession. It’s quite straightforward:
exec $STARTUP
It replaces (via exec
) the current shell with command stored in $STARTUP
variable. This way executed command inherits the whole environment set up by
all previous scripts.
When Xsession will be run
Typically Xsession is sourced (not executed) whenever /etc/X11/xinit/xinitrc is executed. This is handled by startx script (but not xinit, which is wrapped by startx and by itself will only load .xinitrc from user’s home directory).
Xsession is also sourced by display managers, but there are no clear rules when Xsession is used, when it isn’t, and what arguments are passed to it. Documentation of most Display Managers also lacks this knowledge so often all you’re left is the good old trial and error.
This is the source of a lot of headaches about files not being read (or being read unintentionally) during startup. The rule of thumb is: configure your system to ensure Xsession is executed and you’re back on a well-known waters.
Lightdm
Lightdm allows configuring it to use a session-wrapper, which is a script to run session with. This is pre-configured to be Xsession in /usr/share/lightdm/lightdm.conf.d/01_debian.conf.
Typically all available types of X sessions are read in a form of .desktop files from /usr/share/xsessions and some other directories. On login screen Lightdm only allows selecting one of those and passes the value of its Exec field to the session-wrapper as the first argument, which will cause executing correct program.
There is a special .desktop file there, used for so-called “default sessions”,
which has Exec=default. It will be detected by
20x11-common_process-args
and will result in running a fallback
mechanism described in 50x11-common-determine-startup
.
SDDM
SDDM is a little more sane than Lightdm. It doesn’t have hidden settings or use any obscure features. For custom sessions it executes /etc/sddm/Xsession, which ultimately sources /etx/X11/Xsession itself.
SDDM tries to source .profile, .bash_profile, .zprofile etc. It’s a little unusual, because these files are usually boud to terminal sessions and graphical sessions usually source .xprofile.
GDM3
GDM3 runs a bunch of scripts stored in different directories in /etc/gdm3, but ultimately one of them is /etc/gdm3/Xsession. Yep, it has a custom Xsession script, which is similar in some places to the default one, but also adds a bunch of its own logic. For example, if no argument is passed, it defaults to “failsafe” mode.
It doesn’t source the default Xsession, but sources scripts from /etc/X11/Xsession.d by itself. Before that it also tries to source profile and xprofile files.
It also aliases “default” session with a word “custom”.