Redirecting STDERR to file and screen, STDOUT only to file


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Redirecting STDERR to file and screen, STDOUT only to file
# 1  
Old 09-07-2012
Redirecting STDERR to file and screen, STDOUT only to file

I have to redirect STDERR messages both to screen and also capture the same in a file but STDOUT only to the same file.
I have searched in this formum for a solution, but something like
Code:
srcipt 3>&1 >&2 2>&3 3>&- | tee errs

doesn't work for me...

Has anyone an idea???

Last edited by vbe; 09-07-2012 at 09:53 AM..
# 2  
Old 09-07-2012
I never use this kind of redirection...

You might missing 1. not sure..
try this

Quote:
Originally Posted by thuranga
srcipt 3>&1 1>&2 2>&3 3>&- | tee errs
# 3  
Old 09-07-2012
Don't know if I understand your question correct, but this works I think:
Code:
script 2>&1 1> errs | tee errs

If no error, result is only in file "errs", if error result is both on screen and in file "errs".
# 4  
Old 09-07-2012
Quote:
Originally Posted by thuranga
I have to redirect STDERR messages both to screen and also capture the same in a file but STDOUT only to the same file.

Code:
srcipt 3>&1 >&2 2>&3 3>&- | tee errs

doesn't work for me...
Lets start with some general information to make the problem understandable:

A Unix process is like a (y-shaped) water hose: you fill something in (via <stdin>) and something comes out (via <stdout>) the one way and something else the other way (<stderr>). You can - to continue the analogy - put a bucket under each of the outlets, even the same bucket under several outlets, but they will still remain different outlets of data.

By default, when a process is born, its 3 default I/O-channels are directed to:

stdin: keyboard
stdout: display
stderr: display

As <stdout> and <stderr> are both pointing to display, why is it that

Code:
process_1 | process_2

picks up the output from <stdout> but not from <stderr>? The answer is that "|" is a special form of connector, not just another bucket like ">". "|" means: redirect <stdout> of process_1 to <stdin> of process_2.

Now there is another redirection device, which is:

Code:
process_1 2>&1

This means: redirect output channel 2 (=<stderr>) to where output channel 1 (=<stdout>) points to right now. All redirections are read and carried out from left to right.

Having understood this let us try to solve your problem:

Code:
script 2>&1

will redirect <stderr> to <stdout>, so the next "|" will catch <stderr> output now too. Closer!

Code:
script 2>&1 | tee -a /some/file

This will pick up everything coming out of <stderr> and <stdout> of script and display it as well as appending it to "/some/file". Closer again, but <stdout> should not be displayed, so we will have to direct it away before the pipe picks up its input:

Code:
script 2>&1 1>/some/file | tee -a /some/file

This finally does what we want: output to <stdout> is put into "/some/file", output to <stderr> is being displayed before being appended to /some/file" too.

The only uncertainty left is that i am not sure if the exact sequence of the messages will be preserved, especially if there is high load and many messages. You will have to try that. I'll be tankful if you could post a follow-up telling us this.

I hope this helps.

bakunin
This User Gave Thanks to bakunin For This Post:
# 5  
Old 09-07-2012
The y-shaped hose and bucket analogy paints a memorable image. Nicely done. The only thing I'd add, explicitly (it's implied in your explanation), is that pipe redirection occurs before other, left-to-right redirections.

Quote:
Originally Posted by bakunin
The only uncertainty left is that i am not sure if the exact sequence of the messages will be preserved...
Even without the pipe and redirections, you can't depend on your average script/executable to emit messages in the exact order that they're generated, since typically a mix of unbuffered (stderr) and buffered (stdout) streams are used.

Of much greater importance is that script 2>&1 1>/some/file | tee -a /some/file involves multiple processes writing to the same file without any form of communication. Writes from script will clobber writes from tee, or vice versa. If they at least shared a file descriptor, while one message could still split another in two, there would never be any overwriting.

Regards,
Alister

Last edited by alister; 09-07-2012 at 10:47 AM..
This User Gave Thanks to alister For This Post:
# 6  
Old 09-07-2012
Quote:
Originally Posted by alister
The y-shaped hose and bucket analogy paints a memorable image. Nicely done.
Thank you for this, as well as the additional info. I was not aware that <stderr> is unbuffered while <stdout> is not, so i have learned more here than i have explained. Nice gain. ;-))


It is probably a good idea to do like i have always done (out of luck - you have given me a reason after all) in my scripts: prepend standard and error output with respective prefixes:

Code:
#! /bin/ksh
...
print -u1 "MSG: $(timestamp) , starting the action"
action
if [ $? -gt 0 ] ; then
     print -u2 "ERR: $(timestamp) , action did not work"
else
     print -u1 "MSG: $(timestamp) , action worked out well"
fi
...

bakunin
# 7  
Old 09-07-2012
Bakunin, it appears that I was editing my previous post just as you were responding. I apologize for that incovenience.

Your suggestion won't work at all. As I mentioned in my post (probably after you read it but before you posted), script and tee will clobber each other since they're using file descriptors backed by independent file descriptions each with their own offset.



Quote:
Originally Posted by 244an
Don't know if I understand your question correct, but this works I think:
Code:
script 2>&1 1> errs | tee errs

If no error, result is only in file "errs", if error result is both on screen and in file "errs".
That will not work for the same reason as bakunin's suggestion.



Quote:
Originally Posted by thuranga
I have to redirect STDERR messages both to screen and also capture the same in a file but STDOUT only to the same file.
I have searched in this formum for a solution, but something like
Code:
srcipt 3>&1 >&2 2>&3 3>&- | tee errs

doesn't work for me...

Has anyone an idea???
That approach cannot be made to work because, from the tee-side of the pipe, the distinction between stdout and stderr has been lost; they've been merged into one stream.

The following should work:
Code:
{
    exec 3>&1    # Save the current stdout (the cat pipe)
    script 2>&1 1>&3 | tee -a /dev/tty
} | cat > logfile

That may look like a useless use of cat (Hi, Corona Smilie), but writing to a pipe guarantees atomicity for writes up to PIPE_BUF bytes inclusive.

If you rather not have that second pipe, you can simply delete highlighted text, leaving only the logfile redirection. However, if you do that, you may see interleaving of messages even for small writes.

Regards,
Alister
This User Gave Thanks to alister For This Post:
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Redirect STDOUT & STDERR to file and then on screen

Dear all, redirecting STDOUT & STDERR to file is quite simple, I'm currently using: Code: exec 1>>/tmp/tmp.log; exec 2>>/tmp/tmp.log But during script execution I would like the output come back again to screen, how to do that? Thanks Luc edit by bakunin: please use CODE-tags like the... (6 Replies)
Discussion started by: tmonk1
6 Replies

2. Shell Programming and Scripting

Lost redirecting stderr & stdout to 3 files - one each plus combined

Hi folks I need/want to redirect output (stdout, stderr) from an exec call to separate files. One for stderr only and two(!) different (!) ones for the combined output of stderr and stdout. After some research and testing i got this so far : (( exec ${command} ${command_parameters} 3>&1... (6 Replies)
Discussion started by: MDominok
6 Replies

3. Shell Programming and Scripting

Redirect STDOUT & STDERR to file and then on screen

Dear all, redirecting STDOUT & STDERR to file is quite simple, I'm currently using: exec 1>>/tmp/tmp.log; exec 2>>/tmp/tmp.logBut during script execution I would like the output come back again to screen, how to do that? Thanks Lucas (4 Replies)
Discussion started by: Lord Spectre
4 Replies

4. Programming

stderr stdout to a log file

I originally wrote my script using the korn shell and had to port it to bash on a another server. My script is working find for backing up but noticed that now after the move, I am not getting any output to my log files. Using Korn shell, this worked for me for some odd reason. This was sending... (2 Replies)
Discussion started by: metallica1973
2 Replies

5. Shell Programming and Scripting

Preserve output order when redirecting stdout and stderr

Hi, I already searched through the forum and tried to find a answer for my problem but I didn't found a full working solution, thats way I start this new thread and hope, some can help out. I wonder that I'm not able to find a working solution for the following scenario: Working in bash I... (8 Replies)
Discussion started by: Boemm
8 Replies

6. Shell Programming and Scripting

Redirect stdout/stderr to a file globally

Hi I am not if this is possible: is it possible in bach (or another shell) to redirect GLOBALLY the stdout/stderr channels to a file. So, if I have a script script.sh cmd1 cmd2 cmd3 I want all stdout/stderr goes to a file. I know I can do: ./script.sh 1>file 2>&1 OR ... (2 Replies)
Discussion started by: islegmar
2 Replies

7. Shell Programming and Scripting

sending stdout and stderr to a file

working on a c sell script I think I understand the concept of it, which is: filename >> file.txt (to appaend) or filename | tee -a file.txt (to append) The problem is that my shell script is used with several parameters, and these commands don't seem to work with just filename. They... (2 Replies)
Discussion started by: mistermojo
2 Replies

8. Shell Programming and Scripting

How to redirect stderr and stdout to a file

Hi friends I am facing one problem while redirecting the out of the stderr and stdout to a file let example my problem with a simple example I have a file (say test.sh)in which i run 2 command in the background ps -ef & ls & and now i am run this file and redirect the output to a file... (8 Replies)
Discussion started by: sushantnirwan
8 Replies

9. Shell Programming and Scripting

Redirecting STDERR message to STDOUT & file at same time

Friends I have to redirect STDERR messages both to screen and also capture the same in a file. 2 > &1 | tee file works but it also displays the non error messages to file, while i only need error messages. Can anyone help?? (10 Replies)
Discussion started by: vikashtulsiyan
10 Replies

10. Shell Programming and Scripting

redirecting STDOUT & STDERR

In bash, I need to send the STDOUT and STDERR from a command to one file, and then just STDERR to another file. Doing one or the other using redirects is easy, but trying to do both at once is a bit tricky. Anyone have any ideas? (9 Replies)
Discussion started by: jshinaman
9 Replies
Login or Register to Ask a Question