Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have this simple script which redirects the output and append it to a file.

filename="/home/ronnie/tmp/hello"

date=$(date)
echo "$date" >> $filename

Now, lets suppose I change date=$(date) to date= $(date) which will generate an error.

My modified script:

filename="/home/ronnie/tmp/hello"

date= $(date)
echo "$date" >> $filename 2>> $filename 
#Also tried echo "$date" >> $filename 2>&1

I was thinking that above script will redirect the error test.sh: line 5: Fri: command not found to the file hello but it just enters a new line into the file and the error gets printed on my stdout.

My bash version:

ronnier@ronnie:~/tmp$ bash --version
GNU bash, version 4.2.24(1)-release (i686-pc-linux-gnu)

So, where am I going wrong.

share|improve this question
add comment

2 Answers

up vote 5 down vote accepted

The line which causes the error is date =$(date), that error is sent to stderr. At that stage, you're not redirecting stderr anywhere. The subsequent line sends stderr to $filename, but it's not that line which causes the error.

One of the ways to get the effect you want, you would run your script and direct stderr to somewhere else at the same time, so,

./myscript 2>> errors.txt

at that point, errors.txt will contain your error.

So the issue is, the line generating the error is an error in the script itself, not an error caused by an external command the script calls which has it's output redirected. i.e. it's the top level script output you need to redirect.

share|improve this answer
    
Thanks for the explanation. –  ronnie Oct 19 '12 at 12:33
1  
Another strategy would be to surround several lines in your script with {...} 2>> errors.txt or (...) 2>> errors.txt. The second is less efficient but behaves in ways that are useful in certain circumstances. (Read about "subshells" to learn more.) –  dubiousjim Oct 19 '12 at 14:20
add comment

The shell emits an error message when it reaches line 5. The shell's error stream is not redirected at this point.

If you write date= $(date) 2>/dev/null, the “command not found” message comes from the shell, not from the command whose error stream is redirected. Therefore you'll still see the error message.

To avoid seeing the error message, put the whole command inside a group and redirect the error stream from the whole group:

{ date= $(date); } 2>/dev/null

With braces, the command is still executed in the parent shell, so it can change its environment and other state (not that it does here). You can also put the command in a function body, or in a subshell (commands inside parentheses, which are executed in a separate shell process).

You can redirect the file descriptors of the shell permanently (or at least until the next time you change them) by using a redirection on the exec builtin with no command name.

exec 2>/dev/null
# From this point on, all error messages are lost
date= $(date)
…
exec 2>/some/log/file
# From this point on, all error messages go to the specified file
share|improve this answer
    
Thanks for suggesting the alternatives. What is {} called in bash. I am aware of <() and $() process and command substitution respectively but not of {}. –  ronnie Oct 20 '12 at 6:54
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.