3

This is a task that I try to do pretty often. I want to log both stderr and stdout to a log file. But I only want to print to console stderr.

I've tried with tee, but once I've merge stderr and stdout using "2>&1". I can not print stdout to the screen anymore since both my pipes are merged.

Here is a simple example of what I tried

./dosomething.sh | tee -a log 2>&1. Now I have both stderr and stdout to the log and the screen.

Any Ideas?

Based on some reading on this web site, this question has been asked. Write STDOUT & STDERR to a logfile, also write STDERR to screen

And also a question very similar here: Save stdout, stderr and stdout+stderr synchronously

But neither of them are able to redirect both stdout+stderr to a log and stderr to the screen while stdoud and stderr are synchronously written to the log file.

Community
  • 1
  • 1
Damien
  • 1,944
  • 2
  • 18
  • 21

2 Answers2

5

I was able to get this working in bash:

(./tmp.sh 2> >(tee >(cat >&2) >&1)) > tmp.log

This does not work correctly in zsh (the prompt does not wait for the process to exit), and does not work at all in dash. A more portable solution may be to write a simple C program to do it.

Random832
  • 37,415
  • 3
  • 44
  • 63
  • I think `dash` and other simple, POSIX-like shells can't express this at all. +1, seems to work. – Fred Foo Apr 21 '11 at 14:22
  • When I use this I need to press enter to get back to prompt. Typing a command and then enter runs that command. Any way to avoid this? – neildeadman Jun 28 '11 at 09:44
1

I managed to get this working with this script in bash.

mkfifo stdout 
mkfifo stderr 

rm -f out 
cat stderr | tee -a out & 
cat stdout >> out & 
(echo "stdout";  
 grep;  
 echo "an other stdout";  
 echo "again stdout";  
 stat) 2> stderr > stdout 

rm -f stdout 
rm -f stderr

The order of the output is preserved. With this script the process ends correctly.

Note: I used grep and stat without parameter to generate stdout.

Lynch
  • 9,174
  • 2
  • 23
  • 34
  • The accepted solution (from Random832) does get executed in the background. See here the command does not print in the rigth order. $ echo line; ((echo line2; grep) 2> >(tee >(cat >&2) >&1)) > tmp.log; echo line3 line line3 $ Usage: grep [OPTION]... PATTERN [FILE]... Try `grep --help' for more information. – Lynch Apr 23 '11 at 16:29