To disable some getty on my device /dev/ttyAMA0, I have to mask it with systemctl mask serial-getty@ttyAMA0.service. This works fine. So I enable a getty on ttyUSB1 with systemctl enable getty@ftdi2.service. Works also fine.

So my Question: Is there a difference (and what it is) between a serial-getty@.service and a getty@.service?


To see the difference between these two units (or, rather, unit templates), it's enough to look at the difference between files getty@.service and serial-getty@.service, which you can find at /lib/systemd/system on your system.

(The files linked here point to the ones in systemd v239, latest release as of this writing. The files have m4 macros in them, so they're processed before installing, but it's a minor change introduced by m4 processing, so they're close enough.)

There are a few differences, but the main one is the ExecStart= command invoked by each unit.

Unit getty@.service invokes this command:

ExecStart=-/sbin/agetty -o '-p -- \\u' --noclear %I $TERM

While serial-getty@.service invokes this command:

ExecStart=-/sbin/agetty -o '-p -- \\u' --keep-baud 115200,38400,9600 %I $TERM

The command used in serial-getty@.service passes agetty the --keep-baud argument, in order to configure the serial port speed. In a way, getty@.service will work on a serial port, but it might not configure the serial port properly, which might end up not working as well as it could or perhaps being slower than it could be if properly configured.

On the other hand, getty@.service passes agetty the --noclear argument, so the console screen is not cleared after a user logs out (this was traditionally configured on at least tty0.)

Further differences from the unit files:

  • serial-getty@.service binds to the udev device for the serial port (BindsTo=dev-%i.device), so if it's a removable device (such as USB), systemd will stop the getty if the device is removed or unplugged.
  • getty@.service checks that tty0 exists (ConditionPathExists=/dev/tty0), so it doesn't spawn any local consoles if support for them was disabled in the kernel.
  • getty@.service unsets locale variables (UnsetEnvironment=LANG LANGUAGE LC_...) since localization is typically unsupported or poorly supported on the local console.

Regarding your particular case where you're masking ttyAMA0 and enabling ttyUSB1 instead, ttyUSB1 is a serial port (at least, it emulates one), so using serial-getty@.service would be more appropriate.

However, enabling a getty@ or serial-getty@ttyUSB1.service and masking the one @ttyAMA0 is not the best way to accomplish this.

systemd takes its console configuration from the kernel, typically from the console= argument in the kernel command line (this is implemented by systemd-getty-generator, so see its documentation for more details.) So all you need to do is configure the console on the kernel command line (with an argument such as console=ttyUSB1, though you might want to include a local console such as tty0 too) and systemd will do the right thing.

Take a look at this blog post on serial console support in systemd for more details.

| improve this answer | |
  • @StephenKitt That snippet was introduced in this commit which mentions Hindi characters, also linked this bug at the Fedora bug tracker. The commit mentions "most distributions traditionally did from a shell fragment executed post login", which from the bug seems to be /etc/profile.d/lang.sh. Overall, this seems to be another set of compounding nasty bugs and using a coarse workaround... Unfortunately, probably not that on priority list of bugs to fix. – filbranden Nov 7 '18 at 6:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.