Saturday, June 14, 2014

Unix Shell Example: Software Builds Automation(1)

 #! /bin/bash  

 #Initiate the input field separator to newline-space-tab  
 IFS="  
  "  

 #Set the path to be limited directory set  
 #Exporting the PATH variable will make all sub processes  
 #inherited from the here have the same PATH value  
 PATH="/usr/local/bin:/bin:/usr/bin"  
 export PATH  

 ALLTARGETS=   #targets to build  
 altlogdir=   #alternative log directory  
 altsrcdirs=   #alternative source file location  
 ALTUSERHOSTS=  #additional user hosts  
 CHECKTARGETS=check  
 CONFIGUREDIR=. #subdirectory with configure scripts  
 CONFIGUREFLAGS= #special flags for configuration  
 LOGDIR=     #local directory to hold log files  
 userhosts=   #Additional build hosts named on command line  
 BUILDHOME=$HOME/.build #In this case: /home/aubinxia/.build  
 BUILDBEGIN=./.build/begin  
 BUILDEND=./.build/end  
 EXITCODE=0   #Specify the exit code as 0  
 EXTRAENVIRONMENT=  
 PROGRAM=`basename $0` #in this case: ./script_1  
 VERSION=1.0  
 DATEFLAGS="+%Y.%m.%d.%H.%M.%S" #Specify the date format used later  
 SCP=scp  
 SSH=ssh  
 SSHFLAGS=${SSHFLAGS--x} #if SSHFLAGS is not defined return "-x". In this case, SSHFLAGS is: -x  
 STRIPCOMMENTS='sed -e s/#.*$//' # a facility to strip comments  
 INDENT="awk '{ print \"\t\t\t\" \$0 }'" # a facility to print out indention  
 JOINTLINES="tr '\n' '\040'" # a facility to join lines by converting newline to \040(space)  
 defaultdirectories=$BUILDHOME/directories  
 defaultuserhosts=$BUILDHOME/userhosts  

 test -f $defaultdirectories && SRCDIRS="`$STRIPCOMMENTS $defaultdirectories`"   
 #if defaultdirectories exists, strip all comments from defaultdirectories file  
 #NOTE: $defaultdirectories is just a file, which contains the list of source directories  
 # as one per line. We need to use STRIPCOMMENTS to remove any comments there. And the result  
 #, also the output here is just a few lines, each line is a directory  
 #Test if SRCDIRS is empty here, if it is, then we assign very basic location  
 # to it.  
 test -z $SRCDIRS && \  
   SRCDIRS="  
       .  
       /usr/local/src  
       /usr/local/gnu/src  
       $HOME/src  
       $HOME/gnu/src  
       /tmp  
       /usr/tmp  
       /var/tmp  
       "  

 echo $SRCDIRS  
 #output:   
 #. /usr/local/src /usr/local/gnu/src /home/aubinxia/src /home/aubinxia/gnu/src /tmp /usr/tmp /var/tmp  
 #everything get compacted to same line.  

 while test $# -gt 0  
 do  
   case $1 in  
     -all | -al | -a)  
       shift  
       ALLTARGETS="$1"  
       ;;  
     -cd)  
       shift  
       CONFIGUREDIR="$1"  
       ;;  
     -check | -chec | -che | -ch | -c)  
       shift  
       CHECKTARGETS="$1"  
       ;;  
     -configure | -conf)  
       shift  
       CONFIGUREFLAGS="$1"  
       ;;  
     -environment | -env)  
       shift  
       EXTRAENVIRONMENT="$1"  
       ;;  
     -help | -h)  
       usage_and_exit 0  
       ;;  
     -logdirectory | -log)  
       shift  
       altlogdir="$1"  
       ;;  
     -on)  
       shift  
       userhosts="$userhosts $1"  
       ;;  
     -source)  
       shift  
       altsrcdirs="$altsrcdirs $1"  
       ;;  
     -userhosts | -hosts)  
       shift  
       set_user_hosts $1  
       ;;  
     -version | -v)  
       version  
       exit 0  
       ;;  
     -*)  
       error "Unrecognized option: $1"  
       ;;  
     *)  
       break  
       ;;  
   esac  
   shift  
 done  

 #Search for the mail command in current system, since mail command  
 #is in different location across different LINUX system  
 for MAIL in /bin/mailx /usr/bin/mailx /usr/sbin/mailx /usr/ucb/mailx /bin/mail /usr/bin/mail  
 do  
   test -x MAIL && break  
 done  
 echo $MAIL  

 #If user put in additional source dirs, put it in the front  
 #So right now we have 2 sources, firstly check defaultdirectories, if not exist, we  
 #assign the default list to SRCDIRS, then check if user provide his own src  
 #dirs, if yes, put it in the front  
 SRCDIRS="$altsrcdirs $SRCDIRS"  

 #Two situations, if user provided the userhost, we ignore defaultuserhosts, and   
 #add ALTUSERUSERHOSTS to the userhost. If user doesn't provide userhost, we take  
 #defaultuserhosts into consideration. As long as ALTUSERHOSTS is empty, we add  
 #defaultuserhosts to userhosts  
 if test -n "$userhosts"  
 then  
   test -n "$ALTUSERHOSTS" && userhosts="$userhosts `$STRIPCOMMENTS $ALTUSERHOSTS 2> /devnull`"  
 else  
   test -z "$ALTUSERHOSTS" && ALTUSERHOSTS="$defaultuserhosts"  
   userhosts="`$STRIPCOMMENTS $ALTUSERHOSTS 2> /dev/null`"  
 fi  

 #We need to check if userhosts is empty before moving forward  
 test -z "$userhosts" && usage_and_exit 1  

 #Assume remaining arguments are just packages user want to build  
 #We loop each package and build them  
 for p in "$@"  
 do  
   #try to locate the package from $SRCDIRS, and assign the result to   
   #global variable $PARFILE  
   find_package "$p"  

   #check the result of find_package, if it can not be found, skip processing  
   #it and move to next package  
   if test -z "$PARFILE"  
   then  
     warning "Can not find the package file"  
     continue  
   fi  

   LOGDIR="$altlogdir"  
   #-o means "OR", following statement means: if $LOGDIR is empty or not a   
   #directory or not writable  
   if test -z $LOGDIR -o ! -d "$LOGDIR" -o ! -w "$LOGDIR"  
   then  
     #Try to create following directories, as long as we have one directory  
     #who is writable, then we quit the loop and use that directory as   
     #log directory  
     for LOGDIR in "`dirname $PARFILE`/logs/$p" $BUILDHOME/logs/$p \  
            /usr/tmp /var/tmp /tmp  
     #dirname just checkout the "path" part of given file, there is no slash  
     #it will output "." to represent local directory. It doesn't check existance   
     #of given file.   
     #dirname hello => .  
     #dirname /var/hello => /var  
     do  
       test -d "$LOGRDIR" || mkdir -p "$LOGDIR" 2> /dev/null  
       test -d "$LOGDIR" -a -w "$LOGDIR" && break  
       #-a means "AND" here, so above statement means:  
       #if "$LOGDIR" is one directory and writable, then break out from  
       #the current loop  
     done  
   fi  

   #Use the above $mail facility to send the message to user to   
   #remind checking the logs  
   msg="Checkout build logs for $p in `hostname`: $LOGDIR"  
   echo $msg | $MAIL -s "$msg" $USER 2>/dev/null    

   #Itereate user hosts, and build the package there.  
   for u in $userhosts  
   do  
     build_one $u  
   done  
 done  

 #return the exit code, but we need to make sure that EXIT must be less 
 #than or equal to 125
 test $EXITCODE -gt 125 && EXITCODE=125
 exit $EXITCODE

No comments:

Post a Comment