[stdin / stdout] Strategies for redirecting outputs

Well.. let's say i need to write a pretty simple script.

In my script i have 2 variables which can have value of 0 or 1.

  • $VERBOSE
  • $LOG

I need to implement these cases:

  1. ($VERBOSE = 0 && $LOG = 0) => ONLY ERROR output (STDERR to console && STDOUT to /dev/null)
  2. ($VERBOSE = 1 && $LOG = 0) => VERBOSE output (ALL to console)
  3. ($VERBOSE = 0 && $LOG = 1) => LOG output (ALL to file.log)
  4. ($VERBOSE = 1 && $LOG = 1) => BOTH output (ALL to console && ALL to file.log)

For now i got to understand i can do the following to put EVERYTHING to a file

exec > file.log                                                                    
exec 2>&1

Sure it is a very known argument.. but i'd like to hear some opinion :wink:

Is this a homework assignment? Homework and coursework questions can only be posted in the Homework & Coursework forum under special homework rules.

If you did post homework in the main forums, please review the guidelines for posting homework and repost.

If you did not post homework, please explain the company you work for and the nature of the problem you are working on. And, tell us what operating system you're using, tell us what shell you're using, and tell us how redirecting STDIN (i.e. Standard Input) has anything to do with controlling where normal and diagnostic output should be written?

I apologize if this is not the right place for my question.

This is not a real job .. i'm developing this not for money, but only for personal study.
My intent was to ask for some opinion and see how different people approach this common situation.

For what concerns STDIN redirection... well it was my error :o
of course i meant STDOUT (just edited..)

If i should move / delete this post, just tell me and i will do.
Sorry again for misunderstanding the rules

Since this isn't a homework assignment, this is a perfectly reasonable forum for this question.

Have you looked at the man page for the logger utility on your system?

Do you really want output from your script to be physically directed to the console when you specify that the output should go to the console, or do you just want output you specified as going to the console to be sent to the script's standard output (so whoever invokes your script can redirect the output wherever they want it to go)?

If you want output to appear in two places, you should consider looking at the man page for the tee utility.

logfile=file.log
if [ $VERBOSE = 0 -a $LOG = 0 ] ; then
  exec 2>> /dev/null
elif [ $VERBOSE = 1 -a $LOG = 0 ] ; then
  :
elif [ $VERBOSE = 0 -a $LOG = 1 ] ; then
  >> $logfile 2>&1
else
  echo "output goes to $logfile"
  >> $logfile
fi

For the latter case to go to *both* file and console, you would need a pipe to tee for the following code, e.g. by means of enclosing the code with { } :

{
# block starts, see redirection at the end
: code
# redirect this block to
} 2>&1 | tee -a $logfile

My take on this is to first lay down some rules:

1) I do not want to interfere with normal redirection, i.e. if i enter the command:

# myscript.sh > /some/log

I expect the script not to "overrule" this and put the output to stdout somewhere else than /some/log . It might write it somewhere else too, but finally whatever the output is should go to the file i specified. Analogous for stderr

2) I would like to encapsulate this whole functionality as much as possible. It would be OK to call some_function instead of, say echo , but i would try the utmost to avoid to "decorate" every single output-statement like this:

if [ $VERBOSE -eq 0 ] ; then
    if [ $LOG -eq 0 ] ; then
       .....
    else
       .....
    fi
else
     if [ $LOG -eq 0 ] ; then
       .....
    else
       .....
    fi
fi

3) If i already go through the trouble of writing a wrapper function for my output i could as well automatically add more than the "naked" output i send as an argument: a timestamp, maybe the process number, name of the calling function or similar information might come in handy when trying to figure out why a script has failed and what exactly has and has not done. If i write in a script:

....
if do_something ; then
     out_function "successfully executed the something step"
else
     out_function "executing the something step FAILED"
fi

I would like to see exactly this at the screen output (or the file i redirected it at) but maybe something like:

1.1.2017 00:10 (123456) ERROR: executing the something step FAILED

where (123456) is the process number of the script this was part of.

Having said all this i don't want to spoil your fun of writing such a function, so i will stop here. Post your production once you have it and i will be glad to discuss it with you. In fact i have written (and used) exactly such a function(-set) in my scripts for years, so kudos for your insight to feel the necessity for such a thing.

I hope this helps.

bakunin