I have a service running which has a CLI connected to stdin. When I ssh
into the machine, I'd like to be able to send commands to the stdin of that service.
systemd.exec says that StandardInput=file:/path/to/file
is a thing and supports FIFOs. That sounds like the simplest method.
I've tried this in my ~/.config/systemd/user/foo.service
[Service]
ExecStartPre=mkfifo %t/foo.stdin
ExecStart=cat -
StandardInput=file:%t/foo.stdin
ExecStopPost=rm -f %t/foo.stdin
In this example, I expect that when I run the following, I'll see the output echo'd in the journal.
echo "hello" > /run/user/1000/foo.stdin
I have two problems with this:
foo.service: Failed to set up standard input: No such file or directory
. It appears thatStandardInput=
must exist beforeExecStartPre=
. Will I need to create a permanent pipe in a static location during installation or is there a work-around? If I make the file manually, and removeExecStartPre
/ExecStopPost
, then things work.- The first
echo "command"
is processed fine, but sends anEOF
and stdin closes. I wanted the stdin to remain open. The answer (exec 3> stdin
, ...,exec 3>&-
) seems to be to use bash FD redirection, but that isn't available in systemd.
ExecStart
to a shell script that will set up the pipe and chainload the real executable. But if I may challenge the framing, why not usencat
/netcat
and Unix sockets instead of pipes?netcat
to listen on a specific port, but I'd prefer the user to log-in (instead of listening to any traffic on that port port). I haven't usednetcat
with unix sockets.accept()
. That meansfoo.socket
needsAccept=yes
. But that means the socket will spawn one instance of the service per connection, then stop the service when the connection completes.