3 # Purpose: build process script for generating a (grml based) Linux Live-ISO
4 # Authors: grml-team (grml.org),
5 # (c) Michael Prokop <mika@grml.org>,
6 # (c) Thorsten Glaser <tg@mirbsd.org>
7 # Bug-Reports: see http://grml.org/bugs/
8 # License: This file is licensed under the GPL v2 or any later version.
9 ################################################################################
11 # some misc and global stuff {{{
15 # define function getfilesize before "set -e"
16 if stat --help >/dev/null 2>&1; then
17 getfilesize='stat -c %s' # GNU stat
19 getfilesize='stat -f %z' # BSD stat
23 # disable for now since it seems to cause some problems
27 GRML_LIVE_VERSION='0.14.1'
30 SOURCES_LIST_FILE='/etc/grml/fai/apt/sources.list'
31 ADDONS_LIST_FILE='/boot/isolinux/addons_list.cfg'
34 # usage information {{{
38 $PN - build process script for generating a (grml based) Linux Live-ISO
40 Usage: $PN [options, see as follows]
42 -a <architecture> architecture; available values: i386 and amd64
43 -b build the ISO without updating the chroot via FAI
44 -B build the ISO without touching the chroot (skips cleanup)
45 -c <classe[s]> classes to be used for building the ISO via FAI
46 -C <configfile> configuration file for grml-live
47 -d <date> use specified date instead of build time as date of release
48 -F force execution without prompting
49 -g <grml_name> set the grml flavour name
50 -h display short usage information and exit
51 -i <iso_name> name of ISO
52 -I <src_directory> directory which provides files that should become
53 part of the chroot/ISO
54 -n skip generation of ISO
55 -o <output_directory> main output directory of the build process
57 -r <release_name> release name
58 -s <suite> Debian suite; values: etch, lenny, squeeze, sid
59 -t <template_directory> place of the templates
60 -u update existing chroot instead of rebuilding it from scratch
61 -v <version_number> specify version number of the release
62 -V increase verbosity in the build process
63 -z use ZLIB instead of LZMA/XZ compression
68 $PN -c GRMLBASE,GRML_MEDIUM,I386 -o /dev/shm/grml
69 $PN -c GRMLBASE,GRML_SMALL,REMOVE_DOCS,I386 -g grml-small -v 1.0
70 $PN -c GRMLBASE,GRML_FULL,I386 -i grml_0.0-1.iso -v 0.0-1
71 $PN -c GRMLBASE,GRML_FULL,I386 -s sid -V -r 'grml-live rocks'
73 More details: man grml-live + /usr/share/doc/grml-live/grml-live.html
74 http://grml.org/grml-live/
76 Please send your bug reports and feedback to the grml-team: http://grml.org/bugs/
80 # make sure it's possible to get usage information without being
81 # root or actually executing the script
82 if [ "$1" = '-h' -o "$1" = '--help' ] ; then
84 [ "$(id -u 2>/dev/null)" != 0 ] && echo "Please notice that this script requires root permissions."
89 # some runtime checks {{{
90 # we need root permissions for the build-process:
91 if [ "$(id -u 2>/dev/null)" != 0 ] ; then
92 echo "Error: please run this script with uid 0 (root)." >&2
96 if [ -r /var/run/fai/FAI_INSTALLATION_IN_PROGRESS ] ; then
97 echo "/usr/sbin/fai already running or was aborted before.">&2
98 echo "You may remove /var/run/fai/FAI_INSTALLATION_IN_PROGRESS and try again.">&2
103 if [ -r /var/run/fai/fai_softupdate_is_running ] ; then
104 echo "/usr/sbin/fai softupdate already running or was aborted before.">&2
105 echo "You may remove /var/run/fai/fai_softupdate_is_running and try again.">&2
110 # lsb-functions and configuration stuff {{{
111 # make sure they are not set by default
119 if [ -r /etc/grml/lsb-functions ] ; then
120 . /etc/grml/lsb-functions
122 einfo() { echo " [*] $*" ;}
123 eerror() { echo " [!] $*">&2 ;}
124 ewarn() { echo " [x] $*" ;}
126 eindent() { return 0 ;}
127 eoutdent() { return 0 ;}
130 # source main configuration file:
131 LIVE_CONF=/etc/grml/grml-live.conf
135 # umount all directories {{{
137 # make sure we don't leave any mounts - FAI doesn't remove them always
138 umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
139 umount $CHROOT_OUTPUT/sys 2>/dev/null || /bin/true
140 umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
141 umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
142 [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
148 rm -f /var/run/fai/fai_softupdate_is_running \
149 /var/run/fai/FAI_INSTALLATION_IN_PROGRESS
150 [ -n "$SQUASHFS_STDERR" ] && rm -rf "$SQUASHFS_STDERR"
152 [ -n "$1" ] && EXIT="$1" || EXIT="1"
153 [ -n "$2" ] && eerror "$2">&2
154 log "------------------------------------------------------------------------------"
157 trap bailout 1 2 3 3 6 9 14 15 EXIT
161 [ -n "$LOGFILE" ] || LOGFILE=/var/log/grml-live.log
163 chown root:adm $LOGFILE
167 # some important functions {{{
170 # usage: log "string to log"
171 log() { echo "$*" >> $LOGFILE ; }
173 # cut string at character number int = $1
174 # usage: cut_string 5 "1234567890" will output "12345"
176 [ -n "$2" ] || return 1
177 echo "$2" | head -c "$1"; echo -ne "\n"
180 # prepend int = $1 spaces before string = $2
181 # usage: extend_string_begin 5 "123" will output " 123"
182 extend_string_begin() {
183 [ -n "$2" ] || return 1
184 local COUNT="$(echo $2 | wc -c)"
185 local FILL="$(expr $COUNT - $1)"
186 while [ "$FILL" -gt 1 ] ; do
188 local FILL=$(expr $FILL - 1)
190 while [ "$FILL" -lt 1 ] ; do
192 local FILL=$(expr $FILL + 1)
194 echo "$2" | head -c "$1"; echo -ne "\n"
197 # append int = $1 spaces to string = $2
198 # usage: extend_string_begin 5 "123" will output "123 "
199 extend_string_end() {
200 [ -n "$2" ] || return 1
201 echo -n "$2" | head -c "$1"
202 local COUNT="$(echo $2 | wc -c)"
203 local FILL="$(expr $COUNT - $1)"
204 while [ "$FILL" -gt 1 ] ; do
206 local FILL=$(expr $FILL - 1)
208 while [ "$FILL" -lt 1 ] ; do
210 local FILL=$(expr $FILL + 1)
216 # read local (non-packaged) configuration {{{
217 LOCAL_CONFIG=/etc/grml/grml-live.local
218 if [ -r "$LOCAL_CONFIG" ] ; then
219 log "Sourcing $LOCAL_CONFIG"
222 log "No $LOCAL_CONFIG found, not sourcing it"
227 # command line parsing {{{
228 while getopts "a:C:c:d:g:i:I:o:r:s:t:v:bBFnquVz" opt; do
233 c) CLASSES="$OPTARG" ;;
234 C) CONFIG="$OPTARG" ;;
236 g) GRML_NAME="$OPTARG" ;;
237 i) ISO_NAME="$OPTARG" ;;
238 I) CHROOT_INSTALL="$OPTARG" ;;
240 o) OUTPUT="$OPTARG" ;;
241 q) SKIP_MKSQUASHFS=1 ;;
242 r) RELEASENAME="$OPTARG" ;;
243 s) SUITE="$OPTARG" ;;
244 t) TEMPLATE_DIRECTORY="$OPTARG";;
245 v) VERSION="$OPTARG" ;;
249 z) SQUASHFS_ZLIB=1 ;;
250 ?) echo "invalid option -$OPTARG" >&2; bailout 1 ;;
253 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
256 # assume sane defaults (if not set already) {{{
257 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
258 [ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux'
259 [ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_MEDIUM,I386"
260 [ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)"
261 [ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators '
262 [ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml"
263 [ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png'
264 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
265 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai'
266 [ -n "$GRML_NAME" ] || GRML_NAME='grml'
267 [ -n "$HOSTNAME" ] || HOSTNAME='grml'
268 [ -n "$HYBRID_METHOD" ] || HYBRID_METHOD='manifold'
269 [ -n "$NFSROOT_CONF" ] || NFSROOT_CONF='/etc/grml/fai/make-fai-nfsroot.conf'
270 [ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks'
271 [ -n "$SQUASHFS_EXCLUDES_FILE " ] || SQUASHFS_EXCLUDES_FILE='/etc/grml/fai/squashfs-excludes'
272 [ -n "$SUITE" ] || SUITE='squeeze'
273 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
274 [ -n "$USERNAME" ] || USERNAME='grml'
275 [ -n "$VERSION" ] || VERSION='0.0.1'
276 [ -n "$WINDOWS_BINARIES" ] || WINDOWS_BINARIES='http://the.earth.li/~sgtatham/putty/latest/x86/'
278 # output specific stuff, depends on $OUTPUT (iff not set):
279 [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live'
280 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
281 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
282 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
285 # some misc checks before executing FAI {{{
286 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
287 specify it on the command line using the -c option."
288 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
289 specify it on the command line using the -o option."
291 # trim characters that are known to cause problems inside $GRML_NAME;
292 # for example isolinux does not like '-' inside the directory name
293 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
295 # export variables to have them available in fai scripts:
296 [ -n "$GRML_NAME" ] && export GRML_NAME="$GRML_NAME"
297 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
300 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
301 # this was default behaviour until grml-live 0.9.34:
302 if [ -n "$ZERO_LOGFILE" ] ; then
303 PRESERVE_LOGFILE='' # make sure it's cleaned then
304 ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
305 ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
310 # ask user whether the setup is ok {{{
311 if [ -z "$FORCE" ] ; then
313 echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
315 echo " FAI classes: $CLASSES"
316 [ -r "$LOCAL_CONFIG" ] && echo " Local config: /etc/grml/grml-live.local"
317 [ -n "$CONFIG" ] && echo " Configuration: $CONFIG"
318 echo " main directory: $OUTPUT"
319 [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT"
320 [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT"
321 [ -n "$ISO_OUTPUT" ] && echo " ISO target: $ISO_OUTPUT"
322 [ -n "$GRML_NAME" ] && echo " Grml name: $GRML_NAME"
323 [ -n "$RELEASENAME" ] && echo " Release name: $RELEASENAME"
324 [ -n "$DATE" ] && echo " Build date: $DATE"
325 [ -n "$VERSION" ] && echo " Grml version: $VERSION"
326 [ -n "$SUITE" ] && echo " Debian suite: $SUITE"
327 [ -n "$ARCH" ] && echo " Architecture: $ARCH"
328 [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD"
329 [ -n "$HYBRID_METHOD" ] && echo " Hybrid method: $HYBRID_METHOD"
330 [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY"
331 [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL"
332 [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID"
333 [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature."
334 [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
335 [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS"
336 [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE"
337 [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA/XZ) compression."
338 [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
339 [ -n "$VERBOSE" ] && echo " Using VERBOSE mode."
340 [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation."
341 [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file."
342 [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file."
343 [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE."
344 [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched."
346 echo -n "Is this ok for you? [y/N] "
348 if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
349 bailout 1 "Exiting as requested."
355 # clean/zero/remove logfiles {{{
357 if [ -n "$PRESERVE_LOGFILE" ] ; then
358 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
360 # make sure it is empty (as it is e.g. appended to grml-live-db)
364 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
365 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
366 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
367 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
368 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
369 rm -f /var/log/fai/"$HOSTNAME"/last \
370 /var/log/fai/"$HOSTNAME"/last-dirinstall \
371 /var/log/fai/"$HOSTNAME"/last-softupdate
376 # source config and startup {{{
377 if [ -n "$CONFIG" ] ; then
378 if ! [ -f "$CONFIG" ] ; then
379 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
380 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
383 log "Sourcing $CONFIG"
388 start_seconds=$(cut -d . -f 1 /proc/uptime)
389 log "------------------------------------------------------------------------------"
390 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
391 log "Executed grml-live command line:"
394 einfo "Logging actions to logfile $LOGFILE"
397 # on-the-fly configuration {{{
398 if [ -n "$MIRROR_DIRECTORY" ] ; then
399 if ! [ -d "$MIRROR_DIRECTORY/debian" ] ; then
400 log "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting. [$(date)]"
401 eerror "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting." ; eend 1
404 cat > "$SOURCES_LIST_FILE" << EOF
405 # NOTE: This file is *NOT* meant for manual customisation! This file is
406 # modified by grml-live and any changes might be overridden.
407 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
408 # or FAI's fcopy command with /etc/grml/fai/config/files instead!
410 echo "$MIRROR_SOURCES" >> "$SOURCES_LIST_FILE"
411 if [ -n "$GRML_LIVE_SOURCES" ] ; then
412 echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
414 elif [ -n "$GRML_LIVE_SOURCES" ] ; then
415 cat > "$SOURCES_LIST_FILE" << EOF
416 # NOTE: This file is *NOT* meant for manual customisation! This file is
417 # modified by grml-live and any changes might be overridden.
418 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
419 # or FAI's fcopy command with /etc/grml/fai/config/files instead!
421 echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
424 if [ -n "$FAI_DEBOOTSTRAP" ] ; then
425 sed "s#^FAI_DEBOOTSTRAP=.*#FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"#" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
428 # does this suck? YES!
429 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
431 unstable) SUITE='sid' ;;
432 # make sure that we *NEVER* write any broken suite name to sources.list,
433 # otherwise we won't be able to adjust it one next (correct) execution
441 *) echo "Sorry, $SUITE is not a valid Debian suite, exiting.">&2; bailout 1 ;;
444 DIST=" etch\| stable\| lenny\| squeeze\| wheezy\| testing\| sid\| unstable"
445 sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
446 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" ; do
447 if [ -n "$file" ] ; then
448 sed "s/^SUITE=.*/SUITE=\"$SUITE\"/" $file | sponge $file
449 sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$file" | sponge "$file"
453 # notice: activate grml-live pool only if we are building against unstable:
454 if grep -qwe unstable -qwe sid "$SOURCES_LIST_FILE" ; then
455 grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" || \
456 grep grml-stable "$SOURCES_LIST_FILE" | \
457 sed 's/grml-stable/grml-live/' >> "$SOURCES_LIST_FILE"
459 grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" && \
460 sed 's/.*grml-live.*/# removed grml-live repository/' "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
463 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" "$NFSROOT_CONF" ; do
464 if [ -n "$file" ] ; then
465 sed "s|^FAI_DEBOOTSTRAP=\"[a-z]* |FAI_DEBOOTSTRAP=\"$SUITE |" "$file" | sponge "$file"
469 # validate whether the specified architecture class matches the
470 # architecture (option), otherwise installation of kernel will fail
471 if echo $CLASSES | grep -qi i386 ; then
472 if ! [[ "$ARCH" == "i386" ]] ; then
473 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
474 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
475 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
479 elif echo $CLASSES | grep -qi amd64 ; then
480 if ! [[ "$ARCH" == "amd64" ]] ; then
481 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
482 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
483 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
489 if grep -q -- 'FAI_DEBOOTSTRAP_OPTS.*--arch' "$NFSROOT_CONF" ; then
490 sed "s/--arch [a-z0-9]* /--arch $ARCH /" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
492 sed "s|^FAI_DEBOOTSTRAP_OPTS=\"\(.*\)|FAI_DEBOOTSTRAP_OPTS=\"--arch $ARCH \1|" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
496 # CHROOT_OUTPUT - execute FAI {{{
497 if [ -n "$BUILD_DIRTY" ]; then
498 log "Skipping stage 'fai' as requested via option -B"
499 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
501 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
503 # provide inform fai about the ISO we build
504 [ -d "$CHROOT_OUTPUT/etc/" ] || mkdir -p "$CHROOT_OUTPUT/etc/"
505 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
506 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
507 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
509 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
510 FAI_ACTION=softupdate
512 FAI_ACTION=dirinstall
515 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
516 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
517 log "Error: does not look like you have a working chroot. Updating/building not possible."
518 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
524 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
525 log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
526 ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
528 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
530 if [ -n "${MIRROR_DIRECTORY}" ] ; then
531 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
532 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
535 log "Executed FAI command line:"
536 log "BUILD_ONLY=$BUILD_ONLY fai $VERBOSE -C $GRML_FAI_CONFIG -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS"
537 BUILD_ONLY="$BUILD_ONLY" fai $VERBOSE -C "$GRML_FAI_CONFIG" -c"$CLASSES" -u \
538 "$HOSTNAME" $FAI_ACTION "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
539 RC="$PIPESTATUS" # notice: bash-only
541 FORCE_ISO_REBUILD=true
543 if [ "$RC" != 0 ] ; then
544 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
545 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
548 log "Setting /etc/grml_version to $GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]"
549 echo "$GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]" > $CHROOT_OUTPUT/etc/grml_version
550 chmod 644 $CHROOT_OUTPUT/etc/grml_version
551 einfo "Rebuilding initramfs"
552 # make sure new /etc/grml_version reaches the initramfs:
553 # chroot $CHROOT_OUTPUT update-initramfs -u -t => might break when using kernel-package :(
554 chroot $CHROOT_OUTPUT update-initramfs -u -k all
558 # Remove all FAI logs from chroot if class RELEASE is used:
559 if [ -f "$CHROOT_OUTPUT"/etc/grml_fai_release ] ; then
560 rm -rf "$CHROOT_OUTPUT"/var/log/fai/*
561 rm -f "$CHROOT_OUTPUT"/var/log/install_packages.list
566 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
568 CHECKLOG=/var/log/fai/$HOSTNAME/last
569 if [ -r "$CHECKLOG/software.log" ] ; then
570 # 1 errors during executing of commands
571 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
572 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
573 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
574 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
575 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
578 if [ -r "$CHECKLOG/shell.log" ] ; then
579 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
582 if [ -n "$ERROR" ] ; then
583 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
584 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
585 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
589 log "Finished execution of stage 'fai dirinstall' [$(date)]"
590 einfo "Finished execution of stage 'fai dirinstall'"
593 einfo "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
594 log "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
600 # package validator {{{
601 CHECKLOG=/var/log/fai/$HOSTNAME/last
603 if [ -r "$CHECKLOG/package_errors.log" ] && grep -q '[a-z]' "$CHECKLOG/package_errors.log" ; then
605 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
606 eerror "The following packages were requested for installation but could not be processed:"
607 cat $CHECKLOG/package_errors.log
608 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
612 ewarn "The following packages were requested for installation but could not be processed:"
613 cat $CHECKLOG/package_errors.log
619 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
620 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
621 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
624 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
625 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
626 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
627 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
630 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
631 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
633 if [ -z "$NO_ADDONS" ] ; then
634 [ -d "$BUILD_OUTPUT"/boot/addons ] || mkdir -p "$BUILD_OUTPUT"/boot/addons
635 if [ -r "$TEMPLATE_DIRECTORY"/boot/addons/memtest ] ; then
636 log "Installing $TEMPLATE_DIRECTORY/boot/addons/memtest"
637 cp "$TEMPLATE_DIRECTORY"/boot/addons/memtest "$BUILD_OUTPUT"/boot/addons/memtest
638 elif [ -r /boot/memtest86+.bin ] ; then
639 log "Installing /boot/memtest86+.bin"
640 cp /boot/memtest86+.bin "$BUILD_OUTPUT"/boot/addons/memtest
642 ewarn "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
643 log "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
648 # if we don't have an initrd we a) can't boot and b) there was an error
649 # during build, so check for the file:
650 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
651 if [ -n "$INITRD" ] ; then
652 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.gz
653 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
655 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
656 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
660 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
661 if [ -n "$KERNEL_IMAGE" ] ; then
662 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/linux26
664 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
665 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
669 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
670 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
671 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
672 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
676 # *always* copy files to output directory so the variables
677 # get adjusted according to the build
678 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
680 if [ -n "$NO_ADDONS" ] ; then
681 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
682 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
684 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
685 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
686 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
688 # copy only files so we can handle bsd4grml on its own
689 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
690 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
693 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
694 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
695 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
697 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
698 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
700 log "bsd4grml addon not found, skipping therefore."
701 ewarn "bsd4grml addon not found, skipping therefore." ; eend 0
705 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
708 if ! [ -d ${TEMPLATE_DIRECTORY}/boot/grub ] ; then
709 log "grub templates do not exist, skipping therefore."
710 ewarn "grub templates do not exist, skipping therefore." ; eend 0
712 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
713 cp -a ${TEMPLATE_DIRECTORY}/boot/grub "$BUILD_OUTPUT"/boot/
716 # make sure we have recent template files available, otherwise updating
717 # the strings like $GRML_NAME and $VERSION might be out of date
718 cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
721 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
722 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
723 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
727 [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML
728 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/
730 # adjust boot splash information:
731 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
732 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
733 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
735 if [ -r "$BUILD_OUTPUT"/GRML/grml-version ] ; then
736 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version
737 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/grml-version
740 # make sure the squashfs filename is set accordingly:
741 SQUASHFS_NAME="$GRML_NAME.squashfs"
743 if [ -n "$NO_BOOTID" ] ; then
744 log 'Skipping bootid feature as requested via $NO_BOOTID.'
745 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
747 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
748 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
749 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
750 log "Generating /conf/bootid.txt with entry ${BOOTID}."
751 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
755 # adjust all variables in the templates with the according distribution information
756 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
757 "${BUILD_OUTPUT}"/boot/grub/* ; do
758 if [ -r "${file}" ] ; then
759 sed -i "s/%ARCH%/$ARCH/g" "${file}"
760 sed -i "s/%DATE%/$DATE/g" "${file}"
761 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
762 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
763 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
764 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
765 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
766 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
767 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
768 sed -i "s/%VERSION%/$VERSION/g" "${file}"
770 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s/ boot=live/ boot=live $DEFAULT_BOOTOPTIONS/" "${file}"
772 if [ -n "$NO_BOOTID" ] ; then
773 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
775 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
780 # adjust bootsplash accordingly but make sure the string has the according lenght
781 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
782 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
783 for file in f4 f5 ; do
784 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
785 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
786 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
790 # generate addon list
791 rm "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
792 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
793 include_name=$(basename "$name")
794 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
797 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
798 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
799 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
800 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
801 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
802 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
804 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
805 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
808 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
809 if [ ! -n "$NO_ADDONS" ] ; then
810 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
812 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
813 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
814 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
815 else # assume we are building a custom distribution:
816 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
817 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
818 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
819 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
821 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
825 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
826 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
827 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
831 # use old style console based isolinux method only if requested:
832 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
833 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
834 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
835 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
836 einfo "include for console.cfg already foud, nothing to do."
839 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
840 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
841 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
845 log 'Using graphical boot menu.'
846 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
847 log "include for vesamenu.cfg already foud, nothing to do."
849 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
850 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
854 # jump back to grub from bsd4grml (/boot/grub/stage2):
857 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
858 if [ -e "$BUILD_OUTPUT"/boot/grub/core.img ]; then
864 for file in "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 \
865 "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.cfg \
866 "$BUILD_OUTPUT"/boot/isolinux/*.cfg \
867 "$BUILD_OUTPUT"/boot/grub/grub.cfg \
868 "$BUILD_OUTPUT"/boot/grub/menu.lst ; do
869 if [ -e "$file" ] ; then
870 sed -i -e "s!%GRUB_VERSION%!$GRUB_VERSION!g" \
871 -e "s!%GRUB_LEGACY%!$GRUB_LEGACY!g" "$file"
875 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
878 if [ -e "$BUILD_OUTPUT"/boot/grub/$GRUB_LEGACY ]; then
879 sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/menu.lst
880 sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/grub.cfg
881 elif [ -e "$BUILD_OUTPUT"/boot/grub/menu.lst -a -e "$BUILD_OUTPUT"/boot/grub/grub.cfg ] ; then
882 sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/menu.lst
883 sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/grub.cfg
886 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
887 if ! [ -r "$DPKG_LIST" ] ; then
888 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
890 einfo "Storing package list information as /GRML/${GRML_NAME}-packages.txt on ISO."
891 cp "$DPKG_LIST" "${BUILD_OUTPUT}/GRML/${GRML_NAME}-packages.txt"
895 # autostart for Windows:
896 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
897 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
901 if [ -n "$NO_WINDOWS_BINARIES" ] ; then
902 log "Skipping download of windows binaries as requested via \$NO_WINDOWS_BINARIES."
903 einfo "Skipping download of windows binaries as requested via \$NO_WINDOWS_BINARIES."
906 if [ -f "$BUILD_OUTPUT"/windows/putty.exe ] ; then
907 log "Skipping stage 'WINDOWS_BINARIES' as $BUILD_OUTPUT/windows exists already."
908 ewarn "Skipping stage 'WINDOWS_BINARIES' as $BUILD_OUTPUT/windows exists already." ; eend 0
910 if ! [ -d "$BUILD_OUTPUT"/windows ] ; then
911 mkdir "$BUILD_OUTPUT"/windows
912 ( cd "$BUILD_OUTPUT"/windows
913 for file in pageant plink pscp psftp putty puttygen ; do
914 wget -O ${file}.exe ${WINDOWS_BINARIES}/${file}.exe
915 md5sum ${file}.exe > ${file}.exe.md5
919 log "Finished execution of stage 'WINDOWS_BINARIES' [$(date)]"
920 einfo "Finished execution of stage 'WINDOWS_BINARIES'" ; eend 0
924 FORCE_ISO_REBUILD=true
925 einfo "Finished execution of stage 'boot'" ; eend 0
928 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
929 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
933 # support installation of local files into the chroot/ISO
934 if [ -n "$CHROOT_INSTALL" ] ; then
935 if ! [ -d "$CHROOT_INSTALL" ] ; then
936 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
937 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
939 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
940 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
941 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
943 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
944 FORCE_ISO_REBUILD=true
948 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
949 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
950 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
951 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
952 log "Skipping stage 'squashfs' as requested via option -q"
953 ewarn "Skipping stage 'squashfs' as requested via option -q" ; eend 0
955 [ -d "$BUILD_OUTPUT"/live ] || mkdir "$BUILD_OUTPUT"/live
956 # make sure we don't leave (even an empty) base.tgz:
957 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
959 # if unconfigured default to squashfs-tools' mksquashfs binary
960 if [ -z "$SQUASHFS_BINARY" ] ; then
961 SQUASHFS_BINARY='mksquashfs'
964 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
965 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
966 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
968 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
969 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
973 # use sane defaults if $SQUASHFS_OPTIONS isn't set
974 if [ -z "$SQUASHFS_OPTIONS" ] ; then
975 # use blocksize 256k as this gives best result with regards to time + compression
976 SQUASHFS_OPTIONS="-b 256k"
978 # set lzma/xz compression by default, unless -z option has been specified on command line
979 if [ -z "$SQUASHFS_ZLIB" ] ; then
980 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
982 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
986 # support exclusion of files via exclude-file:
987 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
988 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE"
991 # get rid of unnecessary files when building grml-small for final release:
992 if echo "$CLASSES" | grep -q GRML_SMALL ; then
993 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
997 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
999 # informational stuff
1000 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1001 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1002 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1004 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1006 if $SQUASHFS_BINARY $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \
1007 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1008 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/filesystem.module
1009 log "Finished execution of stage 'squashfs' [$(date)]"
1010 einfo "Finished execution of stage 'squashfs'" ; eend 0
1012 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1013 log "$(cat $SQUASHFS_STDERR)"
1014 eerror "Error: there was a critical error executing stage 'squashfs':"
1015 cat "${SQUASHFS_STDERR}"
1020 FORCE_ISO_REBUILD=true
1023 # create md5sum file:
1024 ( cd $BUILD_OUTPUT/GRML &&
1025 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1028 # ISO_OUTPUT - mkisofs {{{
1029 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1030 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1032 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1033 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1034 elif [ "$BOOT_METHOD" = "grub" ] ; then
1035 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/grub/stage2"
1036 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1037 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1040 # Just until http://bts.grml.org/grml/issue945 has been resolved.
1041 # HYBRID_METHOD defaults to manifold, so make sure the default works OOTB.
1042 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1043 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1044 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1045 HYBRID_METHOD='grub2'
1049 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1050 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1051 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1052 elif [ -n "$SKIP_MKISOFS" ] ; then
1053 log "Skipping stage 'iso build' as requested via option -n"
1054 ewarn "Skipping stage 'iso build' as requested via option -n" ; eend 0
1056 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1058 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1059 log "Forcing rebuild of ISO because files on ISO have been modified."
1060 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1063 # support mkisofs as well as genisoimage
1064 if which mkisofs >/dev/null 2>&1; then
1066 elif which genisoimage >/dev/null 2>&1; then
1067 MKISOFS='genisoimage'
1069 log "Error: neither mkisofs nor genisoimage available - can not create ISO."
1070 eerror "Error: neither mkisofs nor genisoimage available - can not create ISO." ; eend 1
1075 if cd "$BUILD_OUTPUT" ; then
1076 if [ "$BOOT_METHOD" = "grub2" ]; then
1077 # make a 2048-byte bootsector for El Torito
1078 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1079 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1080 echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
1081 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1083 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1084 "$MKISOFS" -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1085 -l -r -J $BOOT_ARGS -no-pad \
1086 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1087 # both of these need core.img there, so it’s easier to write it here
1088 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1089 # must be <= 30720 bytes
1090 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1091 conv=notrunc bs=512 seek=4 2>/dev/null
1094 # pad the output ISO to multiples of 256 KiB for partition table support
1095 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1096 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1097 siz=$((cyls * 16 * 32 * 512)) # size after padding
1098 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1099 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1101 # support disabling hybrid ISO image
1102 if [ "$HYBRID_METHOD" = "disable" ] ; then\
1103 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1104 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1106 # use isohybrid only on request
1107 elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
1108 if ! which isohybrid >/dev/null 2>&1 ; then
1109 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1111 log "Creating hybrid ISO file with isohybrid method"
1112 einfo "Creating hybrid ISO file with isohybrid method"
1113 # Notes for consideration:
1114 # "-entry 4 -type 1c"
1115 # * using 4 as the partition number is supposed to help with BIOSes
1116 # that only support USB-Zip boot
1117 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1118 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1119 # to get the BIOS even look at the partition created by isohybrid
1120 isohybrid "${ISO_OUTPUT}/${ISO_NAME}"
1123 # by default use our manifold boot method:
1125 # isoinfo is part of both mkisofs and genisoimage so we're good
1126 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1127 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN;1 *$/s//\1/p')
1128 if ! [ -r boot/grub/core.img ] ; then
1129 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1130 elif [ "${bootoff:-0}" -lt 1 ] ; then
1131 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1133 log "Creating hybrid ISO file with manifold method"
1134 einfo "Creating hybrid ISO file with manifold method"
1135 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1136 # 512 bytes: MBR, partition table, load GRUB 2
1137 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1139 # read only one but 2048-byte sized (scale: << 2) sector
1140 echo $bootoff $bootoff | \
1141 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1142 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1147 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1148 case $CLASSES in *RELEASE*)
1151 if cd $ISO_OUTPUT ; then
1152 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1153 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1154 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1155 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1164 if [ "$RC" = 0 ] ; then
1165 log "Finished execution of stage 'iso build' [$(date)]"
1166 einfo "Finished execution of stage 'iso build'" ; eend 0
1168 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1169 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1175 # log build information to database if grml-live-db is installed and enabled {{{
1177 if [ -d /usr/share/grml-live-db ] ; then
1180 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1181 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1182 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1183 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1185 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1186 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1187 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1191 # disable by default for now, not sure whether really everyone is using a local db file
1192 #if ! touch "$DPKG_DATABASE" ; then
1193 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1197 if ! [ -r "$DPKG_LIST" ] ; then
1198 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1199 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1201 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1202 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1203 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1206 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1222 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1223 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1225 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1227 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1231 ## END OF FILE #################################################################
1232 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=3