Killing the Display Manager
Display managers like LightDM and SDDM come standard with many Linux distros, and I personally find them useless. I'd like to share with you how to get rid of them and gain a bit of control over how X is launched, and take back a few precious megabytes of RAM.
Writing an xinitrc
Display managers are usually a fancy graphical wrapper around a few basic commands, namely startx
which is actually a wrapper around xinit
. I won't get into too many of the details (I'm not even sure of many of them, there's historical reasoning that made sense long ago), but suffice it to say, all you need to replace a display manager is the xinit
package and an ~/.xinitrc
script.
My xinitrc
is a bit complex, but here it is:
#!/usr/bin/env bash# arguments passed to startx start at $2 for some reason..# if nothing is passed, default to xtermdeclare wm="${2:-xterm}"# small helper functionis_running() { pgrep -x "$1" &> /dev/null}# this will run immediatelyxrdb -load ~/.Xresourceswhile sleep 0.3; do if is_running "$wm"; then # things inside this will run after your wm has launched xmodmap ~/.xmodmap # firefox & # example break fidone &# Arch Linux users need the followingif [[ -d /etc/X11/xinit/xinitrc.d ]]; then for f in /etc/X11/xinit/xinitrc.d/*; do [[ -x "$f" ]] && source "$f" donefiexec "$wm"
With this script, running startx
will launch xterm, and you can use xterm to run any window manager you want, and switch window managers without actually restarting the X session. You can also pass arguments to startx
: for example, if you wanted to start XFCE you would use startx startxfce4
or if you wanted to launch Openbox: startx openbox-session
.
It's important to note that the last line of the script must be exec <what you want to launch X with>
, and that anything before it will block until it's finished, potentially leaving the script running indefinitely. If you wanted to launch another program automatically (for example redshift), make sure it goes inside the while...if
loop, and that it has an &
after it (like the Firefox example) so that it runs in the background. In the above example I didn't add an &
to the end of the xrdb
or xmodmap
commands since they usually finish running in milliseconds, and forking them to the background would be an unnecessary subshell. Basically any long-running processes, or commands that take a non-trivial amount of time to run, should be forked to the background with &
.
Now that you have an xinitrc script, you can disable your display manager. I can't tell you exactly how to do that since it varies from distro to distro, but if you're using systemd and LightDM you would want to run sudo systemctl disable lightdm
to disable it from running on boot, and sudo systemctl stop lightdm
to stop it running right now. Be warned that the latter will also kill your current X session, so you might want to bookmark this page before you do that.
Starting X automatically on login
Running startx
after login every time is pretty annoying though. Wouldn't it be nice if we could automatically run startx
when we login?
if [[ -z "$DISPLAY" && "$TTY" = '/dev/tty1' ]]; then exec startx startxfce4fi
This little blurb will do just that! It checks to see if there is no existing X server running, and the login occurred on tty1
, which is usually the default. If these conditions are met, it runs startx startxfce4
for you. You'll want to change the startxfce4
part depending on which window manager or desktop environment you use.
If you use bash you'll want to save this as ~/.bash_login
, or if you use zsh you'll want to save it as ~/.zlogin
. If you're unsure, it's likely bash (if you use fish you're on your own here). If you want a solution that's a bit more independent of the shell, you can save it as ~/.login
but you'll still have to tell your shell to source
it either by symlinking to it or by putting source ~/.login
in the appropriate file.
Getting fancy with fzf
If you have a few window managers or desktop environments installed, you'll probably want to be able change between them without editing a script. I hacked together a solution that uses Junegunn's fzf to list and choose those that are available. If fzf
isn't installed or available for some reason it falls back to bash's built in select
feature. You'll want to change your bash_login
or zlogin
script to something like this:
if [[ -z "$DISPLAY" && "$TTY" = '/dev/tty1' ]]; then exec startx "$(wmpicker)"fi
Then, in a new file, save this somewhere in your user's $PATH
(ideally ~/.bin
or ~/.local/bin
) and chmod +x
to make it executable. If you don't have a local-user bin directory I'd strongly suggest making one (the details are a bit out of the scope of this article, you'll have to consult your shell's docs), but if you're lazy you could save it in /usr/local/bin
, just don't forget to chmod +x
.
#!/usr/bin/env bashdeclare -a known_wmsdeclare -a avail_wmsknown_wms=( awesome openbox-session bspwm xmonad dwm startkde startxfce4 xterm )avail_wms=()for wm in "${known_wms[@]}"; do command -v "$1" &> /dev/null "$wm" && avail_wms+=( "$wm" )doneif has fzf; then fzf --reverse --inline-info --cycle < <(printf '%s\n' "${avail_wms[@]}")else PS3="choose a number between 1 and ${#avail_wms[@]}: " select wm in "${avail_wms[@]}"; do echo "$wm" break donefi
This has a hard-coded list, so if yours isn't in there you'll want to add it to the list of known_wms
.
If you prefer fzy or selecta or even just plain dialog
you could change it to use that, but I'll leave that as a exercise for the reader :)
systemd auto-login
Some display manager's include a feature to automatically log you in, but you can do that without a display manager on systemd.
sudo systemctl edit getty@tty1
will open a file with your $EDITOR
, you'll want to change it so it looks something like this:
[Service]ExecStart=-/usr/bin/agetty --autologin <YOUR USERNAME HERE> --noclear %I $TERM
This is shameless stolen from Arch Wiki