Stop Clearing My God Damned Console

If you're like me, the very first thing you see when you boot a new version of your Linux distribution that has switched to systemd is that it erases everything from your console. Obviously, we don't want that! We want to see at least the boot messages. If you're even more like me, you want to see everything from the previous login session, too. I mean, that's why you removed the clear line from your ~/.bash_logout file, right?

In the previous version of your Linux distribution, which probably used some variant of System V init, the screen-clearing was done by getty which was configured in /etc/inittab. All you had to do was:

Trying to figure out how to do the same thing in systemd is maddening. There are some documents floating around the Internet that describe part of the process, but I didn't see any that told you how to do it for all gettys (usually just the getty on tty1), and none of them described what the directory names mean, what the file names mean, how you know what to put where, or what command you have to type after you're all done to make systemd re-read the file.

That's why I'm writing this.

Services... I mean, units

Apparently systemd doesn't manage services like you might be used to from other boot systems. It calls its services "units". So a "unit" is a service, and a "unit file" is the configuration (it's not a file -- it's multiple files) that defines that service.

The first challenge is to find out the name of the unit that you need to change. It's not as obvious as you think, because there's some sort of inheritance crap going on too.

We start with the command systemctl -a which lists all the units:

$ systemctl -a
  UNIT                      LOAD      ACTIVE   SUB       DESCRIPTION
  proc-sys-fs-binfmt_misc.automount loaded    active   waiting   Arbitrary Execu
  dev-cdrom.device          loaded    active   plugged   hp_CDDVDW_SH-216BB
  dev-cdrw.device           loaded    active   plugged   hp_CDDVDW_SH-216BB
  dev-disk-by\x2did-ata\x2dhp_CDDVDW_SH\x2d216BB_R8TM6GBC900DM9.device loaded
  dev-disk-by\x2did-ata\x2dST250DM000\x2d1BD141_9VYJ77MX.device loaded    active
  emergency.service         loaded    inactive dead      Emergency Shell
  exim4.service             loaded    active   running   LSB: exim Mail Transpor
  fcgiwrap.service          loaded    inactive dead      Simple CGI Server
  getty-static.service      loaded    inactive dead      getty on tty2-tty6 if d
  getty@tty1.service        loaded    active   running   Getty on tty1
  getty@tty2.service        loaded    active   running   Getty on tty2
  getty@tty3.service        loaded    active   running   Getty on tty3
  getty@tty4.service        loaded    active   running   Getty on tty4
  getty@tty5.service        loaded    active   running   Getty on tty5
  getty@tty6.service        loaded    active   running   Getty on tty6

The output is automatically piped through a pager if you run it on a terminal (at least in Debian), so you may have to page down a few times.

Once you've identified a unit you want to look at, you move on the the next command.

Unit files

Now we want to see the "unit file" (configuration) for the unit named getty@tty1.service. We run systemctl cat unit-name:

$ systemctl cat getty@tty1.service
# /lib/systemd/system/getty@.service
#  This file is part of systemd.
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

Description=Getty on %I
Documentation=man:agetty(8) man:systemd-getty-generator(8)
# the VT is cleared by TTYVTDisallocate
ExecStart=-/sbin/agetty --noclear %I $TERM

Like systemctl -a, this command's output is also piped through a pager by default. Don't let the "cat" in the name fool you. If you actually want cat-style output (just a bunch of bytes on stdout), you can use systemctl cat unit-name | cat.

Now this tells us some interesting things:

Of course, this doesn't tell you how to change anything. The "obvious" thing to do would be to edit /lib/systemd/system/getty@.service but that's not the accepted practice. Instead, you're supposed to create an override file.

Overriding stupid settings

Apparently, if you want to override stupid settings in /lib/systemd/system/getty@.service you do so by creating a directory (not a file!) named /etc/systemd/system/getty@.service.d (note that the beginning and the ending are different -- it's in /etc and it ends with .d). Then, inside that directory, you create one or more files with little .INI-syntax snippets that mimic the syntax of the file from /lib or /usr/lib.

# mkdir /etc/systemd/system/getty@.service.d
# vi /etc/systemd/system/getty@.service.d/noclear.conf

All of the other documents I found seem to agree that the file you create should end with .conf. The first part of the name seems to be irrelevant.

Inside that file, you create a little miniature version of the .INI-file you're overriding:


As far as I can tell by testing, all of the various getty units that systemd spawns inherit this same "unit file". That is, getty@tty1.service and getty@tty2.service and so on all inherit the configuration called getty@.service. I don't know how or why that happens. It just does. And it's a good thing, too, because otherwise you'd have to create a whole directory + file for every getty. Obviously that would be a horrible thing.

If you followed some other document that said to create /etc/systemd/system/getty@tty1.service.d/ then it will only affect the getty@tty1.service unit (i.e. the getty running on /dev/tty1) and not the others. If you only wanted to avoid clearing the first console and let the others clear themselves after every login session, you could do it that way.

After you've created your override, if you run systemctl cat getty@tty1.service again, you'll see your additions:

$ systemctl cat getty@tty1.service
# /lib/systemd/system/getty@.service
#  This file is part of systemd.

# /etc/systemd/system/getty@.service.d/noclear.conf

So, you can see all of the files that constitute the "unit file" definition, all at once.

But there's one more step to go.

Re-read the file(s)

Now, you have to tell systemd to re-read the files. This step is missing in almost every other document I found.

# systemctl daemon-reload

Of course, rebooting will also work. That's what I ended up doing the first time.

Easier Method

This can be done way easier, by using in-built systemd edit command:

# systemctl edit getty@.service

...this will create the correct directory and open /etc/systemd/system/getty@.service.d/override.conf (with the original config commented out for reference). Add your config as described above, save the file and do a daemon-reload


SystemdNoClear (last edited 2024-01-02 07:17:44 by 140)