bash: /dev/stderr: Permission denied
I don't think this is entirely a bash issue.
In a comment, you said that you saw this error after doing
sudo su username2
when logged in as username
. It's the su
that's triggering the problem.
/dev/stdout
is a symlink to /proc/self/fd/1
, which is a symlink to, for example, /dev/pts/1
. /dev/pts/1
, which is a pseudoterminal, is owned by, and writable by, username
; that ownership was granted when username
logged in. When you sudo su username2
, the ownership of /dev/pts/1
doesn't change, and username2
doesn't have write permission.
I'd argue that this is a bug. /dev/stdout
should be, in effect, an alias for the standard output stream, but here we see a situation where echo hello
works but echo hello > /dev/stdout
fails.
One workaround would be to make username2
a member of group tty
, but that would give username2
permission to write to any tty, which is probably undesirable.
Another workaround would be to login to the username2
account rather than using su
, so that /dev/stdout
points to a newly allocated pseudoterminal owned by username2
. This might not be practical.
Another workaround would be to modify your scripts so they don't refer to /dev/stdout
and /dev/stderr
; for example, replace this:
echo OUT > /dev/stdout
echo ERR > /dev/stderr
by this:
echo OUT
echo ERR 1>&2
I see this on my own system, Ubuntu 12.04, with bash 4.2.24 -- even though the bash document (info bash
) on my system says that /dev/stdout
and /dev/stderr
are treated specially when used in redirections. But even if bash doesn't treat those names specially, they should still act as equivalents for the standard I/O streams. (POSIX doesn't mention /dev/std{in,out,err}
, so it may be difficult to argue that this is a bug.)
Looking at old versions of bash, the documentation implies that /dev/stdout
et al are treated specially whether the files exist or not. The feature was introduced in bash 2.04, and the NEWS
file for that version says:
The redirection code now handles several filenames specially: /dev/fd/N, /dev/stdin, /dev/stdout, and /dev/stderr, whether or not they are present in the file system.
But if you examine the source code (redir.c
), you'll see that that special handling is enabled only if the symbol HAVE_DEV_STDIN
is defined (this is determined when bash is built from source).
As far as I can tell, no released version of bash has made the special handling of /dev/stdout
et al unconditional -- unless some distribution has patched it.
So another workaround (which I haven't tried) would be to grab the bash sources, modify redir.c
to make the special /dev/*
handling unconditional, and use your rebuilt version rather than the one that came with your system. This is probably overkill, though.
SUMMARY :
Your OS, like mine, is not handling the ownership and permissions of /dev/stdout
and /dev/stderr
correctly. bash supposedly treats these names specially in redirections, but in fact it does so only if the files don't exist. That wouldn't matter if /dev/stdout
and /dev/stderr
worked correctly. This problem only shows up when you su
to another account or do something similar; if you simply login to an account, the permissions are correct.