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
162 [ -n "$LOGFILE" ] || LOGFILE=/var/log/grml-live.log
164 chown root:adm $LOGFILE
168 # some important functions {{{
171 # usage: log "string to log"
172 log() { echo "$*" >> $LOGFILE ; }
174 # cut string at character number int = $1
175 # usage: cut_string 5 "1234567890" will output "12345"
177 [ -n "$2" ] || return 1
178 echo "$2" | head -c "$1"; echo -ne "\n"
181 # prepend int = $1 spaces before string = $2
182 # usage: extend_string_begin 5 "123" will output " 123"
183 extend_string_begin() {
184 [ -n "$2" ] || return 1
185 local COUNT="$(echo $2 | wc -c)"
186 local FILL="$(expr $COUNT - $1)"
187 while [ "$FILL" -gt 1 ] ; do
189 local FILL=$(expr $FILL - 1)
191 while [ "$FILL" -lt 1 ] ; do
193 local FILL=$(expr $FILL + 1)
195 echo "$2" | head -c "$1"; echo -ne "\n"
198 # append int = $1 spaces to string = $2
199 # usage: extend_string_begin 5 "123" will output "123 "
200 extend_string_end() {
201 [ -n "$2" ] || return 1
202 echo -n "$2" | head -c "$1"
203 local COUNT="$(echo $2 | wc -c)"
204 local FILL="$(expr $COUNT - $1)"
205 while [ "$FILL" -gt 1 ] ; do
207 local FILL=$(expr $FILL - 1)
209 while [ "$FILL" -lt 1 ] ; do
211 local FILL=$(expr $FILL + 1)
217 # read local (non-packaged) configuration {{{
218 LOCAL_CONFIG=/etc/grml/grml-live.local
219 if [ -r "$LOCAL_CONFIG" ] ; then
220 log "Sourcing $LOCAL_CONFIG"
223 log "No $LOCAL_CONFIG found, not sourcing it"
228 # command line parsing {{{
229 while getopts "a:C:c:d:g:i:I:o:r:s:t:v:bBFnquVz" opt; do
234 c) CLASSES="$OPTARG" ;;
235 C) CONFIG="$OPTARG" ;;
237 g) GRML_NAME="$OPTARG" ;;
238 i) ISO_NAME="$OPTARG" ;;
239 I) CHROOT_INSTALL="$OPTARG" ;;
241 o) OUTPUT="$OPTARG" ;;
242 q) SKIP_MKSQUASHFS=1 ;;
243 r) RELEASENAME="$OPTARG" ;;
244 s) SUITE="$OPTARG" ;;
245 t) TEMPLATE_DIRECTORY="$OPTARG";;
246 v) VERSION="$OPTARG" ;;
250 z) SQUASHFS_ZLIB=1 ;;
251 ?) echo "invalid option -$OPTARG" >&2; bailout 1 ;;
254 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
257 # assume sane defaults (if not set already) {{{
258 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
259 [ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux'
260 [ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_MEDIUM,I386"
261 [ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)"
262 [ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators '
263 [ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml"
264 [ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png'
265 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
266 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai'
267 [ -n "$GRML_NAME" ] || GRML_NAME='grml'
268 [ -n "$HOSTNAME" ] || HOSTNAME='grml'
269 [ -n "$HYBRID_METHOD" ] || HYBRID_METHOD='manifold'
270 [ -n "$NFSROOT_CONF" ] || NFSROOT_CONF='/etc/grml/fai/make-fai-nfsroot.conf'
271 [ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks'
272 [ -n "$SQUASHFS_EXCLUDES_FILE " ] || SQUASHFS_EXCLUDES_FILE='/etc/grml/fai/squashfs-excludes'
273 [ -n "$SUITE" ] || SUITE='squeeze'
274 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
275 [ -n "$USERNAME" ] || USERNAME='grml'
276 [ -n "$VERSION" ] || VERSION='0.0.1'
277 [ -n "$WINDOWS_BINARIES" ] || WINDOWS_BINARIES='http://the.earth.li/~sgtatham/putty/latest/x86/'
279 # output specific stuff, depends on $OUTPUT (iff not set):
280 [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live'
281 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
282 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
283 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
286 # some misc checks before executing FAI {{{
287 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
288 specify it on the command line using the -c option."
289 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
290 specify it on the command line using the -o option."
292 # trim characters that are known to cause problems inside $GRML_NAME;
293 # for example isolinux does not like '-' inside the directory name
294 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
296 # export variables to have them available in fai scripts:
297 [ -n "$GRML_NAME" ] && export GRML_NAME="$GRML_NAME"
298 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
301 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
302 # this was default behaviour until grml-live 0.9.34:
303 if [ -n "$ZERO_LOGFILE" ] ; then
304 PRESERVE_LOGFILE='' # make sure it's cleaned then
305 ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
306 ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
311 # ask user whether the setup is ok {{{
312 if [ -z "$FORCE" ] ; then
314 echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
316 echo " FAI classes: $CLASSES"
317 [ -r "$LOCAL_CONFIG" ] && echo " Local config: /etc/grml/grml-live.local"
318 [ -n "$CONFIG" ] && echo " Configuration: $CONFIG"
319 echo " main directory: $OUTPUT"
320 [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT"
321 [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT"
322 [ -n "$ISO_OUTPUT" ] && echo " ISO target: $ISO_OUTPUT"
323 [ -n "$GRML_NAME" ] && echo " Grml name: $GRML_NAME"
324 [ -n "$RELEASENAME" ] && echo " Release name: $RELEASENAME"
325 [ -n "$DATE" ] && echo " Build date: $DATE"
326 [ -n "$VERSION" ] && echo " Grml version: $VERSION"
327 [ -n "$SUITE" ] && echo " Debian suite: $SUITE"
328 [ -n "$ARCH" ] && echo " Architecture: $ARCH"
329 [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD"
330 [ -n "$HYBRID_METHOD" ] && echo " Hybrid method: $HYBRID_METHOD"
331 [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY"
332 [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL"
333 [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID"
334 [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature."
335 [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
336 [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS"
337 [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE"
338 [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA/XZ) compression."
339 [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
340 [ -n "$VERBOSE" ] && echo " Using VERBOSE mode."
341 [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation."
342 [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file."
343 [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file."
344 [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE."
345 [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched."
347 echo -n "Is this ok for you? [y/N] "
349 if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
350 bailout 1 "Exiting as requested."
356 # clean/zero/remove logfiles {{{
358 if [ -n "$PRESERVE_LOGFILE" ] ; then
359 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
361 # make sure it is empty (as it is e.g. appended to grml-live-db)
365 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
366 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
367 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
368 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
369 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
370 rm -f /var/log/fai/"$HOSTNAME"/last \
371 /var/log/fai/"$HOSTNAME"/last-dirinstall \
372 /var/log/fai/"$HOSTNAME"/last-softupdate
377 # source config and startup {{{
378 if [ -n "$CONFIG" ] ; then
379 if ! [ -f "$CONFIG" ] ; then
380 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
381 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
384 log "Sourcing $CONFIG"
389 start_seconds=$(cut -d . -f 1 /proc/uptime)
390 log "------------------------------------------------------------------------------"
391 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
392 log "Executed grml-live command line:"
395 einfo "Logging actions to logfile $LOGFILE"
398 # on-the-fly configuration {{{
399 if [ -n "$MIRROR_DIRECTORY" ] ; then
400 if ! [ -d "$MIRROR_DIRECTORY/debian" ] ; then
401 log "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting. [$(date)]"
402 eerror "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting." ; eend 1
405 cat > "$SOURCES_LIST_FILE" << EOF
406 # NOTE: This file is *NOT* meant for manual customisation! This file is
407 # modified by grml-live and any changes might be overridden.
408 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
409 # or FAI's fcopy command with /etc/grml/fai/config/files instead!
411 echo "$MIRROR_SOURCES" >> "$SOURCES_LIST_FILE"
412 if [ -n "$GRML_LIVE_SOURCES" ] ; then
413 echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
415 elif [ -n "$GRML_LIVE_SOURCES" ] ; then
416 cat > "$SOURCES_LIST_FILE" << EOF
417 # NOTE: This file is *NOT* meant for manual customisation! This file is
418 # modified by grml-live and any changes might be overridden.
419 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
420 # or FAI's fcopy command with /etc/grml/fai/config/files instead!
422 echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
425 if [ -n "$FAI_DEBOOTSTRAP" ] ; then
426 sed "s#^FAI_DEBOOTSTRAP=.*#FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"#" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
429 # does this suck? YES!
430 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
432 unstable) SUITE='sid' ;;
433 # make sure that we *NEVER* write any broken suite name to sources.list,
434 # otherwise we won't be able to adjust it one next (correct) execution
442 *) echo "Sorry, $SUITE is not a valid Debian suite, exiting.">&2; bailout 1 ;;
445 DIST=" etch\| stable\| lenny\| squeeze\| wheezy\| testing\| sid\| unstable"
446 sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
447 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" ; do
448 if [ -n "$file" ] ; then
449 sed "s/^SUITE=.*/SUITE=\"$SUITE\"/" $file | sponge $file
450 sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$file" | sponge "$file"
454 # notice: activate grml-live pool only if we are building against unstable:
455 if grep -qwe unstable -qwe sid "$SOURCES_LIST_FILE" ; then
456 grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" || \
457 grep grml-stable "$SOURCES_LIST_FILE" | \
458 sed 's/grml-stable/grml-live/' >> "$SOURCES_LIST_FILE"
460 grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" && \
461 sed 's/.*grml-live.*/# removed grml-live repository/' "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
464 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" "$NFSROOT_CONF" ; do
465 if [ -n "$file" ] ; then
466 sed "s|^FAI_DEBOOTSTRAP=\"[a-z]* |FAI_DEBOOTSTRAP=\"$SUITE |" "$file" | sponge "$file"
470 # validate whether the specified architecture class matches the
471 # architecture (option), otherwise installation of kernel will fail
472 if echo $CLASSES | grep -qi i386 ; then
473 if ! [[ "$ARCH" == "i386" ]] ; then
474 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
475 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
476 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
480 elif echo $CLASSES | grep -qi amd64 ; then
481 if ! [[ "$ARCH" == "amd64" ]] ; then
482 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
483 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
484 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
490 if grep -q -- 'FAI_DEBOOTSTRAP_OPTS.*--arch' "$NFSROOT_CONF" ; then
491 sed "s/--arch [a-z0-9]* /--arch $ARCH /" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
493 sed "s|^FAI_DEBOOTSTRAP_OPTS=\"\(.*\)|FAI_DEBOOTSTRAP_OPTS=\"--arch $ARCH \1|" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
497 # CHROOT_OUTPUT - execute FAI {{{
498 if [ -n "$BUILD_DIRTY" ]; then
499 log "Skipping stage 'fai' as requested via option -B"
500 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
502 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
504 # provide inform fai about the ISO we build
505 [ -d "$CHROOT_OUTPUT/etc/" ] || mkdir -p "$CHROOT_OUTPUT/etc/"
506 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
507 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
508 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
510 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
511 FAI_ACTION=softupdate
513 FAI_ACTION=dirinstall
516 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
517 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
518 log "Error: does not look like you have a working chroot. Updating/building not possible."
519 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
525 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
526 log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
527 ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
529 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
531 if [ -n "${MIRROR_DIRECTORY}" ] ; then
532 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
533 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
536 log "Executed FAI command line:"
537 log "BUILD_ONLY=$BUILD_ONLY fai $VERBOSE -C $GRML_FAI_CONFIG -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS"
538 BUILD_ONLY="$BUILD_ONLY" fai $VERBOSE -C "$GRML_FAI_CONFIG" -c"$CLASSES" -u \
539 "$HOSTNAME" $FAI_ACTION "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
540 RC="$PIPESTATUS" # notice: bash-only
542 FORCE_ISO_REBUILD=true
544 if [ "$RC" != 0 ] ; then
545 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
546 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
549 log "Setting /etc/grml_version to $GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]"
550 echo "$GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]" > $CHROOT_OUTPUT/etc/grml_version
551 chmod 644 $CHROOT_OUTPUT/etc/grml_version
552 einfo "Rebuilding initramfs"
553 # make sure new /etc/grml_version reaches the initramfs:
554 # chroot $CHROOT_OUTPUT update-initramfs -u -t => might break when using kernel-package :(
555 chroot $CHROOT_OUTPUT update-initramfs -u -k all
559 # Remove all FAI logs from chroot if class RELEASE is used:
560 if [ -f "$CHROOT_OUTPUT"/etc/grml_fai_release ] ; then
561 rm -rf "$CHROOT_OUTPUT"/var/log/fai/*
562 rm -f "$CHROOT_OUTPUT"/var/log/install_packages.list
567 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
569 CHECKLOG=/var/log/fai/$HOSTNAME/last
570 if [ -r "$CHECKLOG/software.log" ] ; then
571 # 1 errors during executing of commands
572 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
573 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
574 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
575 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
576 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
579 if [ -r "$CHECKLOG/shell.log" ] ; then
580 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
583 if [ -n "$ERROR" ] ; then
584 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
585 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
586 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
590 log "Finished execution of stage 'fai dirinstall' [$(date)]"
591 einfo "Finished execution of stage 'fai dirinstall'"
594 einfo "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
595 log "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
601 # package validator {{{
602 CHECKLOG=/var/log/fai/$HOSTNAME/last
604 if [ -r "$CHECKLOG/package_errors.log" ] && grep -q '[a-z]' "$CHECKLOG/package_errors.log" ; then
606 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
607 eerror "The following packages were requested for installation but could not be processed:"
608 cat $CHECKLOG/package_errors.log
609 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
613 ewarn "The following packages were requested for installation but could not be processed:"
614 cat $CHECKLOG/package_errors.log
620 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
621 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
622 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
625 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
626 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
627 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
628 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
631 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
632 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
634 if [ -z "$NO_ADDONS" ] ; then
635 [ -d "$BUILD_OUTPUT"/boot/addons ] || mkdir -p "$BUILD_OUTPUT"/boot/addons
636 if [ -r "$TEMPLATE_DIRECTORY"/boot/addons/memtest ] ; then
637 log "Installing $TEMPLATE_DIRECTORY/boot/addons/memtest"
638 cp "$TEMPLATE_DIRECTORY"/boot/addons/memtest "$BUILD_OUTPUT"/boot/addons/memtest
639 elif [ -r /boot/memtest86+.bin ] ; then
640 log "Installing /boot/memtest86+.bin"
641 cp /boot/memtest86+.bin "$BUILD_OUTPUT"/boot/addons/memtest
643 ewarn "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
644 log "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
649 # if we don't have an initrd we a) can't boot and b) there was an error
650 # during build, so check for the file:
651 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
652 if [ -n "$INITRD" ] ; then
653 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.gz
654 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
656 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
657 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
661 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
662 if [ -n "$KERNEL_IMAGE" ] ; then
663 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/linux26
665 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
666 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
670 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
671 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
672 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
673 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
677 # *always* copy files to output directory so the variables
678 # get adjusted according to the build
679 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
681 if [ -n "$NO_ADDONS" ] ; then
682 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
683 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
685 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
686 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
687 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
689 # copy only files so we can handle bsd4grml on its own
690 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
691 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
694 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
695 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
696 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
698 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
699 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
701 log "bsd4grml addon not found, skipping therefore."
702 ewarn "bsd4grml addon not found, skipping therefore." ; eend 0
706 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
709 if ! [ -d ${TEMPLATE_DIRECTORY}/boot/grub ] ; then
710 log "grub templates do not exist, skipping therefore."
711 ewarn "grub templates do not exist, skipping therefore." ; eend 0
713 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
714 cp -a ${TEMPLATE_DIRECTORY}/boot/grub "$BUILD_OUTPUT"/boot/
717 # make sure we have recent template files available, otherwise updating
718 # the strings like $GRML_NAME and $VERSION might be out of date
719 cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
722 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
723 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
724 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
728 [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML
729 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/
731 # adjust boot splash information:
732 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
733 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
734 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
736 if [ -r "$BUILD_OUTPUT"/GRML/grml-version ] ; then
737 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version
738 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/grml-version
741 # make sure the squashfs filename is set accordingly:
742 SQUASHFS_NAME="$GRML_NAME.squashfs"
744 if [ -n "$NO_BOOTID" ] ; then
745 log 'Skipping bootid feature as requested via $NO_BOOTID.'
746 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
748 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
749 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
750 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
751 log "Generating /conf/bootid.txt with entry ${BOOTID}."
752 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
756 # adjust all variables in the templates with the according distribution information
757 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
758 "${BUILD_OUTPUT}"/boot/grub/* ; do
759 if [ -r "${file}" ] ; then
760 sed -i "s/%ARCH%/$ARCH/g" "${file}"
761 sed -i "s/%DATE%/$DATE/g" "${file}"
762 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
763 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
764 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
765 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
766 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
767 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
768 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
769 sed -i "s/%VERSION%/$VERSION/g" "${file}"
771 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s/ boot=live/ boot=live $DEFAULT_BOOTOPTIONS/" "${file}"
773 if [ -n "$NO_BOOTID" ] ; then
774 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
776 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
781 # adjust bootsplash accordingly but make sure the string has the according lenght
782 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
783 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
784 for file in f4 f5 ; do
785 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
786 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
787 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
791 # generate addon list
792 rm "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
793 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
794 include_name=$(basename "$name")
795 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
798 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
799 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
800 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
801 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
802 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
803 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
805 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
806 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
809 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
810 if [ ! -n "$NO_ADDONS" ] ; then
811 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
813 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
814 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
815 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
816 else # assume we are building a custom distribution:
817 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
818 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
819 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
820 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
822 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
826 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
827 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
828 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
832 # use old style console based isolinux method only if requested:
833 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
834 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
835 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
836 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
837 einfo "include for console.cfg already foud, nothing to do."
840 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
841 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
842 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
846 log 'Using graphical boot menu.'
847 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
848 log "include for vesamenu.cfg already foud, nothing to do."
850 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
851 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
855 # jump back to grub from bsd4grml (/boot/grub/stage2):
858 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
859 if [ -e "$BUILD_OUTPUT"/boot/grub/core.img ]; then
865 for file in "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 \
866 "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.cfg \
867 "$BUILD_OUTPUT"/boot/isolinux/*.cfg \
868 "$BUILD_OUTPUT"/boot/grub/grub.cfg \
869 "$BUILD_OUTPUT"/boot/grub/menu.lst ; do
870 if [ -e "$file" ] ; then
871 sed -i -e "s!%GRUB_VERSION%!$GRUB_VERSION!g" \
872 -e "s!%GRUB_LEGACY%!$GRUB_LEGACY!g" "$file"
876 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
879 if [ -e "$BUILD_OUTPUT"/boot/grub/$GRUB_LEGACY ]; then
880 sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/menu.lst
881 sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/grub.cfg
882 elif [ -e "$BUILD_OUTPUT"/boot/grub/menu.lst -a -e "$BUILD_OUTPUT"/boot/grub/grub.cfg ] ; then
883 sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/menu.lst
884 sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/grub.cfg
887 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
888 if ! [ -r "$DPKG_LIST" ] ; then
889 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
891 einfo "Storing package list information as /GRML/${GRML_NAME}-packages.txt on ISO."
892 cp "$DPKG_LIST" "${BUILD_OUTPUT}/GRML/${GRML_NAME}-packages.txt"
896 # autostart for Windows:
897 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
898 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
902 if [ -n "$NO_WINDOWS_BINARIES" ] ; then
903 log "Skipping download of windows binaries as requested via \$NO_WINDOWS_BINARIES."
904 einfo "Skipping download of windows binaries as requested via \$NO_WINDOWS_BINARIES."
907 if [ -f "$BUILD_OUTPUT"/windows/putty.exe ] ; then
908 log "Skipping stage 'WINDOWS_BINARIES' as $BUILD_OUTPUT/windows exists already."
909 ewarn "Skipping stage 'WINDOWS_BINARIES' as $BUILD_OUTPUT/windows exists already." ; eend 0
911 if ! [ -d "$BUILD_OUTPUT"/windows ] ; then
912 mkdir "$BUILD_OUTPUT"/windows
913 ( cd "$BUILD_OUTPUT"/windows
914 for file in pageant plink pscp psftp putty puttygen ; do
915 wget -O ${file}.exe ${WINDOWS_BINARIES}/${file}.exe
916 md5sum ${file}.exe > ${file}.exe.md5
920 log "Finished execution of stage 'WINDOWS_BINARIES' [$(date)]"
921 einfo "Finished execution of stage 'WINDOWS_BINARIES'" ; eend 0
925 FORCE_ISO_REBUILD=true
926 einfo "Finished execution of stage 'boot'" ; eend 0
929 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
930 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
934 # support installation of local files into the chroot/ISO
935 if [ -n "$CHROOT_INSTALL" ] ; then
936 if ! [ -d "$CHROOT_INSTALL" ] ; then
937 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
938 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
940 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
941 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
942 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
944 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
945 FORCE_ISO_REBUILD=true
949 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
950 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
951 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
952 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
953 log "Skipping stage 'squashfs' as requested via option -q"
954 ewarn "Skipping stage 'squashfs' as requested via option -q" ; eend 0
956 [ -d "$BUILD_OUTPUT"/live ] || mkdir "$BUILD_OUTPUT"/live
957 # make sure we don't leave (even an empty) base.tgz:
958 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
960 # if unconfigured default to squashfs-tools' mksquashfs binary
961 if [ -z "$SQUASHFS_BINARY" ] ; then
962 SQUASHFS_BINARY='mksquashfs'
965 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
966 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
967 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
969 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
970 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
974 # use sane defaults if $SQUASHFS_OPTIONS isn't set
975 if [ -z "$SQUASHFS_OPTIONS" ] ; then
976 # use blocksize 256k as this gives best result with regards to time + compression
977 SQUASHFS_OPTIONS="-b 256k"
979 # set lzma/xz compression by default, unless -z option has been specified on command line
980 if [ -z "$SQUASHFS_ZLIB" ] ; then
981 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
983 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
987 # support exclusion of files via exclude-file:
988 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
989 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE"
992 # get rid of unnecessary files when building grml-small for final release:
993 if echo "$CLASSES" | grep -q GRML_SMALL ; then
994 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
998 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
1000 # informational stuff
1001 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1002 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1003 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1005 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1007 if $SQUASHFS_BINARY $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \
1008 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1009 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/filesystem.module
1010 log "Finished execution of stage 'squashfs' [$(date)]"
1011 einfo "Finished execution of stage 'squashfs'" ; eend 0
1013 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1014 log "$(cat $SQUASHFS_STDERR)"
1015 eerror "Error: there was a critical error executing stage 'squashfs':"
1016 cat "${SQUASHFS_STDERR}"
1021 FORCE_ISO_REBUILD=true
1024 # create md5sum file:
1025 ( cd $BUILD_OUTPUT/GRML &&
1026 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1029 # ISO_OUTPUT - mkisofs {{{
1030 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1031 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1033 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1034 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1035 elif [ "$BOOT_METHOD" = "grub" ] ; then
1036 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/grub/stage2"
1037 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1038 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1041 # Just until http://bts.grml.org/grml/issue945 has been resolved.
1042 # HYBRID_METHOD defaults to manifold, so make sure the default works OOTB.
1043 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1044 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1045 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1046 HYBRID_METHOD='grub2'
1050 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1051 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1052 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1053 elif [ -n "$SKIP_MKISOFS" ] ; then
1054 log "Skipping stage 'iso build' as requested via option -n"
1055 ewarn "Skipping stage 'iso build' as requested via option -n" ; eend 0
1057 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1059 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1060 log "Forcing rebuild of ISO because files on ISO have been modified."
1061 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1064 # support mkisofs as well as genisoimage
1065 if which mkisofs >/dev/null 2>&1; then
1067 elif which genisoimage >/dev/null 2>&1; then
1068 MKISOFS='genisoimage'
1070 log "Error: neither mkisofs nor genisoimage available - can not create ISO."
1071 eerror "Error: neither mkisofs nor genisoimage available - can not create ISO." ; eend 1
1076 if cd "$BUILD_OUTPUT" ; then
1077 if [ "$BOOT_METHOD" = "grub2" ]; then
1078 # make a 2048-byte bootsector for El Torito
1079 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1080 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1081 echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
1082 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1084 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1085 "$MKISOFS" -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1086 -l -r -J $BOOT_ARGS -no-pad \
1087 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1088 # both of these need core.img there, so it’s easier to write it here
1089 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1090 # must be <= 30720 bytes
1091 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1092 conv=notrunc bs=512 seek=4 2>/dev/null
1095 # pad the output ISO to multiples of 256 KiB for partition table support
1096 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1097 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1098 siz=$((cyls * 16 * 32 * 512)) # size after padding
1099 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1100 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1102 # support disabling hybrid ISO image
1103 if [ "$HYBRID_METHOD" = "disable" ] ; then\
1104 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1105 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1107 # use isohybrid only on request
1108 elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
1109 if ! which isohybrid >/dev/null 2>&1 ; then
1110 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1112 log "Creating hybrid ISO file with isohybrid method"
1113 einfo "Creating hybrid ISO file with isohybrid method"
1114 # Notes for consideration:
1115 # "-entry 4 -type 1c"
1116 # * using 4 as the partition number is supposed to help with BIOSes
1117 # that only support USB-Zip boot
1118 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1119 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1120 # to get the BIOS even look at the partition created by isohybrid
1121 isohybrid "${ISO_OUTPUT}/${ISO_NAME}"
1124 # by default use our manifold boot method:
1126 # isoinfo is part of both mkisofs and genisoimage so we're good
1127 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1128 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN;1 *$/s//\1/p')
1129 if ! [ -r boot/grub/core.img ] ; then
1130 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1131 elif [ "${bootoff:-0}" -lt 1 ] ; then
1132 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1134 log "Creating hybrid ISO file with manifold method"
1135 einfo "Creating hybrid ISO file with manifold method"
1136 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1137 # 512 bytes: MBR, partition table, load GRUB 2
1138 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1140 # read only one but 2048-byte sized (scale: << 2) sector
1141 echo $bootoff $bootoff | \
1142 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1143 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1148 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1149 case $CLASSES in *RELEASE*)
1152 if cd $ISO_OUTPUT ; then
1153 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1154 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1155 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1156 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1165 if [ "$RC" = 0 ] ; then
1166 log "Finished execution of stage 'iso build' [$(date)]"
1167 einfo "Finished execution of stage 'iso build'" ; eend 0
1169 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1170 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1176 # log build information to database if grml-live-db is installed and enabled {{{
1178 if [ -d /usr/share/grml-live-db ] ; then
1181 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1182 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1183 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1184 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1186 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1187 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1188 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1192 # disable by default for now, not sure whether really everyone is using a local db file
1193 #if ! touch "$DPKG_DATABASE" ; then
1194 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1198 if ! [ -r "$DPKG_LIST" ] ; then
1199 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1200 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1202 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1203 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1204 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1207 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1223 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1224 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1226 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1228 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1232 ## END OF FILE #################################################################
1233 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=3