16

In scripts, errors are usually sent to file descriptor 2 with &2, ie:

echo "error" >&2

Sometimes /dev/stderr is used instead:

echo "error" > /dev/stderr 

Looking at /dev/stderr, I see that it is only a symlink to /proc/self/fd/2 , which in turn is a symlink to /dev/pts/5 (on my current terminal).

Seems little bit over complicated. Is there some logic behind that ?

Is using /dev/stderr and &2 equivalent ?

Is any of those preferred over the other ?

cat
  • 3,468
  • 4
  • 23
  • 51
Martin Vegter
  • 358
  • 75
  • 236
  • 411

3 Answers3

15

The special device /dev/stderr is system-specific, while the file descriptor 2 (not the special device /proc/self/fd/2) is portable. If you want to write non-portable code, those special devices are a good place to start.

There are a few systems with /dev/stderr: Linux, of course, and OSX. But OSX has no /proc filesystem, and its /dev/stderr is a link to /dev/fd/2.

Further reading:

Thomas Dickey
  • 76,765
  • Also there's the case where someone wants to do eg. this 2> bla.log which would work as long as you pipe to 2 and not hard-code /dev/stderr. Basically 2 doesn't need to be the stderr output. – ljrk Apr 04 '16 at 08:50
  • Moreover: on linux, write to &2 works for every user; write to /dev/stderr works only for root users. – Massimo Sep 16 '22 at 14:20
  • On MacOS, Debian and Fedora, each of the devices is owned by the current user, group tty with permissions 620 (making it writable by the user). – Thomas Dickey Sep 16 '22 at 20:43
8

In bash, and other shells, the way to redirect something to standard error is to use >&2. Bash opens /dev/stderr as the file descriptor 2. File descriptors are referenced by &N where N is the number of the descriptor. So, echo error >&2 will print error to standard error, to /dev/stderr.

It will also open /dev/stdout as file descriptor 1. This means you can do echo output >&1. However, since everything is printed to standard output anyway by default, that is the same as echo output by itself.

Now, 2> is different. Here, you are redirecting the error output of a command somewhere else. So, 2>file means "redirect anything printed to file descriptor 2 (standard error) to file".

erik258
  • 343
  • 1
  • 7
terdon
  • 242,166
3

You're right, >&2 is more direct and perfectly "idiomatic". They should be equivalent, so there's no particular reason to use >/dev/stderr. Except that, if someone reading doesn't know what these do, one of them is probably easier to find out than the other :-). But in general I'd suggest you use >&2.

/dev/stderr could be useful when programs will write errors to a specified filename, but don't support stderr. Clearly this is a bit contrived; /dev/stdout is much more useful. (I recently found the mysql_safe wrapper script won't write errors to the console; unfortunately it also wants to change the permissions on the error log file, so using /dev/stderr causes a few superfluous warnings).

sourcejedi
  • 50,249