3

My user does not have write permissions for STDERR:

user@host:~> readlink -e /dev/stderr
/dev/pts/19
user@host:~> ls -l /dev/pts/19
crw--w---- 1 sysuser tty 136, 19 Apr 26 14:02 /dev/pts/19

It is generally not a big issue,

echo > /dev/stderr

fails with

-bash: /dev/stderr: Permission denied

but usual redirection like

echo >&2

works alright.

However I now need to cope with a 3rd-party binary which only provides logging output to a specified file:

./utility --log-file=output.log

I would like to see the logging output directly in STDERR.

I cannot do it the easy way like --log-file=/dev/stderr due to missing write permissions. On other systems where the write permissions are set this works alright.

Furthermore, I also need to parse output of the process to STDOUT, therefore I cannot simply send log to STDOUT and then redirect to STDERR with >&2. I tried to use the script utility (where the redirection to /dev/stderr works properly) but it merges STDOUT and STDERR together as well.

Blaf
  • 2,050
  • 1
  • 11
  • 14
  • What is the shell's stderr connected to such that it works? – Etan Reisner Apr 26 '16 at 14:42
  • 1
    Why is your stderr such that you cannot write to it? That's unusual — not impossible, but unusual. – Jonathan Leffler Apr 26 '16 at 14:44
  • Agreeing with Jonathan, I can `echo > /dev/stderr` all day – SaintHax Apr 26 '16 at 14:48
  • What is &2 pointing to? – 123 Apr 26 '16 at 14:48
  • Can you use `/dev/fd/2` as the file name instead? – Jonathan Leffler Apr 26 '16 at 15:07
  • @123: the notation `>&2` indicates that standard output should be sent to standard error; it isn't the name of a file per se. – Jonathan Leffler Apr 26 '16 at 15:08
  • @Jonathan - I have `/dev/stderr` -> `/proc/self/fd/2` -> `/dev/pts/19` and `/dev/fd/2` -> `/dev/pts/19`, so if it's the same for the asker, then that's no help. – Toby Speight Apr 26 '16 at 15:16
  • Just replace stdout with stderr here http://stackoverflow.com/questions/7756609/pass-stdout-as-file-name-for-command-line-util-answer-use-named-pipes – Mort Apr 26 '16 at 15:18
  • @TobySpeight: that sounds plausible, which is one reason my suggestion wasn't an answer. – Jonathan Leffler Apr 26 '16 at 15:19
  • @JonathanLeffler It's a file descriptor, it points to a file otherwise known as /proc/self/fd/2. – 123 Apr 27 '16 at 07:13
  • 1
    @Mort: The option with named pipes was the one I originally went for but it has many problems: you cannot view the output real-time (unless you start a background `cat`) and you need to care for the cleanup afterwards. Too much complexity for such a small thing. Answer from @toby-speight does the same but in a very neat manner. – Blaf Apr 27 '16 at 07:42

1 Answers1

4

You can use a Bash process substitution:

./utility --log-file=>(cat>&2)

The substitution will appear to the utility like --log-file=/dev/fd/63, which can be opened. The cat process inherits fd 2 without needing to open it, so it can do the forwarding.

I tested the above using chmod -w /dev/stderr and dd if=/etc/issue of=/dev/stderr. That fails, but changing to dd if=/etc/issue of=>(cat>&2) succeeds.

Note that your error output may suffer more buffering than you would necessarily want/expect, and will not be synchronous with your shell prompt. In other words, your prompt may appear mixed in with error output that arrives at your terminal after utility has completed. The dd example will likely demonstrate this. You may want to append ;wait after the command to ensure that the cat has finished before your PS1 prompt appears: ./utility --log-file=>(cat>&2); wait

Toby Speight
  • 27,591
  • 48
  • 66
  • 103