Lua run as user service cannot find /dev/stderr

71 views
Skip to first unread message

Stefano Cossu

unread,
Sep 17, 2025, 4:53:52 PM (10 days ago) Sep 17
to lua-l
Hi there,
I am creating a user service in Linux/systemd that runs a script using
the Lua 5.4 interpreter. The script is directing output to /dev/stderr:

$ cat ~/src/echo.lua
io.output("/dev/stderr")
while true do
io.write("Very interesting message\n"):flush()
require "socket".select(nil, nil, 3) -- sleep 3s
end

When I run the script from the user shell, it behaves as expected,
looping through very interesting messages in standard error.

Then, I set up a user service:

$ cat ~/.config/systemd/user/echo.service
[Unit]
Description=Toy echo daemon

[Service]
ExecStart=/usr/bin/lua "${HOME}/src/echo.lua"

[Install]
WantedBy=default.target

And if I try to start the service, I get the following error in my journal:

/usr/bin/lua: /srv/app/src/echo.lua:1: cannot open file '/dev/stderr'
(No such device or address)
stack traceback:
[C]: in function 'io.output'
/srv/app/src/echo.lua:1: in main chunk
[C]: in ?

How's that the interpreter can't find /dev/stderr when run in systemd?

Thanks.
OpenPGP_0x1716A1B35E826596.asc
OpenPGP_signature.asc

Sainan

unread,
Sep 17, 2025, 5:03:09 PM (10 days ago) Sep 17
to lu...@googlegroups.com
Lua by default should already have a handle to stderr, which you can access with `io.stderr`, e.g. `io.output(io.stderr)`. In cases where exclusive access is expected, this might help?

-- Sainan

Dmitry Meyer

unread,
Sep 18, 2025, 3:21:39 AM (9 days ago) Sep 18
to lu...@googlegroups.com
On 2025-09-17 20:53, 'Stefano Cossu' via lua-l wrote:

> How's that the interpreter can't find /dev/stderr when run in systemd?
Check the systemd documentation:
https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html

> StandardOutput=
> [...]
> Also note that, in this case, stdout (or stderr, see below) will be
an > AF_UNIX stream socket, and not a pipe or FIFO that can be reopened.
> This means when executing shell scripts the construct echo "hello" >
/> dev/stderr for writing text to stderr will not work. To mitigate this
> use the construct echo "hello" >&2 instead, which is mostly
equivalent > and avoids this pitfall.

mjmouse9999

unread,
Sep 18, 2025, 5:04:40 AM (9 days ago) Sep 18
to lua-l
You should be able to use `io.output(io.stderr)`, which just uses the existing handle.

Also, luasocket does include a sleep function already, so that could be instead `require 'socket'.sleep(3)`.

Gé Weijers

unread,
Sep 18, 2025, 10:04:20 AM (9 days ago) Sep 18
to lu...@googlegroups.com
On Wed, Sep 17, 2025 at 10:53 PM 'Stefano Cossu' via lua-l <lu...@googlegroups.com> wrote:

How's that the interpreter can't find /dev/stderr when run in systemd?

/dev/stderr is a symbolic link to /proc/self/fd/2, which is a symbolic link again pointing to your terminal when you run from the command line. If the Lua process running as a service does not have file descriptor 2 /proc/self/fd/2 does not exist and /dev/stderr points to a non-existing file.

Try the following commands to see how this works:

ls -l /proc/self/fd/2
ls -l /proc/self/fd/2 2>/dev/null
ls -l /proc/self/fd/2 2>somefile

/proc/self/fd/2 will be a symbolic link to whatever you redirected stderr to.

You probably have to dig into systemd documentation to find out which file descriptors are opened by systemd before it starts your service. Maybe none?


--

Stefano

unread,
Sep 19, 2025, 8:13:08 AM (8 days ago) Sep 19
to lua-l
Thanks for the suggestions. io.output(io.stderr) works as expected and looks like is much more portable that /dev/stderr. 
Reply all
Reply to author
Forward
0 new messages