chintaps
asked on
how to redirect standard error and output from a shell script to a file
Hi all,
by doing this:
script.sh 2>>output.txt
I am able to run the script and send the errors if any to output.txt but how can I send both the output and errors to output.txt by running the script only once.
Also how I can send errors+output to both screen and output.txt by running the script only once.
Thanks in advance
chintaps
by doing this:
script.sh 2>>output.txt
I am able to run the script and send the errors if any to output.txt but how can I send both the output and errors to output.txt by running the script only once.
Also how I can send errors+output to both screen and output.txt by running the script only once.
Thanks in advance
chintaps
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
with tee, the -a flag tells it to append rather than (Default) of clobber.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
manav_manthur, there was no mention in the question of not clobbering, but yes ">>" rather than ">" will append (I mentioned the "tee -a" option myself).
The question involved a statement like
<quote>
script.sh 2>>output.txt
</quote>
Just wanted to bring to notice that the solution above, unlike the command posted in the question itself, will clobber the files. If the author has no problems with this, its his call.
Cheers
Manav
<quote>
script.sh 2>>output.txt
</quote>
Just wanted to bring to notice that the solution above, unlike the command posted in the question itself, will clobber the files. If the author has no problems with this, its his call.
Cheers
Manav
fair enough...
actually, looking at the quote from the question it looks like its a CSH shell - is this correct author?
actually, looking at the quote from the question it looks like its a CSH shell - is this correct author?
> CSH shell
Isnt the format same for ksh,bash (any other shell) ??
Manav
Isnt the format same for ksh,bash (any other shell) ??
Manav
nope, AFAIK CSH is broken.... (in particular how it handles file descriptors is broken... a quick google on "csh considered harmful" gives http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/
a quick test highlights that the same format doesn't work:
% python -c "import sys; sys.stderr.write( 'hello ' ); print 'world'" >> /tmp/test1.txt 2>&1
csh: Ambiguous output redirect.
whereas in Bash:
$ python -c "import sys; sys.stderr.write( 'hello ' ); print 'world'" 2>&1 | tee /tmp/test3.txt
hello world
[]$ cat /tmp/test3.txt
hello world
[]$
a quick test highlights that the same format doesn't work:
% python -c "import sys; sys.stderr.write( 'hello ' ); print 'world'" >> /tmp/test1.txt 2>&1
csh: Ambiguous output redirect.
whereas in Bash:
$ python -c "import sys; sys.stderr.write( 'hello ' ); print 'world'" 2>&1 | tee /tmp/test3.txt
hello world
[]$ cat /tmp/test3.txt
hello world
[]$
beg your pardon......Im not able to understand what you are trying to say here.......
<quote>
by doing this:
script.sh 2>>output.txt
I am *able* to run the script ....
</quote>
a '>>' works fine on bash, ksh but not on csh(as you've just shown). And the author says that he *is* able to run th command that uses this form of redirection, he should not be on csh....or am I missing something here??
Manav
<quote>
by doing this:
script.sh 2>>output.txt
I am *able* to run the script ....
</quote>
a '>>' works fine on bash, ksh but not on csh(as you've just shown). And the author says that he *is* able to run th command that uses this form of redirection, he should not be on csh....or am I missing something here??
Manav
ASKER
its a Bourne shell! thanks for the answers guys!
Both these work:
script.sh >> output.txt 2>&1 ##will append all STDOUT/STDERR to output.txt
script.sh 2>&1 | tee -a output.txt ##will make all STDERR?STDOUT appear on screen and append to output.txtx
the difference is the return code from both! While 1 gives the same code(error if error in script) as a return code 2 actually gives it as true no matter what. So if I do a
if [ $? = 0 ];
after this line its a success always!!! is there a way around this?
Thanks
chintaps
Both these work:
script.sh >> output.txt 2>&1 ##will append all STDOUT/STDERR to output.txt
script.sh 2>&1 | tee -a output.txt ##will make all STDERR?STDOUT appear on screen and append to output.txtx
the difference is the return code from both! While 1 gives the same code(error if error in script) as a return code 2 actually gives it as true no matter what. So if I do a
if [ $? = 0 ];
after this line its a success always!!! is there a way around this?
Thanks
chintaps
The second command will give the return code of the tee command, not your script.....
Manav
Manav
an indirect method may be to touch a file if this succeeds, and check for the existence of the file...(thats what occurs to my bleak mind)
script.sh 2>&1 && touch /tmp/file1 | tee -a output.txt
if [ -a /tmp/file1 ]; then
#script.sh succeeded, do something to celebrate!!
rm /tmp/file1
script.sh 2>&1 && touch /tmp/file1 | tee -a output.txt
if [ -a /tmp/file1 ]; then
#script.sh succeeded, do something to celebrate!!
rm /tmp/file1
or should it be
{script.sh 2>&1 && touch /tmp/file1} | tee -a output.txt
{script.sh 2>&1 && touch /tmp/file1} | tee -a output.txt
There's an example of how to get return values from programs earlier in the pipe than the last one, on that URL regarding CSH being harmful...
to quote:
Consider the pipeline:
A | B | C
You want to know the status of C, well, that's easy: it's in $?, or
$status in csh. But if you want it from A, you're out of luck -- if
you're in the csh, that is. In the Bourne shell, you can get it, although
doing so is a bit tricky. Here's something I had to do where I ran dd's
stderr into a grep -v pipe to get rid of the records in/out noise, but had
to return the dd's exit status, not the grep's:
device=/dev/rmt8
dd_noise='^[0-9]+\+[0-9]+ records (in|out)$'
exec 3>&1
status=`((dd if=$device ibs=64k 2>&1 1>&3 3>&- 4>&-; echo $? >&4) |
egrep -v "$dd_noise" 1>&2 3>&- 4>&-) 4>&1`
exit $status;
--- End Quote
Making sense of this is a little painful...
for our simple example...
(I don't fully follow what is going on, but I got it to work relatively easily....
exec 3>&1
status=$( ((./script.sh 2>&1 1>&3 3>&- 4>&-; echo $?>&4) | tee /tmp/test.txt 1>&2 3>&- 4>&- ) 4>&1 )
echo $status
The return code gets extracted correctly, but the output mightn't be fully correct... too many angle brackets, and amersands!!!! I'm off home!!
to quote:
Consider the pipeline:
A | B | C
You want to know the status of C, well, that's easy: it's in $?, or
$status in csh. But if you want it from A, you're out of luck -- if
you're in the csh, that is. In the Bourne shell, you can get it, although
doing so is a bit tricky. Here's something I had to do where I ran dd's
stderr into a grep -v pipe to get rid of the records in/out noise, but had
to return the dd's exit status, not the grep's:
device=/dev/rmt8
dd_noise='^[0-9]+\+[0-9]+ records (in|out)$'
exec 3>&1
status=`((dd if=$device ibs=64k 2>&1 1>&3 3>&- 4>&-; echo $? >&4) |
egrep -v "$dd_noise" 1>&2 3>&- 4>&-) 4>&1`
exit $status;
--- End Quote
Making sense of this is a little painful...
for our simple example...
(I don't fully follow what is going on, but I got it to work relatively easily....
exec 3>&1
status=$( ((./script.sh 2>&1 1>&3 3>&- 4>&-; echo $?>&4) | tee /tmp/test.txt 1>&2 3>&- 4>&- ) 4>&1 )
echo $status
The return code gets extracted correctly, but the output mightn't be fully correct... too many angle brackets, and amersands!!!! I'm off home!!
ASKER
This works fine! thanks guys.
:-)
for Bourne Shell, KSH and Bash:
# redirect both to same output file
script.sh >output.txt 2>&1
# redirect separately
script.sh >output.txt 2> error.txt
# redirect stdout to null and save error
script.sh >/dev/null 2> error.txt