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/*
565 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
567 CHECKLOG=/var/log/fai/$HOSTNAME/last
568 if [ -r "$CHECKLOG/software.log" ] ; then
569 # 1 errors during executing of commands
570 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
571 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
572 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
573 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
574 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
577 if [ -r "$CHECKLOG/shell.log" ] ; then
578 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
581 if [ -n "$ERROR" ] ; then
582 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
583 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
584 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
588 log "Finished execution of stage 'fai dirinstall' [$(date)]"
589 einfo "Finished execution of stage 'fai dirinstall'"
592 einfo "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
593 log "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
599 # package validator {{{
600 CHECKLOG=/var/log/fai/$HOSTNAME/last
602 if [ -r "$CHECKLOG/package_errors.log" ] && grep -q '[a-z]' "$CHECKLOG/package_errors.log" ; then
604 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
605 eerror "The following packages were requested for installation but could not be processed:"
606 cat $CHECKLOG/package_errors.log
607 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
611 ewarn "The following packages were requested for installation but could not be processed:"
612 cat $CHECKLOG/package_errors.log
618 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
619 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
620 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
623 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
624 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
625 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
626 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
629 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
630 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
632 if [ -z "$NO_ADDONS" ] ; then
633 [ -d "$BUILD_OUTPUT"/boot/addons ] || mkdir -p "$BUILD_OUTPUT"/boot/addons
634 if [ -r "$TEMPLATE_DIRECTORY"/boot/addons/memtest ] ; then
635 log "Installing $TEMPLATE_DIRECTORY/boot/addons/memtest"
636 cp "$TEMPLATE_DIRECTORY"/boot/addons/memtest "$BUILD_OUTPUT"/boot/addons/memtest
637 elif [ -r /boot/memtest86+.bin ] ; then
638 log "Installing /boot/memtest86+.bin"
639 cp /boot/memtest86+.bin "$BUILD_OUTPUT"/boot/addons/memtest
641 ewarn "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
642 log "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
647 # if we don't have an initrd we a) can't boot and b) there was an error
648 # during build, so check for the file:
649 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
650 if [ -n "$INITRD" ] ; then
651 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.gz
652 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
654 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
655 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
659 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
660 if [ -n "$KERNEL_IMAGE" ] ; then
661 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/linux26
663 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
664 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
668 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
669 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
670 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
671 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
675 # *always* copy files to output directory so the variables
676 # get adjusted according to the build
677 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
679 if [ -n "$NO_ADDONS" ] ; then
680 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
681 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
683 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
684 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
685 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
687 # copy only files so we can handle bsd4grml on its own
688 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
689 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
692 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
693 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
694 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
696 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
697 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
699 log "bsd4grml addon not found, skipping therefore."
700 ewarn "bsd4grml addon not found, skipping therefore." ; eend 0
704 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
707 if ! [ -d ${TEMPLATE_DIRECTORY}/boot/grub ] ; then
708 log "grub templates do not exist, skipping therefore."
709 ewarn "grub templates do not exist, skipping therefore." ; eend 0
711 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
712 cp -a ${TEMPLATE_DIRECTORY}/boot/grub "$BUILD_OUTPUT"/boot/
715 # make sure we have recent template files available, otherwise updating
716 # the strings like $GRML_NAME and $VERSION might be out of date
717 cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
720 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
721 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
722 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
726 [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML
727 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/
729 # adjust boot splash information:
730 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
731 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
732 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
734 if [ -r "$BUILD_OUTPUT"/GRML/grml-version ] ; then
735 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version
736 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/grml-version
739 # make sure the squashfs filename is set accordingly:
740 SQUASHFS_NAME="$GRML_NAME.squashfs"
742 if [ -n "$NO_BOOTID" ] ; then
743 log 'Skipping bootid feature as requested via $NO_BOOTID.'
744 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
746 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
747 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
748 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
749 log "Generating /conf/bootid.txt with entry ${BOOTID}."
750 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
754 # adjust all variables in the templates with the according distribution information
755 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
756 "${BUILD_OUTPUT}"/boot/grub/* ; do
757 if [ -r "${file}" ] ; then
758 sed -i "s/%ARCH%/$ARCH/g" "${file}"
759 sed -i "s/%DATE%/$DATE/g" "${file}"
760 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
761 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
762 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
763 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
764 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
765 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
766 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
767 sed -i "s/%VERSION%/$VERSION/g" "${file}"
769 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s/ boot=live/ boot=live $DEFAULT_BOOTOPTIONS/" "${file}"
771 if [ -n "$NO_BOOTID" ] ; then
772 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
774 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
779 # adjust bootsplash accordingly but make sure the string has the according lenght
780 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
781 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
782 for file in f4 f5 ; do
783 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
784 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
785 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
789 # generate addon list
790 rm "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
791 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
792 include_name=$(basename "$name")
793 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
796 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
797 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
798 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
799 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
800 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
801 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
803 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
804 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
807 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
808 if [ ! -n "$NO_ADDONS" ] ; then
809 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
811 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
812 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
813 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
814 else # assume we are building a custom distribution:
815 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
816 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
817 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
818 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
820 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
824 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
825 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
826 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
830 # use old style console based isolinux method only if requested:
831 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
832 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
833 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
834 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
835 einfo "include for console.cfg already foud, nothing to do."
838 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
839 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
840 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
844 log 'Using graphical boot menu.'
845 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
846 log "include for vesamenu.cfg already foud, nothing to do."
848 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
849 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
853 # jump back to grub from bsd4grml (/boot/grub/stage2):
856 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
857 if [ -e "$BUILD_OUTPUT"/boot/grub/core.img ]; then
863 for file in "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 \
864 "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.cfg \
865 "$BUILD_OUTPUT"/boot/isolinux/*.cfg \
866 "$BUILD_OUTPUT"/boot/grub/grub.cfg \
867 "$BUILD_OUTPUT"/boot/grub/menu.lst ; do
868 if [ -e "$file" ] ; then
869 sed -i -e "s!%GRUB_VERSION%!$GRUB_VERSION!g" \
870 -e "s!%GRUB_LEGACY%!$GRUB_LEGACY!g" "$file"
874 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
877 if [ -e "$BUILD_OUTPUT"/boot/grub/$GRUB_LEGACY ]; then
878 sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/menu.lst
879 sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/grub.cfg
880 elif [ -e "$BUILD_OUTPUT"/boot/grub/menu.lst -a -e "$BUILD_OUTPUT"/boot/grub/grub.cfg ] ; then
881 sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/menu.lst
882 sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/grub.cfg
885 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
886 if ! [ -r "$DPKG_LIST" ] ; then
887 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
889 einfo "Storing package list information as /GRML/${GRML_NAME}-packages.txt on ISO."
890 cp "$DPKG_LIST" "${BUILD_OUTPUT}/GRML/${GRML_NAME}-packages.txt"
894 # autostart for Windows:
895 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
896 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
900 if [ -n "$NO_WINDOWS_BINARIES" ] ; then
901 log "Skipping download of windows binaries as requested via \$NO_WINDOWS_BINARIES."
902 einfo "Skipping download of windows binaries as requested via \$NO_WINDOWS_BINARIES."
905 if [ -f "$BUILD_OUTPUT"/windows/putty.exe ] ; then
906 log "Skipping stage 'WINDOWS_BINARIES' as $BUILD_OUTPUT/windows exists already."
907 ewarn "Skipping stage 'WINDOWS_BINARIES' as $BUILD_OUTPUT/windows exists already." ; eend 0
909 if ! [ -d "$BUILD_OUTPUT"/windows ] ; then
910 mkdir "$BUILD_OUTPUT"/windows
911 ( cd "$BUILD_OUTPUT"/windows
912 for file in pageant plink pscp psftp putty puttygen ; do
913 wget -O ${file}.exe ${WINDOWS_BINARIES}/${file}.exe
914 md5sum ${file}.exe > ${file}.exe.md5
918 log "Finished execution of stage 'WINDOWS_BINARIES' [$(date)]"
919 einfo "Finished execution of stage 'WINDOWS_BINARIES'" ; eend 0
923 FORCE_ISO_REBUILD=true
924 einfo "Finished execution of stage 'boot'" ; eend 0
927 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
928 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
932 # support installation of local files into the chroot/ISO
933 if [ -n "$CHROOT_INSTALL" ] ; then
934 if ! [ -d "$CHROOT_INSTALL" ] ; then
935 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
936 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
938 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
939 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
940 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
942 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
943 FORCE_ISO_REBUILD=true
947 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
948 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
949 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
950 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
951 log "Skipping stage 'squashfs' as requested via option -q"
952 ewarn "Skipping stage 'squashfs' as requested via option -q" ; eend 0
954 [ -d "$BUILD_OUTPUT"/live ] || mkdir "$BUILD_OUTPUT"/live
955 # make sure we don't leave (even an empty) base.tgz:
956 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
958 # if unconfigured default to squashfs-tools' mksquashfs binary
959 if [ -z "$SQUASHFS_BINARY" ] ; then
960 SQUASHFS_BINARY='mksquashfs'
963 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
964 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
965 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
967 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
968 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
972 # use sane defaults if $SQUASHFS_OPTIONS isn't set
973 if [ -z "$SQUASHFS_OPTIONS" ] ; then
974 # use blocksize 256k as this gives best result with regards to time + compression
975 SQUASHFS_OPTIONS="-b 256k"
977 # set lzma/xz compression by default, unless -z option has been specified on command line
978 if [ -z "$SQUASHFS_ZLIB" ] ; then
979 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
981 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
985 # support exclusion of files via exclude-file:
986 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
987 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE"
990 # get rid of unnecessary files when building grml-small for final release:
991 if echo "$CLASSES" | grep -q GRML_SMALL ; then
992 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
996 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
998 # informational stuff
999 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1000 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1001 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1003 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1005 if $SQUASHFS_BINARY $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \
1006 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1007 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/filesystem.module
1008 log "Finished execution of stage 'squashfs' [$(date)]"
1009 einfo "Finished execution of stage 'squashfs'" ; eend 0
1011 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1012 log "$(cat $SQUASHFS_STDERR)"
1013 eerror "Error: there was a critical error executing stage 'squashfs':"
1014 cat "${SQUASHFS_STDERR}"
1019 FORCE_ISO_REBUILD=true
1022 # create md5sum file:
1023 ( cd $BUILD_OUTPUT/GRML &&
1024 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1027 # ISO_OUTPUT - mkisofs {{{
1028 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1029 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1031 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1032 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1033 elif [ "$BOOT_METHOD" = "grub" ] ; then
1034 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/grub/stage2"
1035 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1036 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1039 # Just until http://bts.grml.org/grml/issue945 has been resolved.
1040 # HYBRID_METHOD defaults to manifold, so make sure the default works OOTB.
1041 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1042 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1043 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1044 HYBRID_METHOD='grub2'
1048 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1049 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1050 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1051 elif [ -n "$SKIP_MKISOFS" ] ; then
1052 log "Skipping stage 'iso build' as requested via option -n"
1053 ewarn "Skipping stage 'iso build' as requested via option -n" ; eend 0
1055 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1057 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1058 log "Forcing rebuild of ISO because files on ISO have been modified."
1059 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1062 # support mkisofs as well as genisoimage
1063 if which mkisofs >/dev/null 2>&1; then
1065 elif which genisoimage >/dev/null 2>&1; then
1066 MKISOFS='genisoimage'
1068 log "Error: neither mkisofs nor genisoimage available - can not create ISO."
1069 eerror "Error: neither mkisofs nor genisoimage available - can not create ISO." ; eend 1
1074 if cd "$BUILD_OUTPUT" ; then
1075 if [ "$BOOT_METHOD" = "grub2" ]; then
1076 # make a 2048-byte bootsector for El Torito
1077 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1078 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1079 echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
1080 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1082 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1083 "$MKISOFS" -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1084 -l -r -J $BOOT_ARGS -no-pad \
1085 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1086 # both of these need core.img there, so it’s easier to write it here
1087 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1088 # must be <= 30720 bytes
1089 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1090 conv=notrunc bs=512 seek=4 2>/dev/null
1093 # pad the output ISO to multiples of 256 KiB for partition table support
1094 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1095 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1096 siz=$((cyls * 16 * 32 * 512)) # size after padding
1097 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1098 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1100 # support disabling hybrid ISO image
1101 if [ "$HYBRID_METHOD" = "disable" ] ; then\
1102 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1103 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1105 # use isohybrid only on request
1106 elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
1107 if ! which isohybrid >/dev/null 2>&1 ; then
1108 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1110 log "Creating hybrid ISO file with isohybrid method"
1111 einfo "Creating hybrid ISO file with isohybrid method"
1112 # Notes for consideration:
1113 # "-entry 4 -type 1c"
1114 # * using 4 as the partition number is supposed to help with BIOSes
1115 # that only support USB-Zip boot
1116 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1117 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1118 # to get the BIOS even look at the partition created by isohybrid
1119 isohybrid "${ISO_OUTPUT}/${ISO_NAME}"
1122 # by default use our manifold boot method:
1124 # isoinfo is part of both mkisofs and genisoimage so we're good
1125 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1126 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN;1 *$/s//\1/p')
1127 if ! [ -r boot/grub/core.img ] ; then
1128 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1129 elif [ "${bootoff:-0}" -lt 1 ] ; then
1130 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1132 log "Creating hybrid ISO file with manifold method"
1133 einfo "Creating hybrid ISO file with manifold method"
1134 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1135 # 512 bytes: MBR, partition table, load GRUB 2
1136 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1138 # read only one but 2048-byte sized (scale: << 2) sector
1139 echo $bootoff $bootoff | \
1140 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1141 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1146 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1147 case $CLASSES in *RELEASE*)
1150 if cd $ISO_OUTPUT ; then
1151 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1152 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1153 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1154 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1163 if [ "$RC" = 0 ] ; then
1164 log "Finished execution of stage 'iso build' [$(date)]"
1165 einfo "Finished execution of stage 'iso build'" ; eend 0
1167 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1168 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1174 # log build information to database if grml-live-db is installed and enabled {{{
1176 if [ -d /usr/share/grml-live-db ] ; then
1179 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1180 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1181 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1182 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1184 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1185 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1186 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1190 # disable by default for now, not sure whether really everyone is using a local db file
1191 #if ! touch "$DPKG_DATABASE" ; then
1192 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1196 if ! [ -r "$DPKG_LIST" ] ; then
1197 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1198 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1200 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1201 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1202 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1205 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1221 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1222 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1224 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1226 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1230 ## END OF FILE #################################################################
1231 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=3