I have the following problem, I am working a script that creates a fifo device file, but I want to return true even if the file exists already. The following snippet is trying to create fifos from the || and /bin/true as well. How can I tell the mkfifo cmd that the last argument is X?

$ /usr/bin/mkfifo /dev/fifofile || /bin/true

Running this in a systemd service:

ExecStartPre=/usr/bin/mkfifo /dev/fifofile || /bin/true
Apr 29 08:39:40  mkfifo[27275]: /usr/bin/mkfifo: cannot create fifo '/dev/fifofile': File exists
Apr 29 08:39:40  mkfifo[27275]: /usr/bin/mkfifo: cannot create fifo '||': File exists
Apr 29 08:39:40  mkfifo[27275]: /usr/bin/mkfifo: cannot create fifo '/bin/true': File exists

Trying to change the ExecStartPre to ExecStartPre=(/usr/bin/mkfifo /dev/fifofile) || /bin/true gives the following error:

 Executable path is not absolute: (/usr/bin/mkfifo /dev/gpsfifo) || /bin/true
  • 1
    Just a comment to say that a named pipe is most definitely not a device file. Why are you creating it in /dev? Why don't you just rm -f fifo; mkfifo fifo? Also, why are you using absolute paths to standard utilities? – Kusalananda Apr 29 at 9:03
  • @Kusalananda because I want to emulate a serial port, but this is not the scope of this question – Mihai Apr 29 at 9:04
  • 1
    The correct way to ignore the exit status in systemd it to prefix the command with a -. – muru Apr 29 at 9:10
  • The correct way of emulating a serial port is openpty() or posix_openpt() which will give you a /dev/pts/xx device that actually acts like a serial port - you can do all the tcgetattr and tcsetattr things on it that you need to do on a real serial port. – Guntram Blohm Apr 29 at 20:15
ExecStartPre=/usr/bin/mkfifo /dev/fifofile || /bin/true

That's fine as a shell command line, but systemd doesn't run ExecStartPre commands and such through the shell. (I'm not sure if the paths of mkfifo and true are be needed)

The documentation says that:

Each command line is unquoted using the rules described in "Quoting" section in systemd.syntax(5). The first item becomes the command to execute, and the subsequent items the arguments.

This syntax is inspired by shell syntax, but only the meta-characters and expansions described in the following paragraphs are understood, and the expansion of variables is different. Specifically, redirection using "<", "<<", ">", and ">>", pipes using "|", running programs in the background using "&", and other elements of shell syntax are not supported.

But as quotes should work, you could be able to explicitly run a shell with something like

ExecStartPre=sh -c 'mkfifo /dev/fifofile || true'. 

That should not be necessary, however, since systemd has a special syntax for ignoring errors.

If the executable path is prefixed with "-", an exit code of the command normally considered a failure (i.e. non-zero exit status or abnormal exit due to signal) is recorded, but has no further effect and is considered equivalent to success.

So, just

ExecStartPre=-mkfifo /dev/fifofile

should do.

I'm not sure about the inevitable error message, though, as the note about redirections only mentions >, and not 2>. But you could also do this to remove the file first and then recreate it:

ExecStartPre=-rm -f /dev/fifofile
ExecStartPre=-mkfifo /dev/fifofile

Or maybe something like

ExecStartPre=-rm -f /dev/fifofile ; mkfifo /dev/fifofile

but I didn't test. Also that would of course nuke any other file with the same name.

If you want to guard against that, you could do something like this:

ExecStartPre=sh -c '[ -p /dev/fifofile ] || mkfifo /dev/fifofile'

That should quit silently if the pipe already exists, but would let mkfifo give an error if the file exists and isn't already a pipe.

There might also be a more "correct" place to put the fifo file.

  • Why the - prefix on rm? -f already makes it not error if /dev/fifofile doesn't exist. Although it would probably still error out if /dev/fifofile existed, but couldn't be deleted. Which would probably be a fine indication of something wonky going on (I'm not familiar enough with fifos to tell). – Jan Dorniak Apr 29 at 19:34

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.