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:
Edit /etc/inittab, adding the --noclear option to each getty command
Run telinit q to make init re-read the file
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 firstname.lastname@example.org loaded active running Getty on tty1 email@example.com loaded active running Getty on tty2 firstname.lastname@example.org loaded active running Getty on tty3 email@example.com loaded active running Getty on tty4 firstname.lastname@example.org loaded active running Getty on tty5 email@example.com 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.
Now we want to see the "unit file" (configuration) for the unit named firstname.lastname@example.org. We run systemctl cat unit-name:
$ systemctl cat email@example.com # /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. [Unit] Description=Getty on %I Documentation=man:agetty(8) man:systemd-getty-generator(8) Documentation=http://0pointer.de/blog/projects/serial-console.html ... [Service] # the VT is cleared by TTYVTDisallocate ExecStart=-/sbin/agetty --noclear %I $TERM Type=idle Restart=always RestartSec=0 UtmpIdentifier=%I TTYPath=/dev/%I TTYReset=yes TTYVHangup=yes TTYVTDisallocate=yes KillMode=process IgnoreSIGPIPE=no SendSIGHUP=yes ...
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:
The bulk of this "unit file" comes from the actual file /lib/systemd/system/getty@.service
- The files are written in Microsoft Windows .INI syntax
TTYVTDisallocate=yes overrides what the manual page systemd.exec(5) says (that the default for this setting is "no")
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:
- One reader claims that there must not be an empty line at the end of this file -- and that if an empty line is present, systemd will ignore the file entirely. I can find no evidence that this is true, but I suppose it's possible there are some weird bugs in specific instances of systemd in the wild.
As far as I can tell by testing, all of the various getty units that systemd spawns inherit this same "unit file". That is, firstname.lastname@example.org and email@example.com 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 /firstname.lastname@example.org/ then it will only affect the email@example.com 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 firstname.lastname@example.org again, you'll see your additions:
$ systemctl cat email@example.com # /lib/systemd/system/getty@.service # This file is part of systemd. # ... # /etc/systemd/system/getty@.service.d/noclear.conf [Service] TTYVTDisallocate=no
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.