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.14.1'
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/XZ 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
134 # umount all directories {{{
136 # make sure we don't leave any mounts - FAI doesn't remove them always
137 umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
138 umount $CHROOT_OUTPUT/sys 2>/dev/null || /bin/true
139 umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
140 umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
141 [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
147 rm -f /var/run/fai/fai_softupdate_is_running \
148 /var/run/fai/FAI_INSTALLATION_IN_PROGRESS
149 [ -n "$SQUASHFS_STDERR" ] && rm -rf "$SQUASHFS_STDERR"
151 [ -n "$1" ] && EXIT="$1" || EXIT="1"
152 [ -n "$2" ] && eerror "$2">&2
153 log "------------------------------------------------------------------------------"
156 trap bailout 1 2 3 3 6 9 14 15 EXIT
160 [ -n "$LOGFILE" ] || LOGFILE=/var/log/grml-live.log
162 chown root:adm $LOGFILE
166 # some important functions {{{
169 # usage: log "string to log"
170 log() { echo "$*" >> $LOGFILE ; }
172 # cut string at character number int = $1
173 # usage: cut_string 5 "1234567890" will output "12345"
175 [ -n "$2" ] || return 1
176 echo "$2" | head -c "$1"; echo -ne "\n"
179 # prepend int = $1 spaces before string = $2
180 # usage: extend_string_begin 5 "123" will output " 123"
181 extend_string_begin() {
182 [ -n "$2" ] || return 1
183 local COUNT="$(echo $2 | wc -c)"
184 local FILL="$(expr $COUNT - $1)"
185 while [ "$FILL" -gt 1 ] ; do
187 local FILL=$(expr $FILL - 1)
189 while [ "$FILL" -lt 1 ] ; do
191 local FILL=$(expr $FILL + 1)
193 echo "$2" | head -c "$1"; echo -ne "\n"
196 # append int = $1 spaces to string = $2
197 # usage: extend_string_begin 5 "123" will output "123 "
198 extend_string_end() {
199 [ -n "$2" ] || return 1
200 echo -n "$2" | head -c "$1"
201 local COUNT="$(echo $2 | wc -c)"
202 local FILL="$(expr $COUNT - $1)"
203 while [ "$FILL" -gt 1 ] ; do
205 local FILL=$(expr $FILL - 1)
207 while [ "$FILL" -lt 1 ] ; do
209 local FILL=$(expr $FILL + 1)
215 # read local (non-packaged) configuration {{{
216 LOCAL_CONFIG=/etc/grml/grml-live.local
217 if [ -r "$LOCAL_CONFIG" ] ; then
218 log "Sourcing $LOCAL_CONFIG"
221 log "No $LOCAL_CONFIG found, not sourcing it"
226 # command line parsing {{{
227 while getopts "a:C:c:d:g:i:I:o:r:s:t:v:bBFnquVz" opt; do
232 c) CLASSES="$OPTARG" ;;
233 C) CONFIG="$OPTARG" ;;
235 g) GRML_NAME="$OPTARG" ;;
236 i) ISO_NAME="$OPTARG" ;;
237 I) CHROOT_INSTALL="$OPTARG" ;;
239 o) OUTPUT="$OPTARG" ;;
240 q) SKIP_MKSQUASHFS=1 ;;
241 r) RELEASENAME="$OPTARG" ;;
242 s) SUITE="$OPTARG" ;;
243 t) TEMPLATE_DIRECTORY="$OPTARG";;
244 v) VERSION="$OPTARG" ;;
248 z) SQUASHFS_ZLIB=1 ;;
249 ?) echo "invalid option -$OPTARG" >&2; bailout 1 ;;
252 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
255 # assume sane defaults (if not set already) {{{
256 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
257 [ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux'
258 [ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_MEDIUM,I386"
259 [ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)"
260 [ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators '
261 [ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml"
262 [ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png'
263 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
264 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai'
265 [ -n "$GRML_NAME" ] || GRML_NAME='grml'
266 [ -n "$HOSTNAME" ] || HOSTNAME='grml'
267 [ -n "$HYBRID_METHOD" ] || HYBRID_METHOD='manifold'
268 [ -n "$NFSROOT_CONF" ] || NFSROOT_CONF='/etc/grml/fai/make-fai-nfsroot.conf'
269 [ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks'
270 [ -n "$SQUASHFS_EXCLUDES_FILE " ] || SQUASHFS_EXCLUDES_FILE='/etc/grml/fai/squashfs-excludes'
271 [ -n "$SUITE" ] || SUITE='squeeze'
272 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
273 [ -n "$USERNAME" ] || USERNAME='grml'
274 [ -n "$VERSION" ] || VERSION='0.0.1'
275 [ -n "$WINDOWS_BINARIES" ] || WINDOWS_BINARIES='http://the.earth.li/~sgtatham/putty/latest/x86/'
277 # output specific stuff, depends on $OUTPUT (iff not set):
278 [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live'
279 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
280 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
281 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
284 # some misc checks before executing FAI {{{
285 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
286 specify it on the command line using the -c option."
287 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
288 specify it on the command line using the -o option."
290 # trim characters that are known to cause problems inside $GRML_NAME;
291 # for example isolinux does not like '-' inside the directory name
292 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
294 # export variables to have them available in fai scripts:
295 [ -n "$GRML_NAME" ] && export GRML_NAME="$GRML_NAME"
296 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
299 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
300 # this was default behaviour until grml-live 0.9.34:
301 if [ -n "$ZERO_LOGFILE" ] ; then
302 PRESERVE_LOGFILE='' # make sure it's cleaned then
303 ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
304 ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
309 # ask user whether the setup is ok {{{
310 if [ -z "$FORCE" ] ; then
312 echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
314 echo " FAI classes: $CLASSES"
315 [ -r "$LOCAL_CONFIG" ] && echo " Local config: /etc/grml/grml-live.local"
316 [ -n "$CONFIG" ] && echo " Configuration: $CONFIG"
317 echo " main directory: $OUTPUT"
318 [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT"
319 [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT"
320 [ -n "$ISO_OUTPUT" ] && echo " ISO target: $ISO_OUTPUT"
321 [ -n "$GRML_NAME" ] && echo " Grml name: $GRML_NAME"
322 [ -n "$RELEASENAME" ] && echo " Release name: $RELEASENAME"
323 [ -n "$DATE" ] && echo " Build date: $DATE"
324 [ -n "$VERSION" ] && echo " Grml version: $VERSION"
325 [ -n "$SUITE" ] && echo " Debian suite: $SUITE"
326 [ -n "$ARCH" ] && echo " Architecture: $ARCH"
327 [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD"
328 [ -n "$HYBRID_METHOD" ] && echo " Hybrid method: $HYBRID_METHOD"
329 [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY"
330 [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL"
331 [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID"
332 [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature."
333 [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
334 [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS"
335 [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE"
336 [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA/XZ) compression."
337 [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
338 [ -n "$VERBOSE" ] && echo " Using VERBOSE mode."
339 [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation."
340 [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file."
341 [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file."
342 [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE."
343 [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched."
345 echo -n "Is this ok for you? [y/N] "
347 if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
348 bailout 1 "Exiting as requested."
354 # clean/zero/remove logfiles {{{
356 if [ -n "$PRESERVE_LOGFILE" ] ; then
357 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
359 # make sure it is empty (as it is e.g. appended to grml-live-db)
363 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
364 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
365 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
366 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
367 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
368 rm -f /var/log/fai/"$HOSTNAME"/last \
369 /var/log/fai/"$HOSTNAME"/last-dirinstall \
370 /var/log/fai/"$HOSTNAME"/last-softupdate
375 # source config and startup {{{
376 if [ -n "$CONFIG" ] ; then
377 if ! [ -f "$CONFIG" ] ; then
378 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
379 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
382 log "Sourcing $CONFIG"
387 start_seconds=$(cut -d . -f 1 /proc/uptime)
388 log "------------------------------------------------------------------------------"
389 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
390 log "Executed grml-live command line:"
393 einfo "Logging actions to logfile $LOGFILE"
396 # on-the-fly configuration {{{
397 if [ -n "$MIRROR_DIRECTORY" ] ; then
398 if ! [ -d "$MIRROR_DIRECTORY/debian" ] ; then
399 log "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting. [$(date)]"
400 eerror "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting." ; eend 1
403 cat > "$SOURCES_LIST_FILE" << EOF
404 # NOTE: This file is *NOT* meant for manual customisation! This file is
405 # modified by grml-live and any changes might be overridden.
406 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
407 # or FAI's fcopy command with /etc/grml/fai/config/files instead!
409 echo "$MIRROR_SOURCES" >> "$SOURCES_LIST_FILE"
410 if [ -n "$GRML_LIVE_SOURCES" ] ; then
411 echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
413 elif [ -n "$GRML_LIVE_SOURCES" ] ; then
414 cat > "$SOURCES_LIST_FILE" << EOF
415 # NOTE: This file is *NOT* meant for manual customisation! This file is
416 # modified by grml-live and any changes might be overridden.
417 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
418 # or FAI's fcopy command with /etc/grml/fai/config/files instead!
420 echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
423 if [ -n "$FAI_DEBOOTSTRAP" ] ; then
424 sed "s#^FAI_DEBOOTSTRAP=.*#FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"#" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
427 # does this suck? YES!
428 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
430 unstable) SUITE='sid' ;;
431 # make sure that we *NEVER* write any broken suite name to sources.list,
432 # otherwise we won't be able to adjust it one next (correct) execution
440 *) echo "Sorry, $SUITE is not a valid Debian suite, exiting.">&2; bailout 1 ;;
443 DIST=" etch\| stable\| lenny\| squeeze\| wheezy\| testing\| sid\| unstable"
444 sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
445 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" ; do
446 if [ -n "$file" ] ; then
447 sed "s/^SUITE=.*/SUITE=\"$SUITE\"/" $file | sponge $file
448 sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$file" | sponge "$file"
452 # notice: activate grml-live pool only if we are building against unstable:
453 if grep -qwe unstable -qwe sid "$SOURCES_LIST_FILE" ; then
454 grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" || \
455 grep grml-stable "$SOURCES_LIST_FILE" | \
456 sed 's/grml-stable/grml-live/' >> "$SOURCES_LIST_FILE"
458 grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" && \
459 sed 's/.*grml-live.*/# removed grml-live repository/' "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
462 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" "$NFSROOT_CONF" ; do
463 if [ -n "$file" ] ; then
464 sed "s|^FAI_DEBOOTSTRAP=\"[a-z]* |FAI_DEBOOTSTRAP=\"$SUITE |" "$file" | sponge "$file"
468 # validate whether the specified architecture class matches the
469 # architecture (option), otherwise installation of kernel will fail
470 if echo $CLASSES | grep -qi i386 ; then
471 if ! [[ "$ARCH" == "i386" ]] ; then
472 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
473 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
474 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
478 elif echo $CLASSES | grep -qi amd64 ; then
479 if ! [[ "$ARCH" == "amd64" ]] ; then
480 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
481 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
482 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
488 if grep -q -- 'FAI_DEBOOTSTRAP_OPTS.*--arch' "$NFSROOT_CONF" ; then
489 sed "s/--arch [a-z0-9]* /--arch $ARCH /" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
491 sed "s|^FAI_DEBOOTSTRAP_OPTS=\"\(.*\)|FAI_DEBOOTSTRAP_OPTS=\"--arch $ARCH \1|" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
495 # CHROOT_OUTPUT - execute FAI {{{
496 if [ -n "$BUILD_DIRTY" ]; then
497 log "Skipping stage 'fai' as requested via option -B"
498 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
500 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
502 # provide inform fai about the ISO we build
503 [ -d "$CHROOT_OUTPUT/etc/" ] || mkdir -p "$CHROOT_OUTPUT/etc/"
504 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
505 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
506 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
508 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
509 FAI_ACTION=softupdate
511 FAI_ACTION=dirinstall
514 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
515 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
516 log "Error: does not look like you have a working chroot. Updating/building not possible."
517 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
523 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
524 log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
525 ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
527 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
529 if [ -n "${MIRROR_DIRECTORY}" ] ; then
530 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
531 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
534 log "Executed FAI command line:"
535 log "BUILD_ONLY=$BUILD_ONLY fai $VERBOSE -C $GRML_FAI_CONFIG -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS"
536 BUILD_ONLY="$BUILD_ONLY" fai $VERBOSE -C "$GRML_FAI_CONFIG" -c"$CLASSES" -u \
537 "$HOSTNAME" $FAI_ACTION "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
538 RC="$PIPESTATUS" # notice: bash-only
540 FORCE_ISO_REBUILD=true
542 if [ "$RC" != 0 ] ; then
543 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
544 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
547 log "Setting /etc/grml_version to $GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]"
548 echo "$GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]" > $CHROOT_OUTPUT/etc/grml_version
549 chmod 644 $CHROOT_OUTPUT/etc/grml_version
550 einfo "Rebuilding initramfs"
551 # make sure new /etc/grml_version reaches the initramfs:
552 # chroot $CHROOT_OUTPUT update-initramfs -u -t => might break when using kernel-package :(
553 chroot $CHROOT_OUTPUT update-initramfs -u -k all
557 # Remove all FAI logs from chroot if class RELEASE is used:
558 if [ -f "$CHROOT_OUTPUT"/etc/grml_fai_release ] ; then
559 rm -rf "$CHROOT_OUTPUT"/var/log/fai/*
564 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
566 CHECKLOG=/var/log/fai/$HOSTNAME/last
567 if [ -r "$CHECKLOG/software.log" ] ; then
568 # 1 errors during executing of commands
569 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
570 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
571 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
572 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
573 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
576 if [ -r "$CHECKLOG/shell.log" ] ; then
577 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
580 if [ -n "$ERROR" ] ; then
581 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
582 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
583 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
587 log "Finished execution of stage 'fai dirinstall' [$(date)]"
588 einfo "Finished execution of stage 'fai dirinstall'"
591 einfo "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
592 log "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
598 # package validator {{{
599 CHECKLOG=/var/log/fai/$HOSTNAME/last
601 if [ -r "$CHECKLOG/package_errors.log" ] && grep -q '[a-z]' "$CHECKLOG/package_errors.log" ; then
603 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
604 eerror "The following packages were requested for installation but could not be processed:"
605 cat $CHECKLOG/package_errors.log
606 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
610 ewarn "The following packages were requested for installation but could not be processed:"
611 cat $CHECKLOG/package_errors.log
617 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
618 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
619 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
622 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
623 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
624 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
625 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
628 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
629 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
631 if [ -z "$NO_ADDONS" ] ; then
632 [ -d "$BUILD_OUTPUT"/boot/addons ] || mkdir -p "$BUILD_OUTPUT"/boot/addons
633 if [ -r "$TEMPLATE_DIRECTORY"/boot/addons/memtest ] ; then
634 log "Installing $TEMPLATE_DIRECTORY/boot/addons/memtest"
635 cp "$TEMPLATE_DIRECTORY"/boot/addons/memtest "$BUILD_OUTPUT"/boot/addons/memtest
636 elif [ -r /boot/memtest86+.bin ] ; then
637 log "Installing /boot/memtest86+.bin"
638 cp /boot/memtest86+.bin "$BUILD_OUTPUT"/boot/addons/memtest
640 ewarn "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
641 log "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
646 # if we don't have an initrd we a) can't boot and b) there was an error
647 # during build, so check for the file:
648 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
649 if [ -n "$INITRD" ] ; then
650 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.gz
651 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
653 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
654 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
658 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
659 if [ -n "$KERNEL_IMAGE" ] ; then
660 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/linux26
662 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
663 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
667 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
668 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
669 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
670 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
674 # *always* copy files to output directory so the variables
675 # get adjusted according to the build
676 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
678 if [ -n "$NO_ADDONS" ] ; then
679 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
680 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
682 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
683 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
684 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
686 # copy only files so we can handle bsd4grml on its own
687 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
688 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
691 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
692 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
693 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
695 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
696 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
698 log "bsd4grml addon not found, skipping therefore."
699 ewarn "bsd4grml addon not found, skipping therefore." ; eend 0
703 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
706 if ! [ -d ${TEMPLATE_DIRECTORY}/boot/grub ] ; then
707 log "grub templates do not exist, skipping therefore."
708 ewarn "grub templates do not exist, skipping therefore." ; eend 0
710 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
711 cp -a ${TEMPLATE_DIRECTORY}/boot/grub "$BUILD_OUTPUT"/boot/
714 # make sure we have recent template files available, otherwise updating
715 # the strings like $GRML_NAME and $VERSION might be out of date
716 cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
719 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
720 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
721 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
725 [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML
726 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/
728 # adjust boot splash information:
729 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
730 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
731 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
733 if [ -r "$BUILD_OUTPUT"/GRML/grml-version ] ; then
734 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version
735 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/grml-version
738 # make sure the squashfs filename is set accordingly:
739 SQUASHFS_NAME="$GRML_NAME.squashfs"
741 if [ -n "$NO_BOOTID" ] ; then
742 log 'Skipping bootid feature as requested via $NO_BOOTID.'
743 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
745 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
746 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
747 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
748 log "Generating /conf/bootid.txt with entry ${BOOTID}."
749 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
753 # adjust all variables in the templates with the according distribution information
754 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
755 "${BUILD_OUTPUT}"/boot/grub/* ; do
756 if [ -r "${file}" ] ; then
757 sed -i "s/%ARCH%/$ARCH/g" "${file}"
758 sed -i "s/%DATE%/$DATE/g" "${file}"
759 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
760 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
761 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
762 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
763 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
764 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
765 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
766 sed -i "s/%VERSION%/$VERSION/g" "${file}"
768 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s/ boot=live/ boot=live $DEFAULT_BOOTOPTIONS/" "${file}"
770 if [ -n "$NO_BOOTID" ] ; then
771 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
773 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
778 # adjust bootsplash accordingly but make sure the string has the according lenght
779 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
780 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
781 for file in f4 f5 ; do
782 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
783 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
784 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
788 # generate addon list
789 rm "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
790 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
791 include_name=$(basename "$name")
792 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
795 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
796 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
797 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
798 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
799 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
800 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
802 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
803 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
806 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
807 if [ ! -n "$NO_ADDONS" ] ; then
808 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
810 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
811 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
812 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
813 else # assume we are building a custom distribution:
814 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
815 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
816 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
817 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
819 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
823 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
824 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
825 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
829 # use old style console based isolinux method only if requested:
830 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
831 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
832 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
833 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
834 einfo "include for console.cfg already foud, nothing to do."
837 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
838 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
839 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
843 log 'Using graphical boot menu.'
844 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
845 log "include for vesamenu.cfg already foud, nothing to do."
847 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
848 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
852 # jump back to grub from bsd4grml (/boot/grub/stage2):
855 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
856 if [ -e "$BUILD_OUTPUT"/boot/grub/core.img ]; then
862 for file in "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 \
863 "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.cfg \
864 "$BUILD_OUTPUT"/boot/isolinux/*.cfg \
865 "$BUILD_OUTPUT"/boot/grub/grub.cfg \
866 "$BUILD_OUTPUT"/boot/grub/menu.lst ; do
867 if [ -e "$file" ] ; then
868 sed -i -e "s!%GRUB_VERSION%!$GRUB_VERSION!g" \
869 -e "s!%GRUB_LEGACY%!$GRUB_LEGACY!g" "$file"
873 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
876 if [ -e "$BUILD_OUTPUT"/boot/grub/$GRUB_LEGACY ]; then
877 sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/menu.lst
878 sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/grub.cfg
879 elif [ -e "$BUILD_OUTPUT"/boot/grub/menu.lst -a -e "$BUILD_OUTPUT"/boot/grub/grub.cfg ] ; then
880 sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/menu.lst
881 sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/grub.cfg
884 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
885 if ! [ -r "$DPKG_LIST" ] ; then
886 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
888 einfo "Storing package list information as /GRML/${GRML_NAME}-packages.txt on ISO."
889 cp "$DPKG_LIST" "${BUILD_OUTPUT}/GRML/${GRML_NAME}-packages.txt"
893 # autostart for Windows:
894 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
895 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
899 if [ -n "$NO_WINDOWS_BINARIES" ] ; then
900 log "Skipping download of windows binaries as requested via \$NO_WINDOWS_BINARIES."
901 einfo "Skipping download of windows binaries as requested via \$NO_WINDOWS_BINARIES."
904 if [ -f "$BUILD_OUTPUT"/windows/putty.exe ] ; then
905 log "Skipping stage 'WINDOWS_BINARIES' as $BUILD_OUTPUT/windows exists already."
906 ewarn "Skipping stage 'WINDOWS_BINARIES' as $BUILD_OUTPUT/windows exists already." ; eend 0
908 if ! [ -d "$BUILD_OUTPUT"/windows ] ; then
909 mkdir "$BUILD_OUTPUT"/windows
910 ( cd "$BUILD_OUTPUT"/windows
911 for file in pageant plink pscp psftp putty puttygen ; do
912 wget -O ${file}.exe ${WINDOWS_BINARIES}/${file}.exe
913 md5sum ${file}.exe > ${file}.exe.md5
917 log "Finished execution of stage 'WINDOWS_BINARIES' [$(date)]"
918 einfo "Finished execution of stage 'WINDOWS_BINARIES'" ; eend 0
922 FORCE_ISO_REBUILD=true
923 einfo "Finished execution of stage 'boot'" ; eend 0
926 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
927 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
931 # support installation of local files into the chroot/ISO
932 if [ -n "$CHROOT_INSTALL" ] ; then
933 if ! [ -d "$CHROOT_INSTALL" ] ; then
934 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
935 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
937 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
938 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
939 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
941 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
942 FORCE_ISO_REBUILD=true
946 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
947 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
948 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
949 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
950 log "Skipping stage 'squashfs' as requested via option -q"
951 ewarn "Skipping stage 'squashfs' as requested via option -q" ; eend 0
953 [ -d "$BUILD_OUTPUT"/live ] || mkdir "$BUILD_OUTPUT"/live
954 # make sure we don't leave (even an empty) base.tgz:
955 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
957 # if unconfigured default to squashfs-tools' mksquashfs binary
958 if [ -z "$SQUASHFS_BINARY" ] ; then
959 SQUASHFS_BINARY='mksquashfs'
962 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
963 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
964 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
966 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
967 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
971 # use sane defaults if $SQUASHFS_OPTIONS isn't set
972 if [ -z "$SQUASHFS_OPTIONS" ] ; then
973 # use blocksize 256k as this gives best result with regards to time + compression
974 SQUASHFS_OPTIONS="-b 256k"
976 # set lzma/xz compression by default, unless -z option has been specified on command line
977 if [ -z "$SQUASHFS_ZLIB" ] ; then
978 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
980 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
984 # support exclusion of files via exclude-file:
985 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
986 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE"
989 # get rid of unnecessary files when building grml-small for final release:
990 if echo "$CLASSES" | grep -q GRML_SMALL ; then
991 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
995 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
997 # informational stuff
998 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
999 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1000 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1002 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1004 if $SQUASHFS_BINARY $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \
1005 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1006 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/filesystem.module
1007 log "Finished execution of stage 'squashfs' [$(date)]"
1008 einfo "Finished execution of stage 'squashfs'" ; eend 0
1010 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1011 log "$(cat $SQUASHFS_STDERR)"
1012 eerror "Error: there was a critical error executing stage 'squashfs':"
1013 cat "${SQUASHFS_STDERR}"
1018 FORCE_ISO_REBUILD=true
1021 # create md5sum file:
1022 ( cd $BUILD_OUTPUT/GRML &&
1023 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1026 # ISO_OUTPUT - mkisofs {{{
1027 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1028 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1030 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1031 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1032 elif [ "$BOOT_METHOD" = "grub" ] ; then
1033 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/grub/stage2"
1034 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1035 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1038 # Just until http://bts.grml.org/grml/issue945 has been resolved.
1039 # HYBRID_METHOD defaults to manifold, so make sure the default works OOTB.
1040 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1041 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1042 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1043 HYBRID_METHOD='grub2'
1047 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1048 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1049 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1050 elif [ -n "$SKIP_MKISOFS" ] ; then
1051 log "Skipping stage 'iso build' as requested via option -n"
1052 ewarn "Skipping stage 'iso build' as requested via option -n" ; eend 0
1054 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1056 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1057 log "Forcing rebuild of ISO because files on ISO have been modified."
1058 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1061 # support mkisofs as well as genisoimage
1062 if which mkisofs >/dev/null 2>&1; then
1064 elif which genisoimage >/dev/null 2>&1; then
1065 MKISOFS='genisoimage'
1067 log "Error: neither mkisofs nor genisoimage available - can not create ISO."
1068 eerror "Error: neither mkisofs nor genisoimage available - can not create ISO." ; eend 1
1073 if cd "$BUILD_OUTPUT" ; then
1074 if [ "$BOOT_METHOD" = "grub2" ]; then
1075 # make a 2048-byte bootsector for El Torito
1076 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1077 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1078 echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
1079 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1081 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1082 "$MKISOFS" -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1083 -l -r -J $BOOT_ARGS -no-pad \
1084 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1085 # both of these need core.img there, so it’s easier to write it here
1086 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1087 # must be <= 30720 bytes
1088 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1089 conv=notrunc bs=512 seek=4 2>/dev/null
1092 # pad the output ISO to multiples of 256 KiB for partition table support
1093 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1094 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1095 siz=$((cyls * 16 * 32 * 512)) # size after padding
1096 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1097 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1099 # support disabling hybrid ISO image
1100 if [ "$HYBRID_METHOD" = "disable" ] ; then\
1101 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1102 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1104 # use isohybrid only on request
1105 elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
1106 if ! which isohybrid >/dev/null 2>&1 ; then
1107 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1109 log "Creating hybrid ISO file with isohybrid method"
1110 einfo "Creating hybrid ISO file with isohybrid method"
1111 # Notes for consideration:
1112 # "-entry 4 -type 1c"
1113 # * using 4 as the partition number is supposed to help with BIOSes
1114 # that only support USB-Zip boot
1115 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1116 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1117 # to get the BIOS even look at the partition created by isohybrid
1118 isohybrid "${ISO_OUTPUT}/${ISO_NAME}"
1121 # by default use our manifold boot method:
1123 # isoinfo is part of both mkisofs and genisoimage so we're good
1124 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1125 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN;1 *$/s//\1/p')
1126 if ! [ -r boot/grub/core.img ] ; then
1127 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1128 elif [ "${bootoff:-0}" -lt 1 ] ; then
1129 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1131 log "Creating hybrid ISO file with manifold method"
1132 einfo "Creating hybrid ISO file with manifold method"
1133 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1134 # 512 bytes: MBR, partition table, load GRUB 2
1135 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1137 # read only one but 2048-byte sized (scale: << 2) sector
1138 echo $bootoff $bootoff | \
1139 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1140 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1145 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1146 case $CLASSES in *RELEASE*)
1149 if cd $ISO_OUTPUT ; then
1150 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1151 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1152 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1153 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1162 if [ "$RC" = 0 ] ; then
1163 log "Finished execution of stage 'iso build' [$(date)]"
1164 einfo "Finished execution of stage 'iso build'" ; eend 0
1166 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1167 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1173 # log build information to database if grml-live-db is installed and enabled {{{
1175 if [ -d /usr/share/grml-live-db ] ; then
1178 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1179 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1180 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1181 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1183 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1184 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1185 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1189 # disable by default for now, not sure whether really everyone is using a local db file
1190 #if ! touch "$DPKG_DATABASE" ; then
1191 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1195 if ! [ -r "$DPKG_LIST" ] ; then
1196 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1197 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1199 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1200 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1201 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1204 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1220 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1221 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1223 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1225 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1229 ## END OF FILE #################################################################
1230 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=3