Confused about redirecting stderr


 
Thread Tools Search this Thread
Top Forums UNIX for Beginners Questions & Answers Confused about redirecting stderr
# 1  
Old 02-16-2019
Confused about redirecting stderr

I know that

Code:
mmmmm 2> error.txt

will send the error message to the specified file instead of the screen. However, I have seen

Code:
>&2

in some scripts, and I can't get it to do anything. A source said it sends stdout and stderr to a file. What file?


Ubuntu 18.04.2; Xfce 4.12.3; kernel 4.15.0-45-generic; bash 4.4.19(1); Dell Inspiron-518

Last edited by vbe; 02-16-2019 at 03:19 PM..
# 2  
Old 02-16-2019
Code:
mmmmm 2> error.txt >&2

will send both the stderr and stdout to the file error.txt
This User Gave Thanks to milhan For This Post:
# 3  
Old 02-16-2019
That's called (man bash)
Quote:
Duplicating File Descriptors
The redirection operator

[n]<&word

is used to duplicate input file descriptors. If word expands to one or more digits, the file descriptor denoted by n is made to be a copy of that file descriptor. If
the digits in word do not specify a file descriptor open for input, a redirection error occurs. If word evaluates to -, file descriptor n is closed. If n is not spec”
ified, the standard input (file descriptor 0) is used.

The operator

[n]>&word

is used similarly to duplicate output file descriptors. If n is not specified, the standard output (file descriptor 1) is used.
You need to be careful about the order of the redirections; done wrongly, the result might not what you expect (see man bash, again).
This User Gave Thanks to RudiC For This Post:
# 4  
Old 02-16-2019
A command sends either fd1 or fd2, correct? That's why neither history 2> test.txt nor hissory 1> test.txt work very well?
I'm still trying to understand the duplicating part of all this.
# 5  
Old 02-16-2019
Quote:
Originally Posted by Xubuntu56
A command sends either fd1 or fd2, correct? That's why neither history 2> test.txt nor hissory 1> test.txt work very well?
Not quite. Picture a UNIX process as a sort-of garden hose for data: you pour something in on the top and something rins out at the bottom. So far, it should be quite clear. Now, where the UNIX process differs from the garden hose is that it doesn't have only one outlet but several of them. So you pour something in above and something comes out on several places at the bottom.

The places where something gets in (=> input) or out (=>output) of the process are called "I/O descriptors" because such an I/O descriptor really is just a - very generalised - intake/outlet for data. To really get input or generate output the I/O-descriptor has to point to some place where the output can be either displayed or printed. Taking again the garden-hose analogy: the I/O-descriptors are just the openings in the hose. Without anything going in or out they are useless. So you have to connect something to the input (i.e. the water tap), only then the hose will do something. Equally if you do not point the bottom opening to something the water just spills out and is lost. If you point it to a bucket it can be collected in it and hence used.

The same is true for these I/O-descriptors: per default there are three of them: <stdin>, <stdout> and <stderr>. And also per default all are pointing to the terminal a process was started at. That means <stdin> is connected to the keyboard (the input device of the terminal) and the others are connected to the display (the output device of the terminal). Two things are worth mentioning: in principle it is possible to use any output descriptor for any kind of data but there is a convention (hence the name of these) that "normal data" goes to <stdout> and diagnostic messages go to <stderr>. Also, per default there are three such I/O-descriptors open: 0 is <stdin>, 1 is <stdout> and 2 is <stderr>. More (IIRC up to 9) you can create on purpose. For instance:

Code:
# ls -l /home /does/not/exist 
ls: cannot access '/does/not/exist': No such file or directory
/home:
total 20
drwx------  2 root    root    16384 Jul 22  2018 lost+found
drwxr-xr-x 42 bakunin bakunin  4096 Feb 17 00:55 bakunin

The line "cannot...." is a diagnostic message and went to <stderr>, the rest is normal output of the ls command. Either of these channels can be redirected to somewhere else - in this case to /dev/null, a file that just devours unwanted output:

Code:
# ls -l /home /does/not/exist >/dev/null
ls: cannot access '/does/not/exist': No such file or directory

# ls -l /home /does/not/exist 2>/dev/null
/home:
total 20
drwx------  2 root    root    16384 Jul 22  2018 lost+found
drwxr-xr-x 42 bakunin bakunin  4096 Feb 17 00:55 bakunin

# ls -l /home /does/not/exist >/dev/null 2>/dev/null

Do you see a pattern? When i wanted to redirect <stdout> (I/O-descriptor 1) i wrote:
Code:
# ls -l /home /does/not/exist >/dev/null

which is a shortcut for the equally correct:

Code:
# ls -l /home /does/not/exist 1>/dev/null

when i wanted to redirect <stderr> or I/O-descriptor 2 i wrote:
Code:
# ls -l /home /does/not/exist 2>/dev/null

Quote:
Originally Posted by Xubuntu56
I'm still trying to understand the duplicating part of all this.
Now, suppose i want to redirect both these output channels to the same place. I could write i.e.:

Code:
# ls -l /home /does/not/exist >/some/file 2>/some/file

But this might be prone to typos as i could write different filenames as they become longer and longer. Therefore i could also write:
Code:
# ls -l /home /does/not/exist >/some/file 2>&1

The first part you know already: > /some/file means redirect <stdout> to /some/file. The second part 2>&1 means redirect <stderr> to where <stdout already points (whereever that is).

You can redirect other output channels the same way. i.e. 4>&6 means: redirect I/O-descriptor 4 to where I/O-descriptor 6 is pointing at right now. These redirections are read from left to right. The respective output stream doesn't even have to transport any data to be redirected. It could be used to just "store" the redirection of another I/O-descriptor that is being redirected.

You can also give general redirections for complete code blocks with the exec command:

Code:
command1                # nothing redirected
exec 3>/some/file       # everything leaving via I/O-descriptor 3 is now landing in /some/file
command2
command3
exec 3>&-               # close this redirection
command4                # nothing redirected again

Suppose some I/O-descriptor is redirected to a location you do not know. You want to temporarily redirect it to somewhere else and then redirect it back to where it was. It is not possible to directly find out where it points at, but you can use another I/O-descriptor to "store" the location by letting it point to where this I/O-descriptor already points, then restore the other one back to that place. Watch I/O-descriptor 3 being manipulated in the example:

Code:
exec 9>&3
command 3>/some/place
exec 3>&9

I let 9 point to where 3 points at, then redirect 3 and finally redirect 3 to where 9 now points at, because that is where 3 has pointed to before.

Also notice that up to now we always used > for ou redirections. If the redirection is to a file this file will be deleted and then recreated that way. You might want to preserve what is in this file, though. Use >> instead in this case, then.

Here is a way to to make sure a file exists but is completely empty:

Code:
: >/some/file

: is the "null-command" and does (and outputs) nothing. Redirecting this to the file truncates it to zero or creates it with zero length if it doesn't exist already.

I hope this helps.

bakunin

Last edited by bakunin; 02-17-2019 at 07:54 AM..
These 2 Users Gave Thanks to bakunin For This Post:
# 6  
Old 02-17-2019
I think the following example makes more sense.
Code:
# Save the stderr destination in descriptor 9 then let stderr point to errorlog file
exec 9>&2 2>errorlog
command1
command2
# Restore stderr
exec 2>&9

The same can be achieved with a command group (code block)
Code:
#Group the following
{
command1
command2
# The group has stderr redirected to errorlog file
} 2>errorlog
# Outside the group the original stderr remains.

The
Code:
: >file

is most correct, while all shells also take
Code:
>file

.

Last edited by MadeInGermany; 02-17-2019 at 09:03 AM..
This User Gave Thanks to MadeInGermany For This Post:
# 7  
Old 02-17-2019
Wow! Thanks much. Smilie
I believe I found a use for >&2, uncommon though it may be: redirecting stdout to where stderr was previously redirected to.
Code:
{ ecko "Hello" || echo "World" } 2>error.txt >&2

resulting in
Code:
Command 'ecko' not found, did you mean:
  command 'echo' from deb coreutils
Try: sudo apt install <deb name>

World


Last edited by Xubuntu56; 02-17-2019 at 06:16 PM.. Reason: continued discussion
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. 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

2. 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

3. Shell Programming and Scripting

Is there a way to tee stderr from a command that's redirecting error to a file?

I'm not a complete novice at unix but I'm not all that advanced either. I'm hoping that someone with a little more knowledge than myself has the answer I'm looking for. I'm writing a wrapper script that will be passed user commands from the cron... Ex: ./mywrapper.sh "/usr/bin/ps -ef |... (1 Reply)
Discussion started by: sumgi
1 Replies

4. Shell Programming and Scripting

Redirecting STDERR to a file from within a bash script

I am trying to redirect the output from stderr to a log file from within a bash script. the script is to long to add 2> $logfile to the end of each command. I have been trying to do it with the command exec 2> $logfile This mostly works. Unfortunately, when a read command requires that anything be... (5 Replies)
Discussion started by: vockleya
5 Replies

5. Shell Programming and Scripting

noob question about redirecting stderr

I dont know what I am doing wrong but I would like to redirect the stderr output to a file? the specific command is this time wget http://www.something.com/somefile.bin All I want to see is time's output which is stderr so I can see how long the file download took. I've tried redirecting... (2 Replies)
Discussion started by: trey85stang
2 Replies

6. Shell Programming and Scripting

Redirecting stderr problem

% ls -ld /usr /foo ls: /foo: No such file or directory drwxr-xr-x 14 root wheel 512 May 18 02:49 /usr % ls -ld /usr /foo 1>/dev/null/ /dev/null/: Not a directory. % ls -ld /usr /foo 2>/dev/null/ /dev/null/: Not a directory. ^^Why why why doesn't this work for me. Furthermore, where is... (7 Replies)
Discussion started by: phpfreak
7 Replies

7. Shell Programming and Scripting

Confused about redirecting output from awk.

I have a simple script written in awk whose purpose is to go through some php files and replace some strings. Naturally, I want the changes to be written out to the files. The script looks generally as follows: { gsub(/'replacethis'/, "with this"); # a bunch of these print $0 > FILENAME }... (3 Replies)
Discussion started by: face1
3 Replies

8. 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

9. Shell Programming and Scripting

Redirecting stderr while live

If I forget to set up stderr redirection on execution of a script, is there a way to set that redirection post-exec? In other words, if I have a script running and no errors are being logged... and then I remember that I forgot the 2>&1 on the script... can I turn it on after the fact? ...and... (1 Reply)
Discussion started by: jjinno
1 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