You are not logged in.

#1 2017-06-02 03:01:42

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 5,575
Website

[ARCHIVE from #!] What startx actually does in Debian

Now the #! website is getting a bit unreliable, I'm going to copy/paste one of my threads in here, on a topic that still comes up. It's a bit long-winded and hands-on but it goes through the whole startx boot up procedure in Debian in 2012. I don't think it's changed too much in 2017.

All those X files still cause no end of confusion: which ones are used/ignored in which circumstances, which ones to use for what, etc.

And of course this omits all the xdg autostart .desktop files in /etc/xdg/autostart and ~/.config/autostart, not to mention window managers'/desktop environments' own autostart things, like ~/.config/openbox/autostart...

From here on I'm not going to do any editing, just copy-paste my posts as they were. Other users' posts will be added as quotes.

Last edited by johnraff (2017-06-02 03:18:15)


John
--------------------
( a boring Japan blog , Japan Links, idle twitterings  and GitStuff )
In case you forget, the rules.

Offline

#2 2017-06-02 03:02:10

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 5,575
Website

Re: [ARCHIVE from #!] What startx actually does in Debian

The Debian startup script system for getting an X session going is pretty complicated, but if you're using GDM, Slim or most other Display Managers it's never used. However, if you just start things off with 'startx' then a lot of stuff will be done for you automatically, provided you don't use a ~/.xinitrc file. Let's have a look.

NB This was done on Debian Squeeze and I noticed some changes from Ubuntu Jaunty, so it's possible something might be different on Wheezy.

It might be long and messy and it's getting late so I'll post some more later, but if you're impatient to get to the bottom line or just prefer to check these things out for yourself, here are some terminal commands I used. Maybe you'd like to try them, one at a time, and quietly meditating on the results before going on to the next...

which startx
file $( which startx )
cat $( which startx )
which xinit
file $(which xinit)
man xinit
cat /etc/X11/xinit/xinitrc
cat /etc/X11/xinit/xserverrc
cat /etc/X11/Xsession
man run-parts
ls /etc/X11/Xsession.d
run-parts --list  /etc/X11/Xsession.d
cat $( run-parts --list  /etc/X11/Xsession.d )

Now,

cp $( which startx ) .

Open your local copy of startx in an editor and go to the line which starts xinit, near the end:

xinit "$client" $clientargs -- "$server" $display $serverargs

and change it to

echo "xinit command is:
xinit \"$client\" $clientargs -- \"$server\" $display $serverargs"

Then delete everything from there to the end of the file. Now you can run

 ./startx

to see what xinit command you'd get in practice.
Try

touch ./.xinitrc

then run ./startx again to see the difference.
You can also do

bash -x ./startx

to see a bit of how you got there.

The end result of all this is that the fancy stuff is being done by /etc/X11/Xsession but that will have to wait for part 2. smile


John
--------------------
( a boring Japan blog , Japan Links, idle twitterings  and GitStuff )
In case you forget, the rules.

Offline

#3 2017-06-02 03:02:43

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 5,575
Website

Re: [ARCHIVE from #!] What startx actually does in Debian

part 1a
...before part 2, a quick breakdown of the stuff in /usr/bin/startx
A look at 'man startx' and it looks as if usually it's run without arguments - if you add some it behaves more like xinit. Anyway, if you're into sending special commands to X you don't need to be reading this. smile So no arguments, and either your own ~/.xinitrc file (if you know how to handle all that dbus/consolekit stuff) or none (which is the easy way I prefer).

NB all these scripts are invoking /bin/sh, not bash, so if you are ever tempted to edit something, bashisms won't work. The same applies to openbox's autostart file btw.

OK the first bit (I added a couple of comments):

unset DBUS_SESSION_BUS_ADDRESS
unset SESSION_MANAGER

userclientrc=$HOME/.xinitrc        # these two files are probably the most important
sysclientrc=/etc/X11/xinit/xinitrc  # system default

userserverrc=$HOME/.xserverrc    # hardly ever needed
sysserverrc=/etc/X11/xinit/xserverrc

defaultclient=/usr/bin/xterm 
defaultserver=/usr/bin/X
defaultclientargs=""
defaultserverargs=""
defaultdisplay=":0"
clientargs=""
serverargs=""

Apart from /etc/X11/xinit/xinitrc, nothing exciting.
Next:

whoseargs="client"
while [ x"$1" != x ]; do
    case "$1" in
    # '' required to prevent cpp from treating "/*" as a C comment.

    # and lines and lines of this stuff,
    # but remember, we're sending no arguments, so $1 is empty
    # and  [ x"$1" != x ] will never be true
    # so this code won't be run.

    ;;
    esac
    shift
done

Don't be freaked by all these x's in the conditions. (while [ x"$1" != x ]; do...) It's a safety thing for some older shells which would go weird if one of the items was empty. [ x$var = x ] just means $var is empty.
We can pretty much ignore all this too:

# process client arguments
if [ x"$client" = x ]; then
    client=$defaultclient

    # if no client arguments either, use rc file instead
    if [ x"$clientargs" = x ]; then
        if [ -f "$userclientrc" ]; then
            client=$userclientrc
        elif [ -f "$sysclientrc" ]; then
            client=$sysclientrc
        fi
        clientargs=$defaultclientargs
    fi
fi

# process server arguments
if [ x"$server" = x ]; then
    server=$defaultserver
    # if no server arguments or display either, use defaults
    if [ x"$serverargs" = x -a x"$display" = x ]; then
    # For compatibility reasons, only use xserverrc if there were no server command line arguments
    if [ -f "$userserverrc" ]; then
        server=$userserverrc
    elif [ -f "$sysserverrc" ]; then
        server=$sysserverrc
    fi
    serverargs=$defaultserverargs
    display=$defaultdisplay
    fi
fi

This next section makes an X authority cookie, if [ x"$enable_xauth" = x1 ] (that x thing again).

if [ x"$enable_xauth" = x1 ] ; then
    if [ x"$XAUTHORITY" = x ]; then
        XAUTHORITY=$HOME/.Xauthority
        export XAUTHORITY
    fi

    removelist=

    # set up default Xauth info for this machine

    # check for GNU hostname
    if hostname --version > /dev/null 2>&1; then
        if [ -z "`hostname --version 2>&1 | grep GNU`" ]; then
            hostname=`hostname -f`
        fi
    fi
    if [ -z "$hostname" ]; then
        hostname=`hostname`
    fi

    authdisplay=${display:-:0}

    mcookie=`/usr/bin/mcookie`
    if test x"$mcookie" = x; then
        echo "Couldn't create cookie"
        exit 1
    fi

    dummy=0
    # create a file with auth information for the server. ':0' is a dummy.
    xserverauthfile=`mktemp --tmpdir serverauth.XXXXXXXXXX`
    trap "rm -f '$xserverauthfile'" HUP INT QUIT ILL TRAP KILL BUS TERM
    xauth -q -f "$xserverauthfile" << EOF
add :$dummy . $mcookie
EOF

    serverargs=${serverargs}" -auth "${xserverauthfile}

    # now add the same credentials to the client authority file
    # if '$displayname' already exists do not overwrite it as another
    # server man need it. Add them to the '$xserverauthfile' instead.
    for displayname in $authdisplay $hostname$authdisplay; do
        authcookie=`xauth list "$displayname" \
        | sed -n "s/.*$displayname[[:space:]*].*[[:space:]*]//p"` 2>/dev/null;
        if [ "z${authcookie}" = "z" ] ; then
            xauth -q << EOF
add $displayname . $mcookie
EOF
        removelist="$displayname $removelist"
        else
            dummy=$(($dummy+1));
            xauth -q -f "$xserverauthfile" << EOF
add :$dummy . $authcookie
EOF
        fi
    done
fi

After that's run there'll be a serverauth.********** file in /tmp.
Finally, the whole point of startx is to run this:

xinit "$client" $clientargs -- "$server" $display $serverargs

$client will be $HOME/.xinitrc if it exists or else /etc/X11/xinit/xinitrc. The other stuff will probably be "/etc/X11/xinit/xserverrc" :0  -auth /tmp/serverauth.something'.
xserverrc does 'exec /usr/bin/X -nolisten tcp "$@"' to start up the X server, and /etc/X11/xinit/xinitrc says:

. /etc/X11/Xsession

So Xsession is doing the actual work, and that will be in part 2... roll


John
--------------------
( a boring Japan blog , Japan Links, idle twitterings  and GitStuff )
In case you forget, the rules.

Offline

#4 2017-06-02 03:03:10

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 5,575
Website

Re: [ARCHIVE from #!] What startx actually does in Debian

Part 2: /etc/X11/Xsession OK let's get a local copy we can mess with relatively safely:

cp /etc/X11/Xsession ./X-session

Better change the name a bit because Xsession is only a dot away from an actual user file that could exist. Open ~/X-session in your favourite editor. This is more interesting than startx was. Let's have a look.

Lines 1~48 declare some functions for message printing, nothing to worry about.
The next bit is important (some comments added):

# initialize variables for use by all session scripts

OPTIONFILE=/etc/X11/Xsession.options

SYSRESOURCES=/etc/X11/Xresources
USRRESOURCES=$HOME/.Xresources # user X stuff - fonts etc (sometimes put in .Xdefaults)

SYSSESSIONDIR=/etc/X11/Xsession.d  # startup stuff, some added by installed apps
USERXSESSION=$HOME/.xsession      # can set your window manager here
USERXSESSIONRC=$HOME/.xsessionrc # can set locales and environment variables here
ALTUSERXSESSION=$HOME/.Xsession  # (can have capital X)
ERRFILE=$HOME/.xsession-errors    # all stdout & stderr from apps not on terminal goes here

These variables keep turning up later on and they're a pain to remember. roll

Lines 63~75 make that .xsession-errors file if it doesn't exist. Now, there's an issue here. That file will collect all the standard output and standard error from apps launched in the X session if they don't have a terminal to talk to. Quite useful sometimes, but verbose apps can fill that file up with dreck and bloat it out to a huge size over time. Ubuntu used to (and maybe still does) add some lines to /etc/X11/Xsession to keep .xsession-errors to a reasonable size:

# truncate ERRFILE if it is too big to avoid disk usage DoS
if [ "`stat -c%s \"$ERRFILE\"`" -gt 500000 ]; then
  T=`mktemp -p "$HOME"`
  tail -c 500000 "$ERRFILE" > "$T" && mv -f "$T" "$ERRFILE" || rm -f "$T"
fi

but that's not in the Debian file for some reason. You could edit Xsession to put it in, but there are more elegant ways (later). GDM on the other hand gets round this by just deleting ERRFILE on every reboot. It works, but if your system crashed just after boot it might be nice to see the error messages left over from the last session.

On line 77 is the magic command:

exec >>"$ERRFILE" 2>&1

This means that from this point on everything output by the script and all its children will go to ERRFILE, including line 79:

echo "$PROGNAME: X session started for $LOGNAME at $(date)"

After a couple of checks, lines 98~109 are the real meat. This is where all the important startup stuff gets done - dbus, consolekit, im-switch etc., and what looks like the best choice of window manager/desktop environment is started up. That will have to wait till part 3 though, because it's 3:30 am.


John
--------------------
( a boring Japan blog , Japan Links, idle twitterings  and GitStuff )
In case you forget, the rules.

Offline

#5 2017-06-02 03:03:36

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 5,575
Website

Re: [ARCHIVE from #!] What startx actually does in Debian

Part 3 /etc/X11/Xsession.d
Good grief, a week has passed... you've probably figured out the ending by now, or just turned the pages yourselves... roll

But anyway, we're at line 102 of that ~/X-session file we copied from /etc/X11/Xsession.

SESSIONFILES=$(run-parts --list $SYSSESSIONDIR)

SYSSESSIONDIR is that /etc/X11/Xsession.d folder. run-parts (rtm) is a utility in the debianutils package which usually runs a bunch of scripts one after the other, in order. With --list it just spits out the filenames, omitting files which don't fit the naming scheme, so what we get here is the files in that directory, which will now be sourced by the next section of code so they're included in /etc/X11/Xsession. Sourcing (or including) instead of executing means those sub-scripts have access to all the variables that got set earlier, as well as any arguments the original script was sent. It's a handy system because apps like dbus and consolekit can add their own bits to the startup script when they're installed, but it makes things pretty hard for us to keep track of. neutral

We can get the same effect in our local file by running:

cat $( run-parts --list  /etc/X11/Xsession.d ) >> ./X-session

Lines 114 to 426 (the total length will depend on what you have in Xsession.d) have been added to our file. Now comment out lines 102 ~ 111  like this:

#SESSIONFILES=$(run-parts --list $SYSSESSIONDIR)
#if [ -n "$SESSIONFILES" ]; then
  #set +e
  #for SESSIONFILE in $SESSIONFILES; do
    #. $SESSIONFILE
  #done
  #set -e
#fi

#exit 0

and add

exit 0

to the end of the file, so we've got the same result as the original script.

We can run ~/X-session to see what it does, but first let's have a look at it, and also comment out or modify any lines which might mess up our session.

First comment out line 77

#exec >>"$ERRFILE" 2>&1

otherwise all the messages will go to ~/.xsession-errors instead of the terminal.

After a couple of sanity checks we get to the code that came from the file 20x11-common_process-args. To digress a moment here - surely the people who wrote these scripts are vastly more knowlegable than me, but I can't help being moderately unimpressed by the has_option() function here. It tests if the string it's passed is in the OPTIONFILE (ie /etc/X11/Xsession.options). However, it seems a bit fragile to me, for example it returns true if passed "use" as the test string, because it starts "use-ssh-agent", so it only works properly if passed the exact names of the options you want to test for. Also it doesn't allow comments or spaces in the same line as the option in the options file. I guess there must have been some good reason to avoid using grep+regular expressions but I'd humbly suggest this alternative:

has_option() { grep "^[[:blank:]]*$1[[:blank:]]*\(#\|$\)" "$OPTIONFILE" >/dev/null 2>&1; }

Anyway, we can ignore the rest of that file (lines 130~181) because it only applies if an argument was sent.

The next section came from 30x11-common_xresources and this is where the stuff in your ~/.Xresources will be added in, if you have one.

40x11-common_xsessionrc sources in your ~/.xsessionrc if you have one. This is a good place to put your locale settings and environment variables. Just remember that this file will only be read in X sessions. (You could also put that ERRFILE-truncating code here.) Things you want to apply on ttys too might better go in ~/.profile.

Now, more interesting, the code from 50x11-common_determine-startup is where the window manager or desktop environment gets chosen. First, it looks for ~/.xsession or ~/.Xsession and if there is one, that file gets set in the STARTUP variable to be run at the end of the script. This means that you can set your window manager (or other startup script like startxfce4) by writing it in ~/.xsession. Worth knowing. cool

If there's no file then the Debian alternatives system is asked for a candidate session manager, window manager or terminal emulator. That's what you usually get from running plain 'startx' with no options or config files. If you've only got one window manager installed that's no problem of course.

Line 262 or so (depending on what you have on your system) runs /usr/bin/xdg-user-dirs-update from the xdg-user-dirs package.

75dbus_dbus-launch adds the dbus command to STARTUP.

If like me you've installed im-switch then 80im-switch brings in a bunch of code to set up your language input.

90consolekit adds consolekit startup stuff to STARTUP if it's needed.

90x11-common_ssh-agent sets up ssh if needed.

And finally, 99x11-common_start contains this line:

exec $STARTUP

This means that the command in STARTUP will be launched as a new process, replacing the Xsession script.
The

exit 0

at the end will never be executed!

If you want to run ~/X-session to see what happens, change the 'exec $STARTUP' line to:

echo "Startup command is:
exec $STARTUP"

then it will be safe to run in a terminal. Since you already have dbus and consolekit running, the STARTUP command won't be exactly what it would be at login time.

########################################

So...WHAT TO DO?
To start X without GDM, Slim or any window manager.

The simple way:
Run plain 'startx' with no arguments. Don't use an ~/.xinitrc file. If you want to specify a particular window manager, or some startup script, put it in ~/.xsession. If you want to specify locales/languages or environment variables (like PATH) put them in ~/.xsessionrc, or put them in ~/.profile if you want them to apply for tty sessions too.

(If you start X from the command line ~/.profile will already have been read.)

The fancy way:
Copy /etc/X11/Xsession to ~/.xinitrc and edit that to suit your needs. cool


John
--------------------
( a boring Japan blog , Japan Links, idle twitterings  and GitStuff )
In case you forget, the rules.

Offline

#6 2017-06-02 03:04:41

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 5,575
Website

Re: [ARCHIVE from #!] What startx actually does in Debian

el_koraco wrote:

If we wanna follow the no .xinitrc route, but have several window managers, we'd choose the preferred one with

sudo update-alternatives --config x-xindow-manager

I guess. Not that I care, I run a bunch of stuff in .xinitrc and it's by far the most convenient way to keep track of it.

@el_k you can also set your preferred window manager by putting it in ~/.xsession, leaving the debian alternatives alone. The advantage of no .xinitrc is you're not obliged to keep track of any of that other dbus/consolekit stuff. You might not need "a bunch of stuff" in your local file at all. If you have any extra personal commands you can put them in ~/.xsession before the window manager, or in ~/.xsessionrc.


John
--------------------
( a boring Japan blog , Japan Links, idle twitterings  and GitStuff )
In case you forget, the rules.

Offline

#7 2017-06-02 03:05:06

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 5,575
Website

Re: [ARCHIVE from #!] What startx actually does in Debian

Debian docs on starting X:
http://www.debian.org/doc/manuals/debia … dow_system
Debian discussion on .profile and .xsessionrc:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=636108


John
--------------------
( a boring Japan blog , Japan Links, idle twitterings  and GitStuff )
In case you forget, the rules.

Offline

#8 2017-06-02 03:08:53

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 5,575
Website

Re: [ARCHIVE from #!] What startx actually does in Debian

That went OK.
If anyone else wants to preserve their words of wisdom from the #! forum, you can still access the content of your post by hitting "Edit", then copy-paste into a post here. I don't know how much longer this will work though...


John
--------------------
( a boring Japan blog , Japan Links, idle twitterings  and GitStuff )
In case you forget, the rules.

Offline

#9 2017-06-02 12:55:32

BLizgreat!
Resident Babbler - vll!
Registered: 2015-10-03
Posts: 1,016

Re: [ARCHIVE from #!] What startx actually does in Debian

Thanks and interesting John. smile

Offline

Board footer

Powered by FluxBB