Classic Shell Scripting - Arnold Robbins [118]
env `$STRIPCOMMENTS $envfile | $JOINLINES` \
$EXTRAENVIRONMENT \
nice time ./configure $CONFIGUREFLAGS ;
The chmod command to add execute permission is there for two reasons: first, because we have occasionally encountered package archives where that permission is lacking, and second, because current implementations of the Java jar archive format neglect to record that permission.[5] The nice command prefix lowers the job priority so that it has minimal impact on the remote system. The time command prefix reports the time for configure to run. We have seen some monster configuration scripts, so it is helpful to record their runtimes to allow estimation of build times for later versions.
We now come to where most of the work happens: the actual build and validation of the package, again with a nice time prefix, and make arguments supplied by —all and —check options (or their defaults):
nice time make $ALLTARGETS && nice time make $CHECKTARGETS ;
The make commands hide a lot of work, but the rules for carrying out that work have already been written down by the developers in the Makefile, so end installers usually need not be concerned with it.
What we expect to see in the log files on completion of a successful build is a report like All tests passed!, or some other easily understood report that all is well. The validation tests are exceedingly important, and should never be skipped. Even if the package worked correctly at its development sites, there is no reason to believe that it will at ours because there are so many things that can go wrong: differences in architectures, compilers, environment variables, filesystems, local customizations and tuning; operating system releases; search paths; shared libraries; system header files; X Window System defaults; and so on, can all contribute to failures.
We are now ready to wrap up the remote commands, with just a few extra lines of final reports for the log files:
echo '= = = = = = = = = = = = = = = = = = = = = = = =
= = = = = = = = = = = = = = = = = = = = = = = = = = =' ;
echo 'Disk free report for $builddir/$package:' ;
df $builddir | $INDENT ;
printf 'Remote date: ' ;
date $DATEFLAGS ;
As with the $BUILDBEGIN script, the $BUILDEND script under the home directory provides for any final additional log-file reporting, but true ensures success:
cd ;
test -f $BUILDEND && . $BUILDEND || \
test -f $BUILDEND && source $BUILDEND || \
true ;
echo '= = = = = = = = = = = = = = = = = = = = = = = =
= = = = = = = = = = = = = = = = = = = = = = = = = = =' ;
The last two lines of the build_one function close off the list of remote commands and the function body, redirect both standard output and standard error to the log file, and importantly, run the remote commands in the background so that execution can immediately continue in the inner loop of the main body. The remote shell's input is redirected to the null device so it does not hang waiting for user input:
" < /dev/null > "$LOGDIR/$logfile" 2>&1 &
}
A program of this size and power certainly requires online documentation. Space does not permit us to present the manual pages for build-all here, but both the script and its manual-page file are available at this book's web site.
The complete script, with a few comments that we omitted in our piecewise presentation, and reordering to put the functions in alphabetical order near the beginning, is collected in Example 8-2. Although it is about 320 lines long (ignoring comments and blank lines), the payoff for our programming investment is substantial. Once a new distribution of a package has been fetched to the local system, a one-line command starts the build and validation on all of the build hosts in parallel. After a suitable wait, the installer can then check the build logs for their success or failure and decide on which machines it is safe to run make install to install the software on the system, after which the build directory can be removed from the remote system.
* * *
Tip
Build failures that are not attributable