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 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 -D <configdir> use specified configuration directory instead of /etc/grml/fai
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 -N bootstrap (build chroot) only, do not create files for ISO
56 -o <output_directory> main output directory of the build process
58 -r <release_name> release name
59 -s <suite> Debian suite; values: etch, lenny, squeeze, sid
60 -t <template_directory> place of the templates
61 -u update existing chroot instead of rebuilding it from scratch
62 -v <version_number> specify version number of the release
63 -V increase verbosity in the build process
64 -z use ZLIB instead of LZMA/XZ compression
69 $PN -c GRMLBASE,GRML_MEDIUM,I386 -o /dev/shm/grml
70 $PN -c GRMLBASE,GRML_SMALL,REMOVE_DOCS,I386 -g grml-small -v 1.0
71 $PN -c GRMLBASE,GRML_FULL,I386 -i grml_0.0-1.iso -v 0.0-1
72 $PN -c GRMLBASE,GRML_FULL,I386 -s sid -V -r 'grml-live rocks'
74 More details: man grml-live + /usr/share/doc/grml-live/grml-live.html
75 http://grml.org/grml-live/
77 Please send your bug reports and feedback to the grml-team: http://grml.org/bugs/
81 # make sure it's possible to get usage information without being
82 # root or actually executing the script
83 if [ "$1" = '-h' -o "$1" = '--help' ] ; then
85 [ "$(id -u 2>/dev/null)" != 0 ] && echo "Please notice that this script requires root permissions."
90 # some runtime checks {{{
91 # we need root permissions for the build-process:
92 if [ "$(id -u 2>/dev/null)" != 0 ] ; then
93 echo "Error: please run this script with uid 0 (root)." >&2
97 if [ -r /var/run/fai/FAI_INSTALLATION_IN_PROGRESS ] ; then
98 echo "/usr/sbin/fai already running or was aborted before.">&2
99 echo "You may remove /var/run/fai/FAI_INSTALLATION_IN_PROGRESS and try again.">&2
104 if [ -r /var/run/fai/fai_softupdate_is_running ] ; then
105 echo "/usr/sbin/fai softupdate already running or was aborted before.">&2
106 echo "You may remove /var/run/fai/fai_softupdate_is_running and try again.">&2
111 # lsb-functions and configuration stuff {{{
112 # make sure they are not set by default
121 if [ -r /etc/grml/lsb-functions ] ; then
122 . /etc/grml/lsb-functions
124 einfo() { echo " [*] $*" ;}
125 eerror() { echo " [!] $*">&2 ;}
126 ewarn() { echo " [x] $*" ;}
128 eindent() { return 0 ;}
129 eoutdent() { return 0 ;}
132 # source main configuration file:
133 LIVE_CONF=/etc/grml/grml-live.conf
137 # umount all directories {{{
139 # make sure we don't leave any mounts - FAI doesn't remove them always
140 umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
141 umount $CHROOT_OUTPUT/sys 2>/dev/null || /bin/true
142 umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
143 umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
144 [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
150 rm -f /var/run/fai/fai_softupdate_is_running \
151 /var/run/fai/FAI_INSTALLATION_IN_PROGRESS
152 [ -n "$SQUASHFS_STDERR" ] && rm -rf "$SQUASHFS_STDERR"
154 [ -n "$1" ] && EXIT="$1" || EXIT="1"
155 [ -n "$2" ] && eerror "$2">&2
156 log "------------------------------------------------------------------------------"
159 trap bailout 1 2 3 3 6 9 14 15
164 [ -n "$LOGFILE" ] || LOGFILE=/var/log/grml-live.log
166 chown root:adm $LOGFILE
170 # some important functions {{{
173 # usage: log "string to log"
174 log() { echo "$*" >> $LOGFILE ; }
176 # cut string at character number int = $1
177 # usage: cut_string 5 "1234567890" will output "12345"
179 [ -n "$2" ] || return 1
180 echo "$2" | head -c "$1"; echo -ne "\n"
183 # prepend int = $1 spaces before string = $2
184 # usage: extend_string_begin 5 "123" will output " 123"
185 extend_string_begin() {
186 [ -n "$2" ] || return 1
187 local COUNT="$(echo $2 | wc -c)"
188 local FILL="$(expr $COUNT - $1)"
189 while [ "$FILL" -gt 1 ] ; do
191 local FILL=$(expr $FILL - 1)
193 while [ "$FILL" -lt 1 ] ; do
195 local FILL=$(expr $FILL + 1)
197 echo "$2" | head -c "$1"; echo -ne "\n"
200 # append int = $1 spaces to string = $2
201 # usage: extend_string_begin 5 "123" will output "123 "
202 extend_string_end() {
203 [ -n "$2" ] || return 1
204 echo -n "$2" | head -c "$1"
205 local COUNT="$(echo $2 | wc -c)"
206 local FILL="$(expr $COUNT - $1)"
207 while [ "$FILL" -gt 1 ] ; do
209 local FILL=$(expr $FILL - 1)
211 while [ "$FILL" -lt 1 ] ; do
213 local FILL=$(expr $FILL + 1)
219 # read local (non-packaged) configuration {{{
220 LOCAL_CONFIG=/etc/grml/grml-live.local
221 if [ -r "$LOCAL_CONFIG" ] ; then
222 log "Sourcing $LOCAL_CONFIG"
225 log "No $LOCAL_CONFIG found, not sourcing it"
230 # command line parsing {{{
231 while getopts "a:C:c:d:D:g:i:I:o:r:s:t:v:bBFnNquVz" opt; do
236 c) CLASSES="$OPTARG" ;;
237 C) CONFIG="$OPTARG" ;;
239 D) GRML_FAI_CONFIG="$OPTARG" ;;
240 g) GRML_NAME="$OPTARG" ;;
241 i) ISO_NAME="$OPTARG" ;;
242 I) CHROOT_INSTALL="$OPTARG" ;;
244 N) BOOTSTRAP_ONLY=1; SKIP_MKISOFS=1; SKIP_MKSQUASHFS=1 ;;
245 o) OUTPUT="$OPTARG" ;;
246 q) SKIP_MKSQUASHFS=1 ;;
247 r) RELEASENAME="$OPTARG" ;;
248 s) SUITE="$OPTARG" ;;
249 t) TEMPLATE_DIRECTORY="$OPTARG";;
250 v) VERSION="$OPTARG" ;;
254 z) SQUASHFS_ZLIB=1 ;;
255 ?) echo "invalid option -$OPTARG" >&2; bailout 1 ;;
258 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
261 # assume sane defaults (if not set already) {{{
262 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
263 [ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux'
264 [ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_MEDIUM,I386"
265 [ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)"
266 [ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators '
267 [ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml"
268 [ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png'
269 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
270 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai'
271 [ -n "$GRML_NAME" ] || GRML_NAME='grml'
272 [ -n "$HOSTNAME" ] || HOSTNAME='grml'
273 [ -n "$HYBRID_METHOD" ] || HYBRID_METHOD='manifold'
274 [ -n "$NFSROOT_CONF" ] || NFSROOT_CONF="${GRML_FAI_CONFIG}/make-fai-nfsroot.conf"
275 [ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks'
276 [ -n "$SOURCES_LIST_INPUT" ] || SOURCES_LIST_INPUT="${GRML_FAI_CONFIG}/apt/sources.list"
277 [ -n "$SOURCES_LIST_OUTPUT" ] || SOURCES_LIST_OUTPUT="${GRML_FAI_CONFIG}/config/files/etc/apt/sources.list/GRMLBASE"
278 [ -n "$SQUASHFS_EXCLUDES_FILE" ] || SQUASHFS_EXCLUDES_FILE="${GRML_FAI_CONFIG}/config/grml/squashfs-excludes"
279 [ -n "$SUITE" ] || SUITE='squeeze'
280 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
281 [ -n "$USERNAME" ] || USERNAME='grml'
282 [ -n "$VERSION" ] || VERSION='0.0.1'
284 # output specific stuff, depends on $OUTPUT (iff not set):
285 [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live'
286 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
287 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
288 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
291 # some misc checks before executing FAI {{{
292 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
293 specify it on the command line using the -c option."
294 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
295 specify it on the command line using the -o option."
297 # trim characters that are known to cause problems inside $GRML_NAME;
298 # for example isolinux does not like '-' inside the directory name
299 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
301 # export variables to have them available in fai scripts:
302 [ -n "$GRML_NAME" ] && export GRML_NAME="$GRML_NAME"
303 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
306 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
307 # this was default behaviour until grml-live 0.9.34:
308 if [ -n "$ZERO_LOGFILE" ] ; then
309 PRESERVE_LOGFILE='' # make sure it's cleaned then
310 ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
311 ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
316 # ask user whether the setup is ok {{{
317 if [ -z "$FORCE" ] ; then
319 echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
321 echo " FAI classes: $CLASSES"
322 [ -r "$LOCAL_CONFIG" ] && echo " Local config: /etc/grml/grml-live.local"
323 [ -n "$CONFIG" ] && echo " Configuration: $CONFIG"
324 [ -n "$GRML_FAI_CONFIG" ] && echo " Config directory: $GRML_FAI_CONFIG"
325 echo " main directory: $OUTPUT"
326 [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT"
327 [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT"
328 [ -n "$ISO_OUTPUT" ] && echo " ISO target: $ISO_OUTPUT"
329 [ -n "$GRML_NAME" ] && echo " Grml name: $GRML_NAME"
330 [ -n "$RELEASENAME" ] && echo " Release name: $RELEASENAME"
331 [ -n "$DATE" ] && echo " Build date: $DATE"
332 [ -n "$VERSION" ] && echo " Grml version: $VERSION"
333 [ -n "$SUITE" ] && echo " Debian suite: $SUITE"
334 [ -n "$ARCH" ] && echo " Architecture: $ARCH"
335 [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD"
336 [ -n "$HYBRID_METHOD" ] && echo " Hybrid method: $HYBRID_METHOD"
337 [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY"
338 [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL"
339 [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID"
340 [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature."
341 [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
342 [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS"
343 [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE"
344 [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA/XZ) compression."
345 [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
346 [ -n "$VERBOSE" ] && echo " Using VERBOSE mode."
347 [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation."
348 if [ -n "$BOOTSTRAP_ONLY" ] ; then
349 echo " Bootstrapping only and not building (files for) ISO."
351 [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file."
352 [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file."
353 [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE."
354 [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched."
357 echo -n "Is this ok for you? [y/N] "
359 if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
360 bailout 1 "Exiting as requested."
366 # clean/zero/remove logfiles {{{
368 if [ -n "$PRESERVE_LOGFILE" ] ; then
369 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
371 # make sure it is empty (as it is e.g. appended to grml-live-db)
375 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
376 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
377 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
378 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
379 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
380 rm -f /var/log/fai/"$HOSTNAME"/last \
381 /var/log/fai/"$HOSTNAME"/last-dirinstall \
382 /var/log/fai/"$HOSTNAME"/last-softupdate
387 # source config and startup {{{
388 if [ -n "$CONFIG" ] ; then
389 if ! [ -f "$CONFIG" ] ; then
390 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
391 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
394 log "Sourcing $CONFIG"
399 start_seconds=$(cut -d . -f 1 /proc/uptime)
400 log "------------------------------------------------------------------------------"
401 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
402 log "Executed grml-live command line:"
405 einfo "Logging actions to logfile $LOGFILE"
408 # on-the-fly configuration {{{
409 mkdir -p "$(dirname $SOURCES_LIST_OUTPUT)" # might not be present in -D config space
411 cat > "$SOURCES_LIST_OUTPUT" << EOF
412 # NOTE: This file is *NOT* meant for manual customisation! This file is
413 # modified by grml-live and any changes will be overridden.
414 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
415 # or FAI's fcopy command with ${GRML_FAI_CONFIG}/config/files instead!
418 if [ -n "$MIRROR_DIRECTORY" ] ; then
419 if ! [ -d "$MIRROR_DIRECTORY/debian" ] ; then
420 log "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting. [$(date)]"
421 eerror "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting." ; eend 1
424 echo "$MIRROR_SOURCES" >> "$SOURCES_LIST_OUTPUT"
427 if [ -n "$GRML_LIVE_SOURCES" ] ; then
428 echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_OUTPUT"
431 if [ -n "$FAI_DEBOOTSTRAP" ] ; then
432 sed "s#^FAI_DEBOOTSTRAP=.*#FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"#" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
435 # does this suck? YES!
436 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
438 unstable) SUITE='sid' ;;
439 # make sure that we *NEVER* write any broken suite name to sources.list,
440 # otherwise we won't be able to adjust it one next (correct) execution
448 *) echo "Sorry, $SUITE is not a valid Debian suite, exiting.">&2; bailout 1 ;;
451 DIST=" etch\| stable\| lenny\| squeeze\| wheezy\| testing\| sid\| unstable"
452 sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$SOURCES_LIST_INPUT" | sponge "$SOURCES_LIST_OUTPUT"
453 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" ; do
454 if [ -n "$file" ] ; then
455 sed "s/^SUITE=.*/SUITE=\"$SUITE\"/" $file | sponge $file
456 sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$file" | sponge "$file"
460 # notice: activate grml-live pool only if we are building against unstable:
461 if grep -qwe unstable -qwe sid "$SOURCES_LIST_INPUT" ; then
462 grep -q 'grml-live.*main' "$SOURCES_LIST_OUTPUT" || \
463 grep grml-stable "$SOURCES_LIST_OUTPUT" | \
464 sed 's/grml-stable/grml-live/' >> "$SOURCES_LIST_OUTPUT"
466 grep -q 'grml-live.*main' "$SOURCES_LIST_INPUT" && \
467 sed 's/.*grml-live.*/# removed grml-live repository/' "$SOURCES_LIST_INPUT" | sponge "$SOURCES_LIST_OUTPUT"
470 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" "$NFSROOT_CONF" ; do
471 if [ -n "$file" ] ; then
472 sed "s|^FAI_DEBOOTSTRAP=\"[a-z]* |FAI_DEBOOTSTRAP=\"$SUITE |" "$file" | sponge "$file"
476 # validate whether the specified architecture class matches the
477 # architecture (option), otherwise installation of kernel will fail
478 if echo $CLASSES | grep -qi i386 ; then
479 if ! [[ "$ARCH" == "i386" ]] ; then
480 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
481 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
482 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
486 elif echo $CLASSES | grep -qi amd64 ; then
487 if ! [[ "$ARCH" == "amd64" ]] ; then
488 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
489 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
490 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
496 if grep -q -- 'FAI_DEBOOTSTRAP_OPTS.*--arch' "$NFSROOT_CONF" ; then
497 sed "s/--arch [a-z0-9]* /--arch $ARCH /" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
499 sed "s|^FAI_DEBOOTSTRAP_OPTS=\"\(.*\)|FAI_DEBOOTSTRAP_OPTS=\"--arch $ARCH \1|" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
503 # CHROOT_OUTPUT - execute FAI {{{
504 if [ -n "$BUILD_DIRTY" ]; then
505 log "Skipping stage 'fai' as requested via option -B"
506 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
508 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
510 # provide inform fai about the ISO we build
511 [ -d "$CHROOT_OUTPUT/etc/" ] || mkdir -p "$CHROOT_OUTPUT/etc/"
512 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
513 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
514 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
516 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
517 FAI_ACTION=softupdate
519 FAI_ACTION=dirinstall
522 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
523 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
524 log "Error: does not look like you have a working chroot. Updating/building not possible."
525 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
531 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
532 log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
533 ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
535 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
537 if [ -n "${MIRROR_DIRECTORY}" ] ; then
538 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
539 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
542 # tell dpkg to use "unsafe io" during the build
543 [ -d "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d" ] || mkdir -p "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d"
544 echo force-unsafe-io > "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d/unsafe-io"
546 log "Executed FAI command line:"
547 log "BUILD_ONLY=$BUILD_ONLY BOOTSTRAP_ONLY=$BOOTSTRAP_ONLY fai $VERBOSE -C $GRML_FAI_CONFIG -s file:///$GRML_FAI_CONFIG/config -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS"
548 BUILD_ONLY="$BUILD_ONLY" BOOTSTRAP_ONLY="$BOOTSTRAP_ONLY" fai $VERBOSE \
549 -C "$GRML_FAI_CONFIG" -s "file:///$GRML_FAI_CONFIG/config" -c"$CLASSES" \
550 -u "$HOSTNAME" "$FAI_ACTION" "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
551 RC="$PIPESTATUS" # notice: bash-only
553 rm -f "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d/unsafe-io"
555 FORCE_ISO_REBUILD=true
557 if [ "$RC" != 0 ] ; then
558 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
559 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
562 einfo "Setting /etc/grml_version to $GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]"
563 log "Setting /etc/grml_version to $GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]"
564 echo "$GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]" > $CHROOT_OUTPUT/etc/grml_version
565 chmod 644 $CHROOT_OUTPUT/etc/grml_version
566 einfo "Rebuilding initramfs"
567 # make sure new /etc/grml_version reaches initramfs, iterate over all
568 # present kernel versions (note: we can't really handle more than one
569 # kernel version anyway right now)
570 # chroot $CHROOT_OUTPUT update-initramfs -u -t => might break when using kernel-package :(
571 for initrd in "$(basename $CHROOT_OUTPUT/boot/vmlinuz-*)" ; do
572 if ! chroot $CHROOT_OUTPUT update-initramfs -k "${initrd##vmlinuz-}" -c ; then
573 einfo "Creating fresh initrd did not work, trying update instead:"
574 log "Creating fresh initrd did not work, trying update instead:"
575 chroot $CHROOT_OUTPUT update-initramfs -k "${initrd##vmlinuz-}" -u
581 # Remove all FAI logs from chroot if class RELEASE is used:
582 if [ -f "$CHROOT_OUTPUT"/etc/grml_fai_release ] ; then
583 rm -rf "$CHROOT_OUTPUT"/var/log/fai/*
584 rm -f "$CHROOT_OUTPUT"/var/log/install_packages.list
589 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
591 CHECKLOG=/var/log/fai/$HOSTNAME/last
592 if [ -r "$CHECKLOG/software.log" ] ; then
593 # 1 errors during executing of commands
594 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
595 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
596 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
597 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
598 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
601 if [ -r "$CHECKLOG/shell.log" ] ; then
602 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
605 if [ -n "$ERROR" ] ; then
606 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
607 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
608 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
612 log "Finished execution of stage 'fai dirinstall' [$(date)]"
613 einfo "Finished execution of stage 'fai dirinstall'"
616 einfo "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
617 log "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
623 # package validator {{{
624 CHECKLOG=/var/log/fai/$HOSTNAME/last
626 if [ -r "$CHECKLOG/package_errors.log" ] && grep -q '[a-z]' "$CHECKLOG/package_errors.log" ; then
628 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
629 eerror "The following packages were requested for installation but could not be processed:"
630 cat $CHECKLOG/package_errors.log
631 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
635 ewarn "The following packages were requested for installation but could not be processed:"
636 cat $CHECKLOG/package_errors.log
642 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
643 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
644 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
647 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
648 if [ -n "$BOOTSTRAP_ONLY" ] ; then
649 log "Skipping stage 'boot' as building with bootstrap only."
650 ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0
652 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
653 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
654 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
657 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
658 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
660 if [ -z "$NO_ADDONS" ] ; then
661 [ -d "$BUILD_OUTPUT"/boot/addons ] || mkdir -p "$BUILD_OUTPUT"/boot/addons
662 if [ -r "$TEMPLATE_DIRECTORY"/boot/addons/memtest ] ; then
663 log "Installing $TEMPLATE_DIRECTORY/boot/addons/memtest"
664 cp "$TEMPLATE_DIRECTORY"/boot/addons/memtest "$BUILD_OUTPUT"/boot/addons/memtest
665 elif [ -r /boot/memtest86+.bin ] ; then
666 log "Installing /boot/memtest86+.bin"
667 cp /boot/memtest86+.bin "$BUILD_OUTPUT"/boot/addons/memtest
669 ewarn "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
670 log "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
675 # if we don't have an initrd we a) can't boot and b) there was an error
676 # during build, so check for the file:
677 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
678 if [ -n "$INITRD" ] ; then
679 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.gz
680 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
682 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
683 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
687 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
688 if [ -n "$KERNEL_IMAGE" ] ; then
689 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/linux26
691 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
692 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
696 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
697 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
698 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
699 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
703 # *always* copy files to output directory so the variables
704 # get adjusted according to the build
705 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
707 if [ -n "$NO_ADDONS" ] ; then
708 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
709 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
711 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
712 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
713 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
715 # copy only files so we can handle bsd4grml on its own
716 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
717 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
720 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
721 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
722 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
724 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
725 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
727 log "bsd4grml addon not found, skipping therefore."
728 ewarn "bsd4grml addon not found, skipping therefore." ; eend 0
732 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
735 if ! [ -d ${TEMPLATE_DIRECTORY}/boot/grub ] ; then
736 log "grub templates do not exist, skipping therefore."
737 ewarn "grub templates do not exist, skipping therefore." ; eend 0
739 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
740 cp -a ${TEMPLATE_DIRECTORY}/boot/grub "$BUILD_OUTPUT"/boot/
743 # make sure we have recent template files available, otherwise updating
744 # the strings like $GRML_NAME and $VERSION might be out of date
745 cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
748 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
749 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
750 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
754 [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML
755 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/
757 # adjust boot splash information:
758 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
759 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
760 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
762 if [ -r "$BUILD_OUTPUT"/GRML/grml-version ] ; then
763 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version
764 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/grml-version
767 # make sure the squashfs filename is set accordingly:
768 SQUASHFS_NAME="$GRML_NAME.squashfs"
770 if [ -n "$NO_BOOTID" ] ; then
771 log 'Skipping bootid feature as requested via $NO_BOOTID.'
772 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
774 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
775 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
776 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
777 log "Generating /conf/bootid.txt with entry ${BOOTID}."
778 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
782 # adjust all variables in the templates with the according distribution information
783 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
784 "${BUILD_OUTPUT}"/boot/grub/* ; do
785 if [ -r "${file}" ] ; then
786 sed -i "s/%ARCH%/$ARCH/g" "${file}"
787 sed -i "s/%DATE%/$DATE/g" "${file}"
788 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
789 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
790 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
791 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
792 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
793 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
794 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
795 sed -i "s/%VERSION%/$VERSION/g" "${file}"
797 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s/ boot=live/ boot=live $DEFAULT_BOOTOPTIONS/" "${file}"
799 if [ -n "$NO_BOOTID" ] ; then
800 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
802 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
807 # adjust bootsplash accordingly but make sure the string has the according lenght
808 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
809 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
810 for file in f4 f5 ; do
811 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
812 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
813 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
817 # generate addon list
818 rm "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
819 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
820 include_name=$(basename "$name")
821 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
824 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
825 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
826 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
827 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
828 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
829 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
831 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
832 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
835 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
836 if [ ! -n "$NO_ADDONS" ] ; then
837 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
839 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
840 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
841 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
842 else # assume we are building a custom distribution:
843 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
844 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
845 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
846 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
848 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
852 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
853 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
854 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
858 # use old style console based isolinux method only if requested:
859 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
860 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
861 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
862 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
863 einfo "include for console.cfg already foud, nothing to do."
866 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
867 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
868 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
872 log 'Using graphical boot menu.'
873 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
874 log "include for vesamenu.cfg already foud, nothing to do."
876 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
877 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
881 # jump back to grub from bsd4grml (/boot/grub/stage2):
884 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
885 if [ -e "$BUILD_OUTPUT"/boot/grub/core.img ]; then
891 for file in "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 \
892 "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.cfg \
893 "$BUILD_OUTPUT"/boot/isolinux/*.cfg \
894 "$BUILD_OUTPUT"/boot/grub/grub.cfg \
895 "$BUILD_OUTPUT"/boot/grub/menu.lst ; do
896 if [ -e "$file" ] ; then
897 sed -i -e "s!%GRUB_VERSION%!$GRUB_VERSION!g" \
898 -e "s!%GRUB_LEGACY%!$GRUB_LEGACY!g" "$file"
902 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
905 if [ -e "$BUILD_OUTPUT"/boot/grub/$GRUB_LEGACY ]; then
906 sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/menu.lst
907 sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/grub.cfg
908 elif [ -e "$BUILD_OUTPUT"/boot/grub/menu.lst -a -e "$BUILD_OUTPUT"/boot/grub/grub.cfg ] ; then
909 sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/menu.lst
910 sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/grub.cfg
913 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
914 if ! [ -r "$DPKG_LIST" ] ; then
915 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
917 einfo "Storing package list information as /GRML/${GRML_NAME}-packages.txt on ISO."
918 cp "$DPKG_LIST" "${BUILD_OUTPUT}/GRML/${GRML_NAME}-packages.txt"
922 # autostart for Windows:
923 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
924 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
927 FORCE_ISO_REBUILD=true
928 einfo "Finished execution of stage 'boot'" ; eend 0
932 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
933 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
937 # support installation of local files into the chroot/ISO
938 if [ -n "$CHROOT_INSTALL" ] ; then
939 if ! [ -d "$CHROOT_INSTALL" ] ; then
940 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
941 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
943 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
944 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
945 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
947 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
948 FORCE_ISO_REBUILD=true
952 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
953 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
954 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
955 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
956 log "Skipping stage 'squashfs' as requested via option -q or -N"
957 ewarn "Skipping stage 'squashfs' as requested via option -q or -N" ; eend 0
959 [ -d "$BUILD_OUTPUT"/live ] || mkdir "$BUILD_OUTPUT"/live
960 # make sure we don't leave (even an empty) base.tgz:
961 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
963 # if unconfigured default to squashfs-tools' mksquashfs binary
964 if [ -z "$SQUASHFS_BINARY" ] ; then
965 SQUASHFS_BINARY='mksquashfs'
968 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
969 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
970 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
972 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
973 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
977 # use sane defaults if $SQUASHFS_OPTIONS isn't set
978 if [ -z "$SQUASHFS_OPTIONS" ] ; then
979 # use blocksize 256k as this gives best result with regards to time + compression
980 SQUASHFS_OPTIONS="-b 256k"
982 # set lzma/xz compression by default, unless -z option has been specified on command line
983 if [ -z "$SQUASHFS_ZLIB" ] ; then
984 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
986 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
990 # support exclusion of files via exclude-file:
991 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
992 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE -wildcards"
995 # get rid of unnecessary files when building grml-small for final release:
996 if echo "$CLASSES" | grep -q GRML_SMALL ; then
997 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
1001 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
1003 # informational stuff
1004 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1005 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1006 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1008 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1010 if $SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \
1011 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1012 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/filesystem.module
1013 log "Finished execution of stage 'squashfs' [$(date)]"
1014 einfo "Finished execution of stage 'squashfs'" ; eend 0
1016 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1017 log "$(cat $SQUASHFS_STDERR)"
1018 eerror "Error: there was a critical error executing stage 'squashfs':"
1019 cat "${SQUASHFS_STDERR}"
1024 FORCE_ISO_REBUILD=true
1027 # create md5sum file:
1028 if [ -z "$BOOTSTRAP_ONLY" ] ; then
1029 ( cd $BUILD_OUTPUT/GRML &&
1030 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1034 # ISO_OUTPUT - mkisofs {{{
1035 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1036 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1038 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1039 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1040 elif [ "$BOOT_METHOD" = "grub" ] ; then
1041 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/grub/stage2"
1042 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1043 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1046 # Just until http://bts.grml.org/grml/issue945 has been resolved.
1047 # HYBRID_METHOD defaults to manifold, so make sure the default works OOTB.
1048 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1049 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1050 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1051 HYBRID_METHOD='grub2'
1055 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1056 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1057 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1058 elif [ -n "$SKIP_MKISOFS" ] ; then
1059 log "Skipping stage 'iso build' as requested via option -n or -N"
1060 ewarn "Skipping stage 'iso build' as requested via option -n or -N" ; eend 0
1062 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1064 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1065 log "Forcing rebuild of ISO because files on ISO have been modified."
1066 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1069 # support mkisofs as well as genisoimage
1070 if which mkisofs >/dev/null 2>&1; then
1072 elif which genisoimage >/dev/null 2>&1; then
1073 MKISOFS='genisoimage'
1075 log "Error: neither mkisofs nor genisoimage available - can not create ISO."
1076 eerror "Error: neither mkisofs nor genisoimage available - can not create ISO." ; eend 1
1081 if cd "$BUILD_OUTPUT" ; then
1082 if [ "$BOOT_METHOD" = "grub2" ]; then
1083 # make a 2048-byte bootsector for El Torito
1084 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1085 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1086 echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
1087 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1089 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1090 "$MKISOFS" -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1091 -l -r -J $BOOT_ARGS -no-pad \
1092 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1093 # both of these need core.img there, so it’s easier to write it here
1094 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1095 # must be <= 30720 bytes
1096 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1097 conv=notrunc bs=512 seek=4 2>/dev/null
1100 # pad the output ISO to multiples of 256 KiB for partition table support
1101 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1102 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1103 siz=$((cyls * 16 * 32 * 512)) # size after padding
1104 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1105 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1107 # support disabling hybrid ISO image
1108 if [ "$HYBRID_METHOD" = "disable" ] ; then\
1109 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1110 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1112 # use isohybrid only on request
1113 elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
1114 if ! which isohybrid >/dev/null 2>&1 ; then
1115 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1117 log "Creating hybrid ISO file with isohybrid method"
1118 einfo "Creating hybrid ISO file with isohybrid method"
1119 # Notes for consideration:
1120 # "-entry 4 -type 1c"
1121 # * using 4 as the partition number is supposed to help with BIOSes
1122 # that only support USB-Zip boot
1123 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1124 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1125 # to get the BIOS even look at the partition created by isohybrid
1126 isohybrid "${ISO_OUTPUT}/${ISO_NAME}"
1129 # by default use our manifold boot method:
1131 # isoinfo is part of both mkisofs and genisoimage so we're good
1132 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1133 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN;1 *$/s//\1/p')
1134 if ! [ -r boot/grub/core.img ] ; then
1135 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1136 elif [ "${bootoff:-0}" -lt 1 ] ; then
1137 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1139 log "Creating hybrid ISO file with manifold method"
1140 einfo "Creating hybrid ISO file with manifold method"
1141 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1142 # 512 bytes: MBR, partition table, load GRUB 2
1143 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1145 # read only one but 2048-byte sized (scale: << 2) sector
1146 echo $bootoff $bootoff | \
1147 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1148 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1153 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1154 case $CLASSES in *RELEASE*)
1157 if cd $ISO_OUTPUT ; then
1158 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1159 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1160 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1161 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1170 if [ "$RC" = 0 ] ; then
1171 log "Finished execution of stage 'iso build' [$(date)]"
1172 einfo "Finished execution of stage 'iso build'" ; eend 0
1174 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1175 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1181 # log build information to database if grml-live-db is installed and enabled {{{
1183 if [ -d /usr/share/grml-live-db ] ; then
1186 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1187 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1188 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1189 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1191 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1192 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1193 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1197 # disable by default for now, not sure whether really everyone is using a local db file
1198 #if ! touch "$DPKG_DATABASE" ; then
1199 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1203 if ! [ -r "$DPKG_LIST" ] ; then
1204 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1205 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1207 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1208 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1209 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1212 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1228 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1229 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1231 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1233 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1237 ## END OF FILE #################################################################
1238 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=2