Bash Wrapper Script
If you have evern wanted to customize the way that bash handles each command
Recently I was tasked to write a couple of bash scripts that I could not capture the output from in a normal fashion. ( Ie piping to another command for cleanup or redirecting to a file ) Also if I need to capture the output or details of each command run in a script, then my script could look ulgy and become horribly difficult to maintain.
Bash Wrapper Script – Details
Writing the bash wrapper function
The first step in setting up a wrapper function is to decide what you want to happen for each command For our example we would like to simple output the Command on one line with a description then output the arguments on a separate line. Once we have done that we are going to call the function and store the result in a variable as well as store the commands numeric return code. After all is said and done we should have a method to call for every line in a script potentially.
To make a function in Bash, we simply need to use the keyword function followed by the function name followed by an opening curly brace, the function definition and finally the closing brace:
function ExecWrap {
# do not forget space between brace
# function definition goes here.
}
Step 1: ( Obtaining the arguments )
* Bash arguments to a function are similar to the function arguments to the bash script themselves which can be accessed numerically or via a special glob variable denoted with the ‘@’ symbol:
# $@ - all arguments
# $1 - first argument
# $2 - second argument
# *** To grab the first argument and echo it to the console will be as simple as using the echo command:
echo "Command: $1";
# *** To grab the remaining argument will require a little more work:
array=(`echo $@`) # copy the glob array into a new array
array=(${array[@]:1}); # extract only the last part of the array or shift.
echo "Parameters: ${array[*]}" # echo the array to the console
Step 2: ( Calling the Command and saving the result )
* When we enclose a command using the backtick operator ‘`’ we can store the output of a command into a variable:
RESULT=`echo "test"` # store the word test into the RESULT variable
# *** Redirecting the output of stderr and stdout to file as well as to the console ( stdout )
ERRLOG=errlog # setup our strerror log
SITELOG=sitelog # setup our stdout log
TEE=tee # setup a program to write to console as well as to file
RESULT=`echo "test" 2>>$ERRLOG | $TEE -a $SITELOG
NOTE: the pipe ‘|’ operator takes the output of a command and sets it as the input to another command using a pipe.
NOTE: the 2>> redirect takes the 2nd file descripter and redirects that to a file
NOTE: the $ERRLOG, $TEE, $SITELOG gets replaced with our variable contents
Step 3:( Output and handling )
Now that we have called the function and retained most of the information how are we going to output the results?
echo "Result: $? : $RESULT" ; # output return code of last command and output
It is also quite possible to use the return code of the last command to exit or proceed by using the following one line script.
if [ "$?" != "0" ]; then exit ; fi
Step 4: ( Reading the script )
Now that we have a wrapper function, lets figure out a way to read a script into bash. If you google bash read a file you may come up with a similar script to the following:
while read line
do
echo $line;
done < file
This will basically read a line from file until the file end has been reached.
We are going to us a slight variation on this and wrap it in a function:
function ReadFile { # do not forget space between brace
while read line
do
WrapExec $line ; # Call our exec routine
done # read from stdinput
}
Step 5: ( Writing the script to run )
The final stage to our script is to write the script we want to perform and pipe it to the read script. We can do this with the heredoc format. Heredoc allows us to use the contents of the file we are actually writing/reading as the file we want to perform an action on. The syntac is something like this:
cat << EOF
# line 1 of script
# line 2 of script
# ...
EOF # this is the end of the script
For our purposes we are going to call our Reading script to read all of the lines and call our wrapper function with.
ReadFile << EOF
ls -al /export/
touch /export/somefile
EOF
Final Script
#!/usr/bin/bash
ERRLOG=error_log
SITELOG=site_log
TEE=tee
function WrapExec {
echo "Command: $1"
array=(`echo $@`)
array=(${array[@]:1});
echo "Parameters: ${array[*]}"
RESULT=`$1 ${array[*]} 2>> $ERRLOG | $TEE -a $SITELOG`
echo "Result:$RESULT:$?" 2>>$ERRLOG | $TEE -a $SITELOG
}
function ReadFile {
while read line
do
WrapExec $line
done
}
ReadFile << EOF
ls -al /export/
touch /export/somefile
EOF
# Hopefully this has been fun and informative
# Thanks for reading.