echo stderr and stdout to file from bash script variable - linux

I have a bash script and inside this bash script I have a JAVARESULT variable like this :
JAVARESULT=`java -cp ... parser_file $file $someextravar`
and what I want is to catch in a log file the stderr and stdout of this result variable.
echo "$JAVARESULT" > $LOG_FILE
but i get only the stdout not the stderr. I tried with :
echo "$JAVARESULT" &> $LOG_FILE
but I don't get the java errors in the log file .

In every Unix based system every process have at least three file descriptors open. As you know, file descriptors are identified by numbers. This three standard file descriptors are:
0 for stdin
1 for stdout
2 for stderr
What you want to do is redirect stderr to stdout, and then redirect stdout to a file. So, in your JAVARESULT variable you'll just have to append:
2>&1
What you're saying here is: redirect stderr (file descriptor 2) to stdout (file descriptor 1).

Try this:
echo "$JAVARESULT" > $LOG_FILE 2>&1

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}-

Get output on screen from linux command

I tried to get command output in a command but I could't get it. If I run manually, It return normal result in screen.
[root#mymachine ~]# dnsdist -e "topQueries()"
1 Rest 0 100.0%
I tried with dnsdist -e 'topQueries() 2>&1 1> /tmp/abc. But /tmp/abc still was empty.
I don't think screen command can resolve it.
Does anyone have any recommendations?
Addition information:
1 Rest 0 100.0%
is the result from topQueries(). '-e' mean execute a command in dnsdist. It works look like we access mysql then we call a sql statement.
As rkosegi commented, order is important. When you run:
examplecommand 2>&1 1> /tmp/abc
It takes the stderr output and sends it to where stdout is currently going and then sends stdout to the file.
You may want, instead:
examplecommand 1> /tmp/abc 2>&1
which sends stdout to the file, then sends stderr to where stdout is currently going, namely the file.
To have stderr and stdout both to te screen and in a file /tmp/abc you
can use tee.
$cat a.sh
echo "stderr" >&2
echo "stdout"
./a.sh 2>&1 | tee /tmp/abc
stderr
stdout
$ cat /tmp/abc
stderr
stdout

How can I send error output to both stdout and file in bash

If I use this
cmd 2>/var/error.log
Then my error goes to that file but then I can't see on screen.
Is there any way I can simultaneously show it on screen as well as send to file?
This will display both stdout and stderr on the terminal while only sending stderr to err.log:
cmd 2> >(tee err.log >&2)
>(...) is process substitution. (The space between the two consecutive > is essential.) This sends stderr and only stderr to the tee command.
The >&2 causes the error messages remain in stderr. This would be important, for example, if this line occurs inside some script whose stdin or stderr is being redirected. (Hat tip: Chepner.)
cmd 2>&1 | tee /tmp/error.log

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

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.

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

Resources