I have a systemd service that is a console application, meaning that it is controlled by sending commands to its stdin and it outputs information to sdout. How can I set up the systemd service so that I can connect to its stdin and give it commands at any point, then detach from this, and repeat when necessary?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
I can think of multiple ways to do this. Of course, each has its own caveats.
-
Probably the most straightforward approach would be to create a simple service with a dedicated tty, similar to this:
# /etc/systemd/system/systemd-interactive-simple-tty.service [Unit] Description=Example systemd interactive simple tty service After=getty.service [Service] # https://www.freedesktop.org/software/systemd/man/systemd.exec.html ExecStart=/usr/local/sbin/systemd-interactive.bash StandardInput=tty-force TTYVHangup=yes TTYPath=/dev/tty20 TTYReset=yes # https://www.freedesktop.org/software/systemd/man/systemd.service.html Type=simple RemainAfterExit=false Restart=always RestartSec=5s [Install] WantedBy=default.target
The following options will work with the above simple service:
-
conspy takes (remote) control of a text mode virtual console. This is probably your best bet (with the above tty service). It’s available via most extended package repositories and is simple to use, like this:
conspy 20 # hit ESC+ESC+ESC (3 times quickly, to exit)
-
chvt works similarly to
conspybut makes /dev/ttyN the foreground (local) terminal. It’s part of the kbd collection and is installed by default on virtually every modern Linux distribution. That’s why I thought it was worth a mention. The major caveat withchvtis that it requires you to use the attached keyboard, which is probably not what you want. For the above service example,chvtcould be used like this:chvt 20 # ALT+F1 to return to /dev/tty1
-
reptyr uses the
ptrace(2)system call to attach to a remote program (via it’s PID). This is a completely different approach thanconspy&chvt, but would work with the above service definition too.Just keep in mind that
reptyr, by itself, doesn’t really support ‘detaching’. Its termcap support isn’t very robust, either. Typically,reptyris used in conjunction with screen and/or tmux because they provide a more seamless way to ‘detach’; I findreptyris a great, niche tool to move existing PIDs into ascreensession ortmuxwindow or pane.That said; I put this option here, albeit last, because it’s still possible to use
reptyrwithoutscreenortmux. The major caveat is if you break out of the process (e.g ^C), rather than reptyr’ing it (again) to another tty/pty (via another shell). Sending a break to the process may cause it to abort and I’m sure you know the rest.Maybe that’s OK, especially if the process isn’t critical and the systemd service is configured to
Restart=alwaysas I’ve shown above. If the process ‘breaks’ then systemd will automatically restart it (another cool feature of systemd!). There are different values forRestart, too. YMMV.reptyris available via most extended package repositories and can be used, like this:reptyr $(systemctl status systemd-interactive-simple-tty.service | grep Main PID | awk '{print $3}') # or just reptyr <pid>
-
conspy takes (remote) control of a text mode virtual console. This is probably your best bet (with the above tty service). It’s available via most extended package repositories and is simple to use, like this:
-
Another (more complex [meaning there’s more that could fail]) approach would be to create a forking service using screen, similar to this:
# /etc/systemd/system/systemd-interactive-forking-screen.service [Unit] Description=Example systemd interactive forking screen service [Service] # https://www.freedesktop.org/software/systemd/man/systemd.exec.html ExecStartPre=-/usr/bin/screen -X -S ${SCREEN_TITLE} kill # [optional] prevent multiple screens with the same name ExecStart=/usr/bin/screen -dmS ${SCREEN_TITLE} -O -l /usr/bin/bash -c /usr/local/sbin/systemd-interactive.bash # https://www.freedesktop.org/software/systemd/man/systemd.service.html Type=forking Environment=SCREEN_TITLE=systemd-interactive RemainAfterExit=false Restart=always RestartSec=5s SuccessExitStatus=1 [Install] WantedBy=default.targetscreen is a full-screen window manager that multiplexes a physical terminal between several processes. It’s quite a bit more complex than anything listed in the first, simple option. Personally, I’ve been using screen for a long, long time and feel comfortable enough to trust it with most things. It’s an invaluable tool.
The primary advantage over the above is decent termcap support (though not as good as tmux’s). That just means that your backspace key, arrows, etc. will work better than with
conspyorreptyr.screenis available via most base package repositories, and can be used like this:screen -r systemd-interactive # CTRL-A+D to detach
-
A similar approach to forking screen would be to fork
tmux. The systemd service fortmuxis almost the same as it is forscreen. But, I’m not going to detail this because, well, it’s late & I’m tired. Yes, I usetmuxa lot more thanscreen(these days).In fact, I’m writing this in neovim pane in
tmuxright now. But, I’ve still usedscreenfor a lot longer. In my experience and opinion,tmuxis overkill for something like this. Suretmuxis newer, has more features, and is a MUCH better shell multiplexer thanscreenbut … it’s even more complex. Along with that extra complexity comes some additional instability.More important, to me at least, is that
tmuxcrashes more often than screen. I listed screen as #2 because, if it were me, for something like that I’d probably just use #1 withconspy. -
Depending on your program; named pipes … systemd services support them, too! i.e.
StandardInput=/path/to/named/pipe|
… and more.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0