What's the difference between ">/dev/null 2>&1" and "2>/dev/null >&2" - linux

I have a question for redirection.
I always use anycommands > /dev/null 2>&1 when I need not any output. But I have never used anycommands 2> /dev/null >&2
Question: Which one is the best way to expect no outputs? What's the difference between anycommands > /dev/null 2>&1 and anycommands 2> /dev/null >&2

case#1:(echo stdout;echo stderr>&2) >/dev/null 2>&1
stdout(1) is replaced by an fd to /dev/null
stderr(2) descriptor is copied from &1 which now is an fd to /dev/null
result: no output at all
case#2:(echo stdout;echo stderr>&2) 2>&1 >/dev/null
stderr(2) descriptor is copied from &1 which is the default stdout
stdout(1) is replaced by an fd to /dev/null
result: stderr is empty, stdout not shown, stderr on stdout
case#3: (echo stdout; echo stderr >&2) 2> /dev/null >&2
same as case#1, stderr and stdout have switched roles

Effectively, the two are equivalent. cmd > /dev/null 2>&1 connects stdout of the command to /dev/null, and then connects stderr to the same file. cmd 2>/dev/null >&2 connects stderr to /dev/null, and then connects stdout to it. The only difference is in the order in which the two streams are associated with /dev/null, which has no bearing on the status of the command when it is run. In both cases, both streams are redirected to the bit bucket.

If you're using only BASH, use &> to redirect both stdout and stderr. That's the most compact, safe and simple solution.
Regarding your question, the first one is equivalent to &> (it redirects both stdout and stderr to /dev/null.
The second connects stderr to /dev/null and redirects stdout to the new stderr, so it's equivalent to as far as the output is concerned. Just the order of file descriptor operations is reversed.

Related

Write stderr and stdout to one file, but also write stderr to a separate file

I have a shell script whose stdout and stderr I want to write to a logfile. I know that this can be achieved via
sh script.sh >> both.log 2>&1
However, I also want to simultaneously write the stderr to a separate file, "error.log". Is this achievable?
You can use tee to duplicate output to two locations. Combine that with some tricky redirections, and...
script.sh 2>&1 >> both.log | tee -a both.log >> error.log
This redirects stderr to stdout, and then stdout to both.log. stderr remains, and is piped to tee, which copies it to both log files.
For this you need to first switch stdout and stderr, which requires an additional file descriptor:
sh script.sh 3>&2 2>&1 1>&3 3>&-
The last operator closes the auxiliary file descriptor.
After that you can use tee to duplicate the error stream (which is now on stdin) and append it to your error log:
sh script.sh 3>&2 2>&1 1>&3 3>&- | tee -a error.log
And after that you can then direct both stdin and stderr to your combined log:
(sh script.sh 3>&2 2>&1 1>&3 3>&- | tee -a error.log) >> both.log 2>&1
The parentheses around the command are important to capture the error stream of the whole command. Without them only the (empty) error stream of the tee command would be captured and the rest would still go to the terminal.
Note: this does not check wheater the file descriptor 3 was in use (open) before. In bash you can use this to choose a previously unused file descriptor and close it on the last redirection:
sh script.sh {tmpfd}>&2 2>&1 1>&${tmpfd}-

Redirecting stderr in csh

I'm executing a program that dumps crash report into STDERR from where I have to filter some necessary information. The problem is that I'm unable to redirect STDERR to STDOUT and PIPE it with grep
command 2>&1 >/dev/null | grep "^[^-]" >& /tmp/fl
Getting error: Ambiguous output redirect.
Same command works under bash terminal.
What should I change to make it work ?
csh is significantly more limited than bash when it comes to file redirection. In csh, you can redirect stdout with the usual > operator, you can redirect both stdout and stderr with the >& operator, you can pipe stdout and stderr with the |& operator, but there is no single operator to redirect stderr alone.
The usual workaround is to execute the command in a sub-shell, redirecting stdout in that sub-shell to whatever file you want (/dev/null in this case), and then use the |& operator to redirect stdout and stderr of the sub-shell to the next command in the main shell.
In your case, this means something like:
( command >/dev/null ) |& grep "^[^-]" >&/tmp/fl
Because stdout is redirected to /dev/null inside the sub-shell, the |& operator will end up acting as 2>&1 in bash - since stdout is discarded in the sub-shell, nothing written to stdout will ever reach the pipe.
If you dont mind mixing stdout and stderr into the pipe you can use
command |& grep "^[^-]" >& /tmp/fl
Otherwise you can do the hack:
(command >/dev/null) |& grep "^[^-]" >& /tmp/fl
which separates out stdout to null, then piping stdout and stderr just gives
stderr as content.

Confusion with the redirection of output to 2>&1?

I have checked couple of relevant posts regarding this in stackoverflow and other sources regarding the usage of 2>&1.
Unfortunately so far have not get my head around it completely.
I understand that 2 is the stderr and 1 is the stdout and we are combining with the 2>&1.
But my question is what is difference between:
1. mycommand > /dev/null
2. mycommand 2> /dev/null
3. mycommand > /dev/null 2>&1
I was thinking:
will redirect stdout and stderr to /dev/null
will redirect stderr to /dev/null
will redirect stdout and stderr to /dev/null
Relevant posts:
What does "/dev/null" mean at the end of shell commands)
i/o stream redirection on linux shell. how does the shell process a command with redirection?
What does “> /dev/null 2>&1″ mean? (http://www.xaprb.com/blog/2006/06/06/what-does-devnull-21-mean/)
See this:
mycommand > /dev/null
it will redirect channel 1 (which is stdout) of mycommand to /dev/null
mycommand 2> /dev/null
it will redirect channel 2 (which is stderr) to /dev/null
mycommand > /dev/null 2>&1
it will redirect channel 1 to /dev/null and then bind channel 2 (stderr) to channel 1 (stdout). Both will go into /dev/null
There is another one (just to complete)
mycommand 2>&1 > /dev/null
In this second case, I bind (the child's) stderr to stdout (of the
parent) and then I find the child's stdout to /dev/null. The result is
that you now get the child's stderr output on stdout and the stdout
goes to the file. This is useful for processing stderr in a pipe, for
example. (see this answer)
(errfile doesn't exist)
$ cat errfile
cat: 0652-050 Cannot open errfile.
$ cat errfile > /tmp/stream.out
cat: 0652-050 Cannot open errfile.
$ cat errfile > /tmp/stream.out 2>&1
$ cat /tmp/stream.out
cat: 0652-050 Cannot open errfile.
($ rm /tmp/stream.out)
$ cat errfile 2>&1 > /tmp/stream.out
cat: 0652-050 Cannot open errfile.
$ cat /tmp/stream.out
$
Order is thus important and 2>&1 1>out is different than 1>out 2>&1 due to stream redirection at shell interpretation. You shoud redirect in "reverse" order. stdout > final than source > stdout
Try these to get the differences:
echo "stderr" > /dev/fd/2 | >/dev/null
stderr
echo "stdout" > /dev/fd/1 | >/dev/null
both commands redirected to /dev/null but in first one we're writing to stderr which prints stderr but in second one it prints nothing
1: redirect STDOUT to /dev/null, you use default file descriptor in this case, e.g. command [default]> filename, the default file descriptor is STDOUT.
2: redirect STDERR to /dev/null
3: redirect STDOUT to /dev/null and redirect STDERROR to STDOUT, which means both STDOUT and STDERROR will be redirected to /dev/null
Hope the tips make you clear.
0, 1, 2...9 are file descriptors in bash. 0 stands for stdin, 1 stands for stdout, 2 stands for stderror. 3~9 is spare for any other temporary usage.
Any file descriptor can be redirected to other file descriptor or file by using operator > or >>(append).
Usage: >
Please reference to http://www.tldp.org/LDP/abs/html/io-redirection.html

What is the difference between ">" and "&>" in bash?

In bash we have 3 stream types:
0 (STDIN)
1 (STDOUT)
2 (STDERR)
So, while executing some program i can use these streams (e.g. i can redirect them from console to a file or smth like /dev/null, etc):
# only errors from STDERR will be shown, STDOUT will be moved to /dev/null
command > /dev/null
# only STDOUT will be shown, STDERR will be moved to /dev/null
command 2> /dev/null
I saw that some people write
command &> /dev/null
What is the difference between > and &> in bash?
what is the difference between ">" and "&>" in bash?
It's a bashism that redirects both stdout and stderr. It can also be achieved with the more portable:
command > file 2>&1

How to redirect the output of an application in background to /dev/null

I would like to redirect the output generated from a background application in Linux to /dev/null.
I am using kate text editor and it prints all the debug messages on the terminal which I would like to redirect to /dev/null.
Any idea how to do it ?
Thanks
You use:
yourcommand > /dev/null 2>&1
If it should run in the Background add an &
yourcommand > /dev/null 2>&1 &
>/dev/null 2>&1 means redirect stdout to /dev/null AND stderr to the place where stdout points at that time
If you want stderr to occur on console and only stdout going to /dev/null you can use:
yourcommand 2>&1 > /dev/null
In this case stderr is redirected to stdout (e.g. your console) and afterwards the original stdout is redirected to /dev/null
If the program should not terminate you can use:
nohup yourcommand &
Without any parameter all output lands in nohup.out
These will also redirect both:
yourcommand &> /dev/null
yourcommand >& /dev/null
though the bash manual says the first is preferred.

Resources