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
# 8  
Old 09-07-2012
I've seen valid uses of cat on a single file before, but this is the first valid use I've seen for no files. Interesting. Smilie This is, of course, assuming that these programs output lines atomically, but still.

I hadn't realized that files wouldn't necessarily be atomic, for that matter.
# 9  
Old 09-07-2012
Quote:
Originally Posted by alister
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

Uhm...
After a few tries:

Code:
$ { exec 3>&1; ls file none 2>&1 1>&3 | tee -a /dev/tty; } |cat >logfile
ls: impossibile accedere a none: File o directory non esistente

$ cat logfile
ls: impossibile accedere a nonefile
: File o directory non esistente

Smilie

BTW: reading the thread, at first I've been a bit confused about what you all mean with "script": a script or the command /usr/bin/script? LOL.
--
Bye
# 10  
Old 09-07-2012
Try ( ) instead of { } .
# 11  
Old 09-07-2012
Quote:
Originally Posted by Corona688
Try ( ) instead of { } .
It's the same: "Each command in a pipeline is executed as a separate process (i.e., in a subshell)". So you have a subshell even with { } | .... Smilie

However:

Code:
$ ( exec 3>&1; ls file none 2>&1 1>&3 | tee -a /dev/tty; ) |cat >logfile; cat logfile
ls: impossibile accedere a none: File o directory non esistente
ls: impossibile accedere a nonefile
: File o directory non esistente

--
Bye
# 12  
Old 09-07-2012
@alister:
Quote:
Originally Posted by alister
...
Code:
{
    exec 3>&1    # Save the current stdout (the cat pipe)
    script 2>&1 1>&3 | tee -a /dev/tty
} | cat > logfile

So from now on we can say "alister told us so" when we are using useless use of cat Smilie
No seriously, in my suggestion I was thinking either STDOUT or STDERR, and that was wrong (was testing with a simple command not a script). Now when I'm testing with a script that has output I see that output to STDOUT is overwriting some characters in STDERR in the resulting "logfile".

But in your suggestion, I don't understand what is happening, see comments:
Code:
{
    # ok, this is saving STDOUT to &3(?)
    exec 3>&1    # Save the current stdout (the cat pipe)
    # here STDOUT is set to &3 which is STDOUT that was saved above???
    # Why is that necessary?
    script 2>&1 1>&3 | tee -a /dev/tty
} | cat > logfile

# 13  
Old 09-07-2012
Quote:
Originally Posted by Lem
Uhm...
After a few tries:

Code:
$ { exec 3>&1; ls file none 2>&1 1>&3 | tee -a /dev/tty; } |cat >logfile
ls: impossibile accedere a none: File o directory non esistente

$ cat logfile
ls: impossibile accedere a nonefile
: File o directory non esistente

Smilie
Quote:
Originally Posted by Corona688
Try ( ) instead of { } .
Quote:
Originally Posted by Lem
It's the same

The blame for that behavior almost certainly lies with your ls implementation. Which ls are you using?

I can reproduce that behavior with GNU ls. I cannot reproduce it with busybox ls. A closer look using strace (I booted a Linux system just for this Smilie) confirmed my suspicions: GNU ls isn't even trying to write a line at a time.

This is how GNU ls and Busybox ls attempt to write an error message for a nonexistent file named idont:
Code:
# GNU ls
write(2, "ls: ", 4)
write(2, "cannot access idont", 19)
# In Lem's example, interleaving occurred here
write(2, ": No such file or directory", 27)
write(2, "\n", 1)

# Busybox ls
write(2, "ls: idont: No such file or directory\n", 37)

There is no way to fix or workaround that, short of fixing GNU ls (or whatever code it depends on for generating its error messages). Perhaps other ls implementations (and other utilities for that matter) suffer from that problem, but there's nothing that can be done about this at the shell level.

With that many writes for a single, relatively short error message, there's a good chance that another process will be given the chance to write to the shared pipe. Each write is still atomic, it's just the message that's broken.

Regards,
Alister

---------- Post updated at 04:31 PM ---------- Previous update was at 04:26 PM ----------

Quote:
Originally Posted by 244an
Code:
{
    # ok, this is saving STDOUT to &3(?)
    exec 3>&1    # Save the current stdout (the cat pipe)
    # here STDOUT is set to &3 which is STDOUT that was saved above???
    # Why is that necessary?
    script 2>&1 1>&3 | tee -a /dev/tty
} | cat > logfile

You need to save stdout at the time that it's pointing to the cat-pipe because, later, when the shell builds the script|tee pipeline and redirect's script's stdout to the tee-pipe, if not for fd 3, there would be no way to refer to the cat-pipe (which script needs so that its stdout can bypass tee).

Regards,
Alister

Last edited by alister; 09-07-2012 at 05:38 PM..
These 4 Users Gave Thanks to alister For This Post:
# 14  
Old 09-07-2012
Quote:
Originally Posted by alister
The blame for that behavior almost certainly lies with your ls implementation. Which ls are you using?

I can reproduce that behavior with GNU ls.
Yep, alister, my ls is ls (GNU coreutils) 8.5.

Just for the sake of curiosity, I was wondering whether we could try an ugly workaround (I know it's at least ugly): if GNU ls splits too much its error messages, what about a little pause between ls and tee?

It seems to work. Here below the count of "nonefile"s gives us the number of
broken logs:

Code:
$ for i in {1..1000}; do { exec 3>&1; ls file none 2>&1 1>&3 | tee -a /dev/null; } |grep nonefile; done |wc -l
56

so 56 broken logs out of 1000 tries, versus:

Code:
for i in {1..100}; do { exec 3>&1; ls file none 2>&1 1>&3 | { sleep 1; tee -a /dev/null; }; } |grep nonefile; done |wc -l
0

0 broken out of 100 tries.


BTW: of course, if one doesn't care at all about having all the errors at the beginning or at the end of the log, a solution is obvious:

Code:
command 2>&1 >logfile | tee -a error; cat error >>logfile

or
Code:
command 2>&1 >output | tee -a logfile; cat output >>logfile

But... ça va sans dire. Smilie
--
Bye
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