TIL: The TTYPath= setting to starting an interactive program on boot
For $WORK I had to setup a Linux machine (a Raspberry Pi) so that right
after boot, an interactive CLI tool would start, ready to receive input and
show information.
Of course if you start a script at boot, its stdin is closed and stdout
goes to the Journal. There exists openvt(1) to launch that script in a new VT
(or to take over tty1). (But then you have to mind that openvt needs to
run as root to open a new VT, so it should wrap sudo to drop privileges, and
that get a bit fiddly.)
Then I happened upon the TTYPath setting, which does exactly what I need;
and of course it combines perfectly fine with settings for User= or
WorkingDirectory. I ended up with the following:
[Unit] Description=Interactive script started on boot [Install] WantedBy=multi-user.target [Service] # The magic to have prompts displayed to the user TTYPath=/dev/tty1 StandardInput=tty StandardOutput=tty User=someuser WorkingDirectory=/opt/software/ ExecStart=/opt/software/bin/start_soft # Always restart on exit, disable restart counter, delay a little bit # the restart to avoid spam in case of repeating error Restart=always StartLimitIntervalSec=0 RestartSec=5s
It only occured to me to have a look at how getty.service is configured, and
indeed it uses the same options:
StandardInput=tty StandardOutput=tty TTYPath=/dev/%I TTYReset=yes # reset $TTYPath before and after execution TTYVHangup=yes # disconnect all clients which have open $TTYPath TTYVTDisallocate=yes # deallocate before and after execution; this ensures screen and scrollback buffer is clear
A inconvenience is that if you start on tty1, then messages from systemd or
the kernel get mixed up with your program output. If you start on tty2, I
tried to add ExecStartPre=chvt 2, but the VT would switch back to tty1
depending on exact boot order.