[systemd-devel] [systemd-nspawn] nginx: [emerg] open() "/dev/stderr" failed (6: No such device or address)

Lennart Poettering lennart at poettering.net
Mon Apr 27 06:39:52 PDT 2015


On Sun, 26.04.15 14:32, Peter Paule (systemd-devel at fedux.org) wrote:

> BTW: I did the `echo "asdf" > /dev/stderr`-thing just to test if
> `/dev/stderr` worked as expected.

/dev/stderr does not work for socket fds, and that's a kernel
limitation, systemd can't do much bout it.

> What I do not understand is: What changed in systemd that the
> service-unit-thing worked in some earlier versions? 

We changed nspawn so that it may be included in shell
pipelines. Effectively this meant passing through the original
stdin/stdout that nspawn got all the way down to PID 1 inside the
container. We do so now if we are invoked non-interactively, i.e. with
stdin/stdout not being a tty.

Previously, we would never pass through fds, but always create a pty
inside the container and automatically forward all bytes of
stdin/stdout from outside the container to it and back. However, that
broke shell pipelines, since it ate up the independent EOF on stdin
and stdout: ptys cannot signal those individually (there's only a
hangup that terminates both directions at once), but that's a property
you inherently need for any kind of pipelines.

I am pretty sure that the new behaviour is a ton more correct though:
with this you get the same behaviour if you start a process
non-intractively as a service or inside an nspawn container, the same
fds, and hence the same (broken) /dev/stderr semantics.

> And what can I do to make it work again? There seems to be no other
> logging target _today_ both for nginx and apache which makes them
> compatible with journald.

Do not use /dev/stderr. If you are in a shell script replace this:

   echo foobar > /dev/stderr

with this

   echo foobar 1>&2

The latter will just duplicate stdin to stderr, the former will reopen
stdin as stderr. Which is a difference, though an non-obvious one,
that is further complicated that GNU bash (though not necessarily
other shells) actually automatically do the second command if you pass
it the first command. The first command does not work (in non-bash
shells..) if stdout is a socket, the second command does.

Lennart

-- 
Lennart Poettering, Red Hat


More information about the systemd-devel mailing list