Results 1 to 8 of 8
I have a short script for which I want it to either output to the terminal it's being run in ("standard out") or to a log file depending on the ...
- 03-18-2009 #1Just Joined!
- Join Date
- Mar 2009
- Posts
- 4
Standard Output for script
I have a short script for which I want it to either output to the terminal it's being run in ("standard out") or to a log file depending on the condition of a flag. If I call "report.sh" it should run (and output) in the terminal, if I call "report.sh -q" it should send its output to log files.
At the moment I am using getopts (Linux.com :: Parsing arguments for your shell script) to parse the flags so that if -q is specified the variable quiet=1 and I have a conditional statement for if [ "quiet" ] then OUT=$logfile, else OUT=$standardoutput. For each subsequent command I then direct its output towards $OUT.
My problem is that I don't know what to set $OUT to for when I want it "sent" to standard out, and also something is screaming at me that there should be a simpler way to do this. My script as it stands is below, any suggestions?
Code:#!/bin/bash # # This file generates reports on the status # of running jobs on various servers # # Location of log files OLD=$HOME/tmp/jobStatus.old NEW=$HOME/tmp/jobStatus.new # Parse arguments quiet= while getopts 'q' OPTION do case $OPTION in q) quiet=1 ;; ?) echo "Usage: $(basename $0) [-q for quiet output)]" >&2 exit 2 ;; esac done shift $(($OPTIND - 1)) # If quiet, setup log file output if [ "quiet" ]; then if [ -a $OLD ]; then rm $OLD ; fi if [ -a $NEW ]; then mv $NEW $OLD ; fi OUT=$NEW else OUT="??? - standard out" fi # Main body of script user=username servers=(server01 server02 server03) date +%d/%m/%y\ %R > $OUT for i in ${servers[@]}; do ssh -l $user ${i} "~/bin/running -c" >> $OUT done
- 03-18-2009 #2Just Joined!
- Join Date
- Oct 2004
- Posts
- 62
Hi,
I'm not an expert, but after many years, you learn something...
The outputs are two: the standard one (the screen) and the error output (normally it too using the screen).
The 1st is "automatically" directed to screen and you need no action except printing or echoing (if you use bash) the data you want.
The output of any program that accesses the screen can be redirected to a file and visualized
by a text or a graphic editor by the well known
As you see you don't have to modify the source of the command ls (probably a c program)...Code:executable (options) command_object > file_capturing_output for ex. ls -1 MyDir > myDir_FileList.txt
The same thing is valid also for logging.
The redirection captures also the error output. Such a thing is sometime annoying.
For example try to use find outside of the home...
In such a case I use the redirection of error to null...
In this way you don't see the annoying "access denied"...Code:find /usr -name "*xx*" 2>/dev/null
As a conclusion I would write a script with no options for output... you decide what you want
by running with or without redirection to a file or a log file.
Bye
- 03-19-2009 #3Just Joined!
- Join Date
- Mar 2009
- Posts
- 4
Thanks fiomba, I believe I understand what you are saying but I shall try to rephrase my question in response...
I would like my script either to output to the screen or to a log file. From what you are saying I would do this simply by calling the script by it's name or by appending "> logfile" after calling it which I understand. The complication is the management of the logfiles.
If I want the script to output to log files the idea is to maintain two files - the current output "jobStatus.new" and the previous output "jobStatus.old" which I will then subsequently examine with diff to determine any changes (I'm learning a bit of awk at the moment as well!). To do this I currently use the log management section to shuffle the log files, however I don't need to do this if I output to the screen.
I guess I could do something like...
...but it would be ideal if I could use $OUT for either screen or file output.Code:if [ "quiet" ]; then date +%d/%m/%y\ %R > $OUT for i in ${servers[@]}; do ssh -l $user ${i} "~/bin/running -c" >> $OUT done else date +%d/%m/%y\ %R for i in ${servers[@]}; do ssh -l $user ${i} "~/bin/running -c" done fi
- 03-30-2009 #4Linux Enthusiast
- Join Date
- Aug 2006
- Location
- Portsmouth, UK
- Posts
- 539
Maybe this previous post will help...
redirecting BASH script stdout/stderr from the script itself - LinuxQuestions.orgRHCE #100-015-395
Please don't PM me with questions as no reply may offend, that's what the forums are for.
- 03-30-2009 #5Linux Newbie
- Join Date
- Mar 2009
- Posts
- 228
The "standard out" is a device called /dev/stdout. So assign your variable to it:
Code:OUT=/dev/stdout
- 03-30-2009 #6Just Joined!
- Join Date
- Mar 2009
- Posts
- 4
Excellent, that's what I was looking for lomcevak - knew it had to be something simple. I've already tweaked the file now though however and gone with earlier suggestions of just sending output to file from calling the script.
Thanks all the same.
- 03-30-2009 #7Linux Enthusiast
- Join Date
- Aug 2006
- Location
- Portsmouth, UK
- Posts
- 539
Glad you've found what you wanted

I must admit that I do like colucix's solution from the earlier posting
As it gives you an easy way to output to either a log file, stdout or both depending on options passed to your script.Code:#!/bin/bash logfile=$$.log exec > $logfile 2>&1
RHCE #100-015-395
Please don't PM me with questions as no reply may offend, that's what the forums are for.
- 03-30-2009 #8Linux Newbie
- Join Date
- Mar 2009
- Posts
- 228
I like colucix's solution as well. Problem is I don't fully understand how the exec command works. I did figure out how to turn it off in the script if you wish as follows:
Code:logfile=$$.log exec 3>&1 exec > $logfile 2>&1 echo Hi1 exec 1>&3 3>&- echo Hi2


Reply With Quote