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
26 GRML_LIVE_VERSION='0.12.0'
29 SOURCES_LIST_FILE='/etc/grml/fai/apt/sources.list'
30 ADDONS_LIST_FILE='/boot/isolinux/addons_list.cfg'
33 # usage information {{{
37 $PN - build process script for generating a (grml based) Linux Live-ISO
39 Usage: $PN [options, see as follows]
41 -a <architecture> architecture; available values: i386 and amd64
42 -b build the ISO without updating the chroot via FAI
43 -B build the ISO without touching the chroot (skips cleanup)
44 -c <classe[s]> classes to be used for building the ISO via FAI
45 -C <configfile> configuration file for grml-live
46 -d <date> use specified date instead of build time as date of release
47 -F force execution without prompting
48 -g <grml_name> set the grml flavour name
49 -h display short usage information and exit
50 -i <iso_name> name of ISO
51 -I <src_directory> directory which provides files that should become
52 part of the chroot/ISO
53 -n skip generation of ISO
54 -o <output_directory> main output directory of the build process
56 -r <release_name> release name
57 -s <suite> Debian suite; values: etch, lenny, squeeze, sid
58 -t <template_directory> place of the templates
59 -u update existing chroot instead of rebuilding it from scratch
60 -v <version_number> specify version number of the release
61 -V increase verbosity in the build process
62 -z use ZLIB instead of LZMA compression
67 $PN -c GRMLBASE,GRML_MEDIUM,I386 -o /dev/shm/grml
68 $PN -c GRMLBASE,GRML_SMALL,REMOVE_DOCS,I386 -g grml-small -v 1.0
69 $PN -c GRMLBASE,GRML_FULL,I386 -i grml_0.0-1.iso -v 0.0-1
70 $PN -c GRMLBASE,GRML_FULL,I386 -s sid -V -r 'grml-live rocks'
72 More details: man grml-live + /usr/share/doc/grml-live/grml-live.html
73 http://grml.org/grml-live/
75 Please send your bug reports and feedback to the grml-team: http://grml.org/bugs/
79 # make sure it's possible to get usage information without being
80 # root or actually executing the script
81 if [ "$1" = '-h' -o "$1" = '--help' ] ; then
83 [ "$(id -u 2>/dev/null)" != 0 ] && echo "Please notice that this script requires root permissions."
88 # some runtime checks {{{
89 # we need root permissions for the build-process:
90 if [ "$(id -u 2>/dev/null)" != 0 ] ; then
91 echo "Error: please run this script with uid 0 (root)." >&2
95 if [ -r /var/run/fai/FAI_INSTALLATION_IN_PROGRESS ] ; then
96 echo "/usr/sbin/fai already running or was aborted before.">&2
97 echo "You may remove /var/run/fai/FAI_INSTALLATION_IN_PROGRESS and try again.">&2
102 if [ -r /var/run/fai/fai_softupdate_is_running ] ; then
103 echo "/usr/sbin/fai softupdate already running or was aborted before.">&2
104 echo "You may remove /var/run/fai/fai_softupdate_is_running and try again.">&2
109 # lsb-functions and configuration stuff {{{
110 # make sure they are not set by default
118 if [ -r /etc/grml/lsb-functions ] ; then
119 . /etc/grml/lsb-functions
121 einfo() { echo " [*] $*" ;}
122 eerror() { echo " [!] $*">&2 ;}
123 ewarn() { echo " [x] $*" ;}
125 eindent() { return 0 ;}
126 eoutdent() { return 0 ;}
129 # source main configuration file:
130 LIVE_CONF=/etc/grml/grml-live.conf
136 rm -f /var/run/fai/fai_softupdate_is_running \
137 /var/run/fai/FAI_INSTALLATION_IN_PROGRESS
138 [ -n "$SQUASHFS_STDERR" ] && rm -rf "$SQUASHFS_STDERR"
139 [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
140 [ -n "$1" ] && EXIT="$1" || EXIT="1"
141 [ -n "$2" ] && eerror "$2">&2
142 log "------------------------------------------------------------------------------"
145 trap bailout 1 2 3 3 6 9 14 15
149 [ -n "$LOGFILE" ] || LOGFILE=/var/log/grml-live.log
151 chown root:adm $LOGFILE
155 # some important functions {{{
158 # usage: log "string to log"
159 log() { echo "$*" >> $LOGFILE ; }
161 # cut string at character number int = $1
162 # usage: cut_string 5 "1234567890" will output "12345"
164 [ -n "$2" ] || return 1
165 echo "$2" | head -c "$1"; echo -ne "\n"
168 # prepend int = $1 spaces before string = $2
169 # usage: extend_string_begin 5 "123" will output " 123"
170 extend_string_begin() {
171 [ -n "$2" ] || return 1
172 local COUNT="$(echo $2 | wc -c)"
173 local FILL="$(expr $COUNT - $1)"
174 while [ "$FILL" -gt 1 ] ; do
176 local FILL=$(expr $FILL - 1)
178 while [ "$FILL" -lt 1 ] ; do
180 local FILL=$(expr $FILL + 1)
182 echo "$2" | head -c "$1"; echo -ne "\n"
185 # append int = $1 spaces to string = $2
186 # usage: extend_string_begin 5 "123" will output "123 "
187 extend_string_end() {
188 [ -n "$2" ] || return 1
189 echo -n "$2" | head -c "$1"
190 local COUNT="$(echo $2 | wc -c)"
191 local FILL="$(expr $COUNT - $1)"
192 while [ "$FILL" -gt 1 ] ; do
194 local FILL=$(expr $FILL - 1)
196 while [ "$FILL" -lt 1 ] ; do
198 local FILL=$(expr $FILL + 1)
204 # read local (non-packaged) configuration {{{
205 LOCAL_CONFIG=/etc/grml/grml-live.local
206 if [ -r "$LOCAL_CONFIG" ] ; then
207 log "Sourcing $LOCAL_CONFIG"
210 log "No $LOCAL_CONFIG found, not sourcing it"
215 # command line parsing {{{
216 while getopts "a:C:c:d:g:i:I:o:r:s:t:v:bBFnquVz" opt; do
221 c) CLASSES="$OPTARG" ;;
222 C) CONFIG="$OPTARG" ;;
224 g) GRML_NAME="$OPTARG" ;;
225 i) ISO_NAME="$OPTARG" ;;
226 I) CHROOT_INSTALL="$OPTARG" ;;
228 o) OUTPUT="$OPTARG" ;;
229 q) SKIP_MKSQUASHFS=1 ;;
230 r) RELEASENAME="$OPTARG" ;;
231 s) SUITE="$OPTARG" ;;
232 t) TEMPLATE_DIRECTORY="$OPTARG";;
233 v) VERSION="$OPTARG" ;;
237 z) SQUASHFS_ZLIB="true" ;;
238 ?) echo "invalid option -$OPTARG" >&2; bailout 1 ;;
241 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
244 # assume sane defaults (if not set already) {{{
245 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
246 [ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux'
247 [ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_MEDIUM,I386"
248 [ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)"
249 [ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators '
250 [ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml"
251 [ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png'
252 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
253 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai'
254 [ -n "$GRML_NAME" ] || GRML_NAME='grml'
255 [ -n "$HOSTNAME" ] || HOSTNAME='grml'
256 [ -n "$NFSROOT_CONF" ] || NFSROOT_CONF='/etc/grml/fai/make-fai-nfsroot.conf'
257 [ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks'
258 [ -n "$SQUASHFS_EXCLUDES_FILE " ] || SQUASHFS_EXCLUDES_FILE='/etc/grml/fai/squashfs-excludes'
259 [ -n "$SUITE" ] || SUITE='lenny'
260 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
261 [ -n "$USERNAME" ] || USERNAME='grml'
262 [ -n "$VERSION" ] || VERSION='0.0.1'
263 [ -n "$WINDOWS_BINARIES" ] || WINDOWS_BINARIES='http://the.earth.li/~sgtatham/putty/latest/x86/'
265 # output specific stuff, depends on $OUTPUT (iff not set):
266 [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live'
267 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
268 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
269 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
272 # some misc checks before executing FAI {{{
273 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
274 specify it on the command line using the -c option."
275 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
276 specify it on the command line using the -o option."
278 # trim characters that are known to cause problems inside $GRML_NAME;
279 # for example isolinux does not like '-' inside the directory name
280 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
282 # export variables to have them available in fai scripts:
283 [ -n "$GRML_NAME" ] && export GRML_NAME="$GRML_NAME"
284 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
287 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
288 # this was default behaviour until grml-live 0.9.34:
289 if [ -n "$ZERO_LOGFILE" ] ; then
290 PRESERVE_LOGFILE='' # make sure it's cleaned then
291 ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
292 ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
297 # ask user whether the setup is ok {{{
298 if [ -z "$FORCE" ] ; then
300 echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
302 echo " FAI classes: $CLASSES"
303 [ -r "$LOCAL_CONFIG" ] && echo " Local config: /etc/grml/grml-live.local"
304 [ -n "$CONFIG" ] && echo " Configuration: $CONFIG"
305 echo " main directory: $OUTPUT"
306 [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT"
307 [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT"
308 [ -n "$ISO_OUTPUT" ] && echo " ISO target: $ISO_OUTPUT"
309 [ -n "$GRML_NAME" ] && echo " Grml name: $GRML_NAME"
310 [ -n "$RELEASENAME" ] && echo " Release name: $RELEASENAME"
311 [ -n "$DATE" ] && echo " Build date: $DATE"
312 [ -n "$VERSION" ] && echo " Grml version: $VERSION"
313 [ -n "$SUITE" ] && echo " Debian suite: $SUITE"
314 [ -n "$ARCH" ] && echo " Architecture: $ARCH"
315 [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD"
316 [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY"
317 [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL"
318 [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID"
319 [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature."
320 [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
321 [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS"
322 [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE"
323 [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA) compression."
324 [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
325 [ -n "$VERBOSE" ] && echo " Using VERBOSE mode."
326 [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation."
327 [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file."
328 [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file."
329 [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE."
330 [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched."
332 echo -n "Is this ok for you? [y/N] "
334 if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
335 bailout 1 "Exiting as requested."
341 # clean/zero/remove logfiles {{{
343 if [ -n "$PRESERVE_LOGFILE" ] ; then
344 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
346 # make sure it is empty (as it is e.g. appended to grml-live-db)
350 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
351 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
352 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
353 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
354 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
355 rm -f /var/log/fai/"$HOSTNAME"/last \
356 /var/log/fai/"$HOSTNAME"/last-dirinstall \
357 /var/log/fai/"$HOSTNAME"/last-softupdate
362 # source config and startup {{{
363 if [ -n "$CONFIG" ] ; then
364 if ! [ -f "$CONFIG" ] ; then
365 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
366 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
369 log "Sourcing $CONFIG"
374 start_seconds=$(cut -d . -f 1 /proc/uptime)
375 log "------------------------------------------------------------------------------"
376 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
377 log "Executed grml-live command line:"
380 einfo "Logging actions to logfile $LOGFILE"
383 # on-the-fly configuration {{{
384 if [ -n "$MIRROR_DIRECTORY" ] ; then
385 if ! [ -d "$MIRROR_DIRECTORY/debian" ] ; then
386 log "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting. [$(date)]"
387 eerror "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting." ; eend 1
390 cat > "$SOURCES_LIST_FILE" << EOF
391 # NOTE: This file is *NOT* meant for manual customisation! This file is
392 # modified by grml-live and any changes might be overridden.
393 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
394 # or FAI's fcopy command with /etc/grml/fai/config/files instead!
396 echo "$MIRROR_SOURCES" >> "$SOURCES_LIST_FILE"
397 if [ -n "$GRML_LIVE_SOURCES" ] ; then
398 echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
400 elif [ -n "$GRML_LIVE_SOURCES" ] ; then
401 cat > "$SOURCES_LIST_FILE" << EOF
402 # NOTE: This file is *NOT* meant for manual customisation! This file is
403 # modified by grml-live and any changes might be overridden.
404 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
405 # or FAI's fcopy command with /etc/grml/fai/config/files instead!
407 echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
410 if [ -n "$FAI_DEBOOTSTRAP" ] ; then
411 sed "s#^FAI_DEBOOTSTRAP=.*#FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"#" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
414 # does this suck? YES!
415 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
417 unstable) SUITE='sid' ;;
418 # make sure that we *NEVER* write any broken suite name to sources.list,
419 # otherwise we won't be able to adjust it one next (correct) execution
426 *) echo "Sorry, $SUITE is not a valid Debian suite, exiting.">&2; bailout 1 ;;
429 DIST=" etch\| stable\| lenny\| squeeze\| testing\| sid\| unstable"
430 sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
431 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" ; do
432 if [ -n "$file" ] ; then
433 sed "s/^SUITE=.*/SUITE=\"$SUITE\"/" $file | sponge $file
434 sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$file" | sponge "$file"
438 # notice: activate grml-live pool only if we are building against unstable:
439 if grep -qe unstable -qe sid "$SOURCES_LIST_FILE" ; then
440 grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" || \
441 grep grml-stable "$SOURCES_LIST_FILE" | \
442 sed 's/grml-stable/grml-live/' >> "$SOURCES_LIST_FILE"
444 grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" && \
445 sed 's/.*grml-live.*/# removed grml-live repository/' "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
448 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" "$NFSROOT_CONF" ; do
449 if [ -n "$file" ] ; then
450 sed "s|^FAI_DEBOOTSTRAP=\"[a-z]* |FAI_DEBOOTSTRAP=\"$SUITE |" "$file" | sponge "$file"
454 # validate whether the specified architecture class matches the
455 # architecture (option), otherwise installation of kernel will fail
456 if echo $CLASSES | grep -qi i386 ; then
457 if ! [[ "$ARCH" == "i386" ]] ; then
458 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
459 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
460 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
464 elif echo $CLASSES | grep -qi amd64 ; then
465 if ! [[ "$ARCH" == "amd64" ]] ; then
466 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
467 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
468 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
474 if grep -q -- 'FAI_DEBOOTSTRAP_OPTS.*--arch' "$NFSROOT_CONF" ; then
475 sed "s/--arch [a-z0-9]* /--arch $ARCH /" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
477 sed "s|^FAI_DEBOOTSTRAP_OPTS=\"\(.*\)|FAI_DEBOOTSTRAP_OPTS=\"--arch $ARCH \1|" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
481 # CHROOT_OUTPUT - execute FAI {{{
482 if [ -n "$BUILD_DIRTY" ]; then
483 log "Skipping stage 'fai' as requested via option -B"
484 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
486 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
488 # provide inform fai about the ISO we build
489 [ -d "$CHROOT_OUTPUT/etc/" ] || mkdir -p "$CHROOT_OUTPUT/etc/"
490 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
491 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
492 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
494 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
495 FAI_ACTION=softupdate
497 FAI_ACTION=dirinstall
500 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
501 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
502 log "Error: does not look like you have a working chroot. Updating/building not possible."
503 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
509 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
510 log "Skiping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
511 ewarn "Skiping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
513 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
515 if [ -n "${MIRROR_DIRECTORY}" ] ; then
516 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
517 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
520 log "Executed FAI command line:"
521 log "BUILD_ONLY=$BUILD_ONLY fai $VERBOSE -C $GRML_FAI_CONFIG -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS"
522 BUILD_ONLY="$BUILD_ONLY" fai $VERBOSE -C "$GRML_FAI_CONFIG" -c"$CLASSES" -u \
523 "$HOSTNAME" $FAI_ACTION "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
524 RC="$PIPESTATUS" # notice: bash-only
526 FORCE_ISO_REBUILD=true
528 if [ "$RC" != 0 ] ; then
529 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
530 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
533 log "Setting /etc/grml_version to $GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]"
534 echo "$GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]" > $CHROOT_OUTPUT/etc/grml_version
535 chmod 644 $CHROOT_OUTPUT/etc/grml_version
536 einfo "Rebuilding initramfs"
537 # make sure new /etc/grml_version reaches the initramfs:
538 # chroot $CHROOT_OUTPUT update-initramfs -u -t => might break when using kernel-package :(
539 chroot $CHROOT_OUTPUT update-initramfs -u -k all
543 # Remove all FAI logs from chroot if class RELEASE is used:
544 if [ -f "$CHROOT_OUTPUT"/etc/grml_fai_release ] ; then
545 rm -rf "$CHROOT_OUTPUT"/var/log/fai/*
548 # make sure we don't leave any mounts - FAI doesn't remove them always
549 umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
550 umount $CHROOT_OUTPUT/sys 2>/dev/null || /bin/true
551 umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
552 umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
554 [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
556 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
558 CHECKLOG=/var/log/fai/$HOSTNAME/last
559 if [ -r "$CHECKLOG/software.log" ] ; then
560 # 1 errors during executing of commands
561 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
562 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
563 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
564 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
565 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
568 if [ -r "$CHECKLOG/shell.log" ] ; then
569 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
572 if [ -n "$ERROR" ] ; then
573 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
574 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
575 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
579 log "Finished execution of stage 'fai dirinstall' [$(date)]"
580 einfo "Finished execution of stage 'fai dirinstall'"
583 einfo "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
584 log "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
590 # package validator {{{
591 CHECKLOG=/var/log/fai/$HOSTNAME/last
593 if [ -r "$CHECKLOG/package_errors.log" ] && grep -q '[a-z]' "$CHECKLOG/package_errors.log" ; then
595 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
596 eerror "The following packages were requested for installation but could not be processed:"
597 cat $CHECKLOG/package_errors.log
598 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
602 ewarn "The following packages were requested for installation but could not be processed:"
603 cat $CHECKLOG/package_errors.log
609 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
610 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
611 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
614 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
615 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
616 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
617 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
620 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
621 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
623 if [ -z "$NO_ADDONS" ] ; then
624 [ -d "$BUILD_OUTPUT"/boot/addons ] || mkdir -p "$BUILD_OUTPUT"/boot/addons
625 if [ -r "$TEMPLATE_DIRECTORY"/boot/addons/memtest ] ; then
626 log "Installing $TEMPLATE_DIRECTORY/boot/addons/memtest"
627 cp "$TEMPLATE_DIRECTORY"/boot/addons/memtest "$BUILD_OUTPUT"/boot/addons/memtest
628 elif [ -r /boot/memtest86+.bin ] ; then
629 log "Installing /boot/memtest86+.bin"
630 cp /boot/memtest86+.bin "$BUILD_OUTPUT"/boot/addons/memtest
632 ewarn "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
633 log "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
638 # if we don't have an initrd we a) can't boot and b) there was an error
639 # during build, so check for the file:
640 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
641 if [ -n "$INITRD" ] ; then
642 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.gz
643 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
645 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
646 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
650 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
651 if [ -n "$KERNEL_IMAGE" ] ; then
652 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/linux26
654 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
655 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
659 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
660 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
661 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
662 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
666 # *always* copy files to output directory so the variables
667 # get adjusted according to the build
668 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
670 if [ -n "$NO_ADDONS" ] ; then
671 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
672 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
674 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
675 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
676 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
678 # copy only files so we can handle bsd4grml on its own
679 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
680 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
683 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
684 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
685 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
687 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
688 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
690 log "bsd4grml addon not found, skipping therefore."
691 ewarn "bsd4grml addon not found, skipping therefore." ; eend 0
695 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
698 if ! [ -d ${TEMPLATE_DIRECTORY}/boot/grub ] ; then
699 log "grub templates do not exist, skipping therefore."
700 ewarn "grub templates do not exist, skipping therefore." ; eend 0
702 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
703 cp -a ${TEMPLATE_DIRECTORY}/boot/grub "$BUILD_OUTPUT"/boot/
706 # make sure we have recent template files available, otherwise updating
707 # the strings like $GRML_NAME and $VERSION might be out of date
708 cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
711 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
712 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
713 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
717 [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML
718 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/
720 # adjust boot splash information:
721 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
722 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
723 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
725 if [ -r "$BUILD_OUTPUT"/GRML/grml-version ] ; then
726 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version
727 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/grml-version
730 # make sure the squashfs filename is set accordingly:
731 SQUASHFS_NAME="$GRML_NAME.squashfs"
733 if [ -n "$NO_BOOTID" ] ; then
734 log 'Skipping bootid feature as requested via $NO_BOOTID.'
735 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
737 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
738 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
739 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
740 log "Generating /conf/bootid.txt with entry ${BOOTID}."
741 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
745 # adjust all variables in the templates with the according distribution information
746 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
747 "${BUILD_OUTPUT}"/boot/grub/* ; do
748 if [ -r "${file}" ] ; then
749 sed -i "s/%ARCH%/$ARCH/g" "${file}"
750 sed -i "s/%DATE%/$DATE/g" "${file}"
751 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
752 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
753 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
754 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
755 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
756 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
757 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
758 sed -i "s/%VERSION%/$VERSION/g" "${file}"
760 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s/ boot=live/ boot=live $DEFAULT_BOOTOPTIONS/" "${file}"
762 if [ -n "$NO_BOOTID" ] ; then
763 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
765 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
770 # adjust bootsplash accordingly but make sure the string has the according lenght
771 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
772 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
773 for file in f4 f5 ; do
774 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
775 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
776 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
780 # generate addon list
781 rm "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
782 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
783 include_name=$(basename "$name")
784 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
787 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
788 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
789 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
790 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
791 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
792 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
794 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
795 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
798 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
799 if [ ! -n "$NO_ADDONS" ] ; then
800 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
802 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
803 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
804 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
805 else # assume we are building a custom distribution:
806 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
807 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
808 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
809 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
811 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
815 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
816 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
817 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
821 # use old style console based isolinux method only if requested:
822 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
823 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
824 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
825 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
826 einfo "include for console.cfg already foud, nothing to do."
829 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
830 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
831 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
835 log 'Using graphical boot menu.'
836 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
837 log "include for vesamenu.cfg already foud, nothing to do."
839 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
840 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
844 # jump back to grub from bsd4grml (/boot/grub/stage2):
847 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
848 if [ -e "$BUILD_OUTPUT"/boot/grub/core.img ]; then
854 for file in "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 \
855 "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.cfg \
856 "$BUILD_OUTPUT"/boot/isolinux/*.cfg \
857 "$BUILD_OUTPUT"/boot/grub/grub.cfg \
858 "$BUILD_OUTPUT"/boot/grub/menu.lst ; do
859 if [ -e "$file" ] ; then
860 sed -i -e "s!%GRUB_VERSION%!$GRUB_VERSION!g" \
861 -e "s!%GRUB_LEGACY%!$GRUB_LEGACY!g" "$file"
865 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
868 if [ -e "$BUILD_OUTPUT"/boot/grub/$GRUB_LEGACY ]; then
869 sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/menu.lst
870 sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/grub.cfg
871 elif [ -e "$BUILD_OUTPUT"/boot/grub/menu.lst -a -e "$BUILD_OUTPUT"/boot/grub/grub.cfg ] ; then
872 sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/menu.lst
873 sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/grub.cfg
876 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
877 if ! [ -r "$DPKG_LIST" ] ; then
878 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
880 einfo "Storing package list information as /GRML/${GRML_NAME}-packages.txt on ISO."
881 cp "$DPKG_LIST" "${BUILD_OUTPUT}/GRML/${GRML_NAME}-packages.txt"
885 # autostart for Windows:
886 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
887 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
891 if [ -n "$NO_WINDOWS_BINARIES" ] ; then
892 log "Skipping download of windows binaries as requested via \$NO_WINDOWS_BINARIES."
893 einfo "Skipping download of windows binaries as requested via \$NO_WINDOWS_BINARIES."
896 if [ -f "$BUILD_OUTPUT"/windows/putty.exe ] ; then
897 log "Skipping stage 'WINDOWS_BINARIES' as $BUILD_OUTPUT/windows exists already."
898 ewarn "Skipping stage 'WINDOWS_BINARIES' as $BUILD_OUTPUT/windows exists already." ; eend 0
900 if ! [ -d "$BUILD_OUTPUT"/windows ] ; then
901 mkdir "$BUILD_OUTPUT"/windows
902 ( cd "$BUILD_OUTPUT"/windows
903 for file in pageant plink pscp psftp putty puttygen ; do
904 wget -O ${file}.exe ${WINDOWS_BINARIES}/${file}.exe
905 md5sum ${file}.exe > ${file}.exe.md5
909 log "Finished execution of stage 'WINDOWS_BINARIES' [$(date)]"
910 einfo "Finished execution of stage 'WINDOWS_BINARIES'" ; eend 0
914 FORCE_ISO_REBUILD=true
915 einfo "Finished execution of stage 'boot'" ; eend 0
918 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
919 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
923 # support installation of local files into the chroot/ISO
924 if [ -n "$CHROOT_INSTALL" ] ; then
925 if ! [ -d "$CHROOT_INSTALL" ] ; then
926 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
927 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
929 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
930 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
931 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
933 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
934 FORCE_ISO_REBUILD=true
938 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
939 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
940 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
941 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
942 log "Skipping stage 'squashfs' as requested via option -q"
943 ewarn "Skipping stage 'squashfs' as requested via option -q" ; eend 0
945 [ -d "$BUILD_OUTPUT"/live ] || mkdir "$BUILD_OUTPUT"/live
946 # make sure we don't leave (even an empty) base.tgz:
947 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
949 # if unconfigured default to squashfs-tools' mksquashfs binary
950 if [ -z "$SQUASHFS_BINARY" ] ; then
951 SQUASHFS_BINARY='mksquashfs'
954 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
955 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
956 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
958 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
959 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
963 # use sane defaults if $SQUASHFS_OPTIONS isn't set
964 if [ -z "$SQUASHFS_OPTIONS" ] ; then
965 # use blocksize 256k as this gives best result with regards to time + compression
966 SQUASHFS_OPTIONS="-b 256k"
968 # set lzma compression by default, unless -z option has been specified on command line
969 if [ -z "$SQUASHFS_ZLIB" ] ; then
970 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp lzma"
974 # support exclusion of files via exclude-file:
975 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
976 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE"
979 # get rid of unnecessary files when building grml-small for final release:
980 if echo "$CLASSES" | grep -q GRML_SMALL ; then
981 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
985 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
987 # informational stuff
988 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
989 [ -n "$SQUASHFS_ZLIB" ] && SQUASHFS_INFO_MSG="$SQUASHFS_INFO_MSG $SQUASHFS_ZLIB"
990 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
991 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
993 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS $SQUASHFS_ZLIB"
995 if $SQUASHFS_BINARY $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \
996 -noappend $SQUASHFS_OPTIONS $SQUASHFS_ZLIB 2>"${SQUASHFS_STDERR}" ; then
997 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/filesystem.module
998 log "Finished execution of stage 'squashfs' [$(date)]"
999 einfo "Finished execution of stage 'squashfs'" ; eend 0
1001 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1002 log "$(cat $SQUASHFS_STDERR)"
1003 eerror "Error: there was a critical error executing stage 'squashfs':"
1004 cat "${SQUASHFS_STDERR}"
1009 FORCE_ISO_REBUILD=true
1012 # create md5sum file:
1013 ( cd $BUILD_OUTPUT/GRML &&
1014 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1017 # ISO_OUTPUT - mkisofs {{{
1018 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1019 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1021 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1022 BOOT_FILE="boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1023 elif [ "$BOOT_METHOD" = "grub" ] ; then
1024 BOOT_FILE="boot/grub/stage2"
1027 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1028 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1029 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1030 elif [ -n "$SKIP_MKISOFS" ] ; then
1031 log "Skipping stage 'iso build' as requested via option -n"
1032 ewarn "Skipping stage 'iso build' as requested via option -n" ; eend 0
1034 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1036 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1037 log "Forcing rebuild of ISO because files on ISO have been modified."
1038 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1041 # support mkisofs as well as genisoimage
1042 if which mkisofs >/dev/null 2>&1; then
1044 elif which genisoimage >/dev/null 2>&1; then
1045 MKISOFS='genisoimage'
1047 log "Error: neither mkisofs nor genisoimage available - can not create ISO."
1048 eerror "Error: neither mkisofs nor genisoimage available - can not create ISO." ; eend 1
1053 if cd "$BUILD_OUTPUT" ; then
1054 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J -no-emul-boot -boot-load-size 4 -boot-info-table -b $BOOT_FILE -o ${ISO_OUTPUT}/${ISO_NAME} ."
1055 "$MKISOFS" -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1056 -l -r -J -no-emul-boot -boot-load-size 4 -boot-info-table \
1057 -b $BOOT_FILE -no-pad \
1058 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1060 # pad the output ISO to multiples of 256 KiB for partition table support
1061 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1062 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1063 siz=$((cyls * 16 * 32 * 512)) # size after padding
1064 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1065 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1067 # support disabling hybrid ISO image
1068 if [ "$HYBRID_METHOD" = "disable" ] ; then\
1069 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1070 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1072 # use isohybrid only on request
1073 elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
1074 if ! which isohybrid >/dev/null 2>&1 ; then
1075 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1077 log "Creating hybrid ISO file with isohybrid method"
1078 einfo "Creating hybrid ISO file with isohybrid method"
1079 # Notes for consideration:
1080 # "-entry 4 -type 1c"
1081 # * using 4 as the partition number is supposed to help with BIOSes
1082 # that only support USB-Zip boot
1083 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1084 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1085 # to get the BIOS even look at the partition created by isohybrid
1086 isohybrid "${ISO_OUTPUT}/${ISO_NAME}"
1089 # by default use our manifold boot method:
1091 # isoinfo is part of both mkisofs and genisoimage so we're good
1092 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1093 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN;1 *$/s//\1/p')
1094 if ! [ -r boot/grub/core.img ] ; then
1095 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1096 elif [ "${bootoff:-0}" -lt 1 ] ; then
1097 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1099 log "Creating hybrid ISO file with manifold method"
1100 einfo "Creating hybrid ISO file with manifold method"
1101 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1102 # 512 bytes: MBR, partition table, load GRUB 2
1103 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1104 # pad to a whole of 2048 bytes (one CD sector)
1105 dd if=/dev/zero bs=512 count=3 2>/dev/null
1106 # append GRUB 2 (must be <=30720 bytes)
1107 cat boot/grub/core.img
1109 # read only one but 2048-byte sized (scale: << 2) sector
1110 echo $bootoff $bootoff | \
1111 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1112 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1117 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1118 case $CLASSES in *RELEASE*)
1121 if cd $ISO_OUTPUT ; then
1122 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1123 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1124 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1125 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1134 if [ "$RC" = 0 ] ; then
1135 log "Finished execution of stage 'iso build' [$(date)]"
1136 einfo "Finished execution of stage 'iso build'" ; eend 0
1138 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1139 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1145 # log build information to database if grml-live-db is installed and enabled {{{
1147 if [ -d /usr/share/grml-live-db ] ; then
1150 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1151 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1152 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1153 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1155 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1156 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1157 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1161 # disable by default for now, not sure whether really everyone is using a local db file
1162 #if ! touch "$DPKG_DATABASE" ; then
1163 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1167 if ! [ -r "$DPKG_LIST" ] ; then
1168 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1169 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1171 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1172 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1173 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1176 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1192 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1193 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1195 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1197 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1201 ## END OF FILE #################################################################
1202 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=3