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_OUTPUT" ] || SOURCES_LIST_OUTPUT="${GRML_FAI_CONFIG}/config/files/etc/apt/sources.list/GRML_LIVE_SOURCES_LIST"
277 [ -n "$SQUASHFS_EXCLUDES_FILE" ] || SQUASHFS_EXCLUDES_FILE="${GRML_FAI_CONFIG}/config/grml/squashfs-excludes"
278 [ -n "$SUITE" ] || SUITE='squeeze'
279 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
280 [ -n "$USERNAME" ] || USERNAME='grml'
281 [ -n "$VERSION" ] || VERSION='0.0.1'
283 # output specific stuff, depends on $OUTPUT (iff not set):
284 [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live'
285 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
286 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
287 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
290 # some misc checks before executing FAI {{{
291 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
292 specify it on the command line using the -c option."
293 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
294 specify it on the command line using the -o option."
296 # trim characters that are known to cause problems inside $GRML_NAME;
297 # for example isolinux does not like '-' inside the directory name
298 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
300 # export variables to have them available in fai scripts:
301 [ -n "$GRML_NAME" ] && export GRML_NAME="$GRML_NAME"
302 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
305 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
306 # this was default behaviour until grml-live 0.9.34:
307 if [ -n "$ZERO_LOGFILE" ] ; then
308 PRESERVE_LOGFILE='' # make sure it's cleaned then
309 ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
310 ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
315 # ask user whether the setup is ok {{{
316 if [ -z "$FORCE" ] ; then
318 echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
320 echo " FAI classes: $CLASSES"
321 [ -r "$LOCAL_CONFIG" ] && echo " Local config: /etc/grml/grml-live.local"
322 [ -n "$CONFIG" ] && echo " Configuration: $CONFIG"
323 [ -n "$GRML_FAI_CONFIG" ] && echo " Config directory: $GRML_FAI_CONFIG"
324 echo " main directory: $OUTPUT"
325 [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT"
326 [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT"
327 [ -n "$ISO_OUTPUT" ] && echo " ISO target: $ISO_OUTPUT"
328 [ -n "$GRML_NAME" ] && echo " Grml name: $GRML_NAME"
329 [ -n "$RELEASENAME" ] && echo " Release name: $RELEASENAME"
330 [ -n "$DATE" ] && echo " Build date: $DATE"
331 [ -n "$VERSION" ] && echo " Grml version: $VERSION"
332 [ -n "$SUITE" ] && echo " Debian suite: $SUITE"
333 [ -n "$ARCH" ] && echo " Architecture: $ARCH"
334 [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD"
335 [ -n "$HYBRID_METHOD" ] && echo " Hybrid method: $HYBRID_METHOD"
336 [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY"
337 [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL"
338 [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID"
339 [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature."
340 [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
341 [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS"
342 [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE"
343 [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA/XZ) compression."
344 [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
345 [ -n "$VERBOSE" ] && echo " Using VERBOSE mode."
346 [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation."
347 if [ -n "$BOOTSTRAP_ONLY" ] ; then
348 echo " Bootstrapping only and not building (files for) ISO."
350 [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file."
351 [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file."
352 [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE."
353 [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched."
356 echo -n "Is this ok for you? [y/N] "
358 if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
359 bailout 1 "Exiting as requested."
365 # clean/zero/remove logfiles {{{
367 if [ -n "$PRESERVE_LOGFILE" ] ; then
368 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
370 # make sure it is empty (as it is e.g. appended to grml-live-db)
374 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
375 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
376 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
377 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
378 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
379 rm -f /var/log/fai/"$HOSTNAME"/last \
380 /var/log/fai/"$HOSTNAME"/last-dirinstall \
381 /var/log/fai/"$HOSTNAME"/last-softupdate
386 # source config and startup {{{
387 if [ -n "$CONFIG" ] ; then
388 if ! [ -f "$CONFIG" ] ; then
389 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
390 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
393 log "Sourcing $CONFIG"
398 start_seconds=$(cut -d . -f 1 /proc/uptime)
399 log "------------------------------------------------------------------------------"
400 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
401 log "Executed grml-live command line:"
404 einfo "Logging actions to logfile $LOGFILE"
407 # on-the-fly configuration {{{
408 mkdir -p "$(dirname $SOURCES_LIST_OUTPUT)" # might not be present in -D config space
410 cat > "$SOURCES_LIST_OUTPUT" << EOF
411 # NOTE: This file is *NOT* meant for manual customisation! This file is
412 # installed temporarily only by grml-live and will be overriden in the
413 # installation and configuration process then.
416 if [ -n "$MIRROR_DIRECTORY" ] ; then
417 if ! [ -d "$MIRROR_DIRECTORY/debian" ] ; then
418 log "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting. [$(date)]"
419 eerror "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting." ; eend 1
422 echo "$MIRROR_SOURCES" >> "$SOURCES_LIST_OUTPUT"
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 ;;
444 export SUITE # make sure it's available in FAI scripts
446 if [ -n "${GRML_LIVE_SOURCES:-}" ] ; then
447 DIST=" etch\| stable\| lenny\| squeeze\| wheezy\| testing\| sid\| unstable"
448 echo "# generated based on \$GRML_LIVE_SOURCES by grml-live
449 $GRML_LIVE_SOURCES" | \
450 sed -e "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/;
451 s/\(^deb-src .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" >> "$SOURCES_LIST_OUTPUT"
453 cat >> "$SOURCES_LIST_OUTPUT" << EOF
454 # generated by grml-live
455 deb http://deb.grml.org/ grml-stable main
456 deb http://deb.grml.org/ grml-testing main
457 deb http://cdn.debian.net/debian $SUITE main contrib non-free
461 # notice: activate grml-live pool only if we are building against unstable:
462 if grep -qwe unstable -qwe sid "$SOURCES_LIST_OUTPUT" ; then
463 grep -q 'grml-live.*main' "$SOURCES_LIST_OUTPUT" || \
464 grep grml-stable "$SOURCES_LIST_OUTPUT" | \
465 sed 's/grml-stable/grml-live/' >> "$SOURCES_LIST_OUTPUT"
467 grep -q 'grml-live.*main' "$SOURCES_LIST_OUTPUT" && \
468 sed -i 's/.*grml-live.*main/# removed grml-live repository/' "$SOURCES_LIST_OUTPUT"
471 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" "$NFSROOT_CONF" ; do
472 if [ -n "$file" ] ; then
473 sed "s|^FAI_DEBOOTSTRAP=\"[a-z]* |FAI_DEBOOTSTRAP=\"$SUITE |" "$file" | sponge "$file"
477 # validate whether the specified architecture class matches the
478 # architecture (option), otherwise installation of kernel will fail
479 if echo $CLASSES | grep -qi i386 ; then
480 if ! [[ "$ARCH" == "i386" ]] ; then
481 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
482 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
483 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
487 elif echo $CLASSES | grep -qi amd64 ; then
488 if ! [[ "$ARCH" == "amd64" ]] ; then
489 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
490 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
491 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
497 if grep -q -- 'FAI_DEBOOTSTRAP_OPTS.*--arch' "$NFSROOT_CONF" ; then
498 sed "s/--arch [a-z0-9]* /--arch $ARCH /" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
500 sed "s|^FAI_DEBOOTSTRAP_OPTS=\"\(.*\)|FAI_DEBOOTSTRAP_OPTS=\"--arch $ARCH \1|" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
504 # CHROOT_OUTPUT - execute FAI {{{
505 if [ -n "$BUILD_DIRTY" ]; then
506 log "Skipping stage 'fai' as requested via option -B"
507 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
509 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
511 # provide inform fai about the ISO we build
512 [ -d "$CHROOT_OUTPUT/etc/" ] || mkdir -p "$CHROOT_OUTPUT/etc/"
513 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
514 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
515 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
517 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
518 FAI_ACTION=softupdate
520 FAI_ACTION=dirinstall
523 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
524 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
525 log "Error: does not look like you have a working chroot. Updating/building not possible."
526 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
532 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
533 log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
534 ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
536 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
538 if [ -n "${MIRROR_DIRECTORY}" ] ; then
539 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
540 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
543 # tell dpkg to use "unsafe io" during the build
544 [ -d "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d" ] || mkdir -p "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d"
545 echo force-unsafe-io > "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d/unsafe-io"
547 log "Executed FAI command line:"
548 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"
549 BUILD_ONLY="$BUILD_ONLY" BOOTSTRAP_ONLY="$BOOTSTRAP_ONLY" fai $VERBOSE \
550 -C "$GRML_FAI_CONFIG" -s "file:///$GRML_FAI_CONFIG/config" -c"$CLASSES" \
551 -u "$HOSTNAME" "$FAI_ACTION" "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
552 RC="$PIPESTATUS" # notice: bash-only
554 rm -f "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d/unsafe-io"
556 FORCE_ISO_REBUILD=true
558 if [ "$RC" != 0 ] ; then
559 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
560 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
563 einfo "Setting /etc/grml_version to $GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]"
564 log "Setting /etc/grml_version to $GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]"
565 echo "$GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]" > $CHROOT_OUTPUT/etc/grml_version
566 chmod 644 $CHROOT_OUTPUT/etc/grml_version
567 einfo "Rebuilding initramfs"
568 # make sure new /etc/grml_version reaches initramfs, iterate over all
569 # present kernel versions (note: we can't really handle more than one
570 # kernel version anyway right now)
571 # chroot $CHROOT_OUTPUT update-initramfs -u -t => might break when using kernel-package :(
572 for initrd in "$(basename $CHROOT_OUTPUT/boot/vmlinuz-*)" ; do
573 if ! chroot $CHROOT_OUTPUT update-initramfs -k "${initrd##vmlinuz-}" -c ; then
574 einfo "Creating fresh initrd did not work, trying update instead:"
575 log "Creating fresh initrd did not work, trying update instead:"
576 chroot $CHROOT_OUTPUT update-initramfs -k "${initrd##vmlinuz-}" -u
582 # Remove all FAI logs from chroot if class RELEASE is used:
583 if [ -f "$CHROOT_OUTPUT"/etc/grml_fai_release ] ; then
584 rm -rf "$CHROOT_OUTPUT"/var/log/fai/*
585 rm -f "$CHROOT_OUTPUT"/var/log/install_packages.list
590 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
592 CHECKLOG=/var/log/fai/$HOSTNAME/last
593 if [ -r "$CHECKLOG/software.log" ] ; then
594 # 1 errors during executing of commands
595 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
596 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
597 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
598 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
599 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
602 if [ -r "$CHECKLOG/shell.log" ] ; then
603 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
606 if [ -n "$ERROR" ] ; then
607 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
608 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
609 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
613 log "Finished execution of stage 'fai dirinstall' [$(date)]"
614 einfo "Finished execution of stage 'fai dirinstall'"
617 einfo "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
618 log "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
624 # package validator {{{
625 CHECKLOG=/var/log/fai/$HOSTNAME/last
627 if [ -r "$CHECKLOG/package_errors.log" ] && grep -q '[a-z]' "$CHECKLOG/package_errors.log" ; then
629 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
630 eerror "The following packages were requested for installation but could not be processed:"
631 cat $CHECKLOG/package_errors.log
632 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
636 ewarn "The following packages were requested for installation but could not be processed:"
637 cat $CHECKLOG/package_errors.log
643 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
644 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
645 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
648 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
649 if [ -n "$BOOTSTRAP_ONLY" ] ; then
650 log "Skipping stage 'boot' as building with bootstrap only."
651 ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0
653 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
654 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
655 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
658 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
659 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
661 if [ -z "$NO_ADDONS" ] ; then
662 [ -d "$BUILD_OUTPUT"/boot/addons ] || mkdir -p "$BUILD_OUTPUT"/boot/addons
663 if [ -r "$TEMPLATE_DIRECTORY"/boot/addons/memtest ] ; then
664 log "Installing $TEMPLATE_DIRECTORY/boot/addons/memtest"
665 cp "$TEMPLATE_DIRECTORY"/boot/addons/memtest "$BUILD_OUTPUT"/boot/addons/memtest
666 elif [ -r /boot/memtest86+.bin ] ; then
667 log "Installing /boot/memtest86+.bin"
668 cp /boot/memtest86+.bin "$BUILD_OUTPUT"/boot/addons/memtest
670 ewarn "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
671 log "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
676 # if we don't have an initrd we a) can't boot and b) there was an error
677 # during build, so check for the file:
678 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
679 if [ -n "$INITRD" ] ; then
680 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.gz
681 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
683 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
684 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
688 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
689 if [ -n "$KERNEL_IMAGE" ] ; then
690 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/linux26
692 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
693 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
697 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
698 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
699 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
700 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
704 # *always* copy files to output directory so the variables
705 # get adjusted according to the build
706 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
708 if [ -n "$NO_ADDONS" ] ; then
709 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
710 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
712 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
713 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
714 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
716 # copy only files so we can handle bsd4grml on its own
717 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
718 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
721 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
722 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
723 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
725 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
726 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
728 log "bsd4grml addon not found, skipping therefore."
729 ewarn "bsd4grml addon not found, skipping therefore." ; eend 0
733 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
736 if ! [ -d ${TEMPLATE_DIRECTORY}/boot/grub ] ; then
737 log "grub templates do not exist, skipping therefore."
738 ewarn "grub templates do not exist, skipping therefore." ; eend 0
740 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
741 cp -a ${TEMPLATE_DIRECTORY}/boot/grub "$BUILD_OUTPUT"/boot/
744 # make sure we have recent template files available, otherwise updating
745 # the strings like $GRML_NAME and $VERSION might be out of date
746 cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
749 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
750 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
751 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
755 [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML
756 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/
758 # adjust boot splash information:
759 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
760 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
761 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
763 if [ -r "$BUILD_OUTPUT"/GRML/grml-version ] ; then
764 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version
765 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/grml-version
768 # make sure the squashfs filename is set accordingly:
769 SQUASHFS_NAME="$GRML_NAME.squashfs"
771 if [ -n "$NO_BOOTID" ] ; then
772 log 'Skipping bootid feature as requested via $NO_BOOTID.'
773 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
775 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
776 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
777 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
778 log "Generating /conf/bootid.txt with entry ${BOOTID}."
779 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
783 # adjust all variables in the templates with the according distribution information
784 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
785 "${BUILD_OUTPUT}"/boot/grub/* ; do
786 if [ -r "${file}" ] ; then
787 sed -i "s/%ARCH%/$ARCH/g" "${file}"
788 sed -i "s/%DATE%/$DATE/g" "${file}"
789 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
790 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
791 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
792 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
793 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
794 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
795 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
796 sed -i "s/%VERSION%/$VERSION/g" "${file}"
798 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s/ boot=live/ boot=live $DEFAULT_BOOTOPTIONS/" "${file}"
800 if [ -n "$NO_BOOTID" ] ; then
801 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
803 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
808 # adjust bootsplash accordingly but make sure the string has the according lenght
809 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
810 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
811 for file in f4 f5 ; do
812 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
813 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
814 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
818 # generate addon list
819 rm "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
820 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
821 include_name=$(basename "$name")
822 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
825 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
826 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
827 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
828 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
829 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
830 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
832 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
833 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
836 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
837 if [ ! -n "$NO_ADDONS" ] ; then
838 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
840 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
841 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
842 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
843 else # assume we are building a custom distribution:
844 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
845 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
846 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
847 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
849 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
853 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
854 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
855 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
859 # use old style console based isolinux method only if requested:
860 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
861 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
862 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
863 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
864 einfo "include for console.cfg already foud, nothing to do."
867 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
868 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
869 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
873 log 'Using graphical boot menu.'
874 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
875 log "include for vesamenu.cfg already foud, nothing to do."
877 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
878 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
882 # jump back to grub from bsd4grml (/boot/grub/stage2):
885 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
886 if [ -e "$BUILD_OUTPUT"/boot/grub/core.img ]; then
892 for file in "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 \
893 "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.cfg \
894 "$BUILD_OUTPUT"/boot/isolinux/*.cfg \
895 "$BUILD_OUTPUT"/boot/grub/grub.cfg \
896 "$BUILD_OUTPUT"/boot/grub/menu.lst ; do
897 if [ -e "$file" ] ; then
898 sed -i -e "s!%GRUB_VERSION%!$GRUB_VERSION!g" \
899 -e "s!%GRUB_LEGACY%!$GRUB_LEGACY!g" "$file"
903 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
906 if [ -e "$BUILD_OUTPUT"/boot/grub/$GRUB_LEGACY ]; then
907 sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/menu.lst
908 sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/grub.cfg
909 elif [ -e "$BUILD_OUTPUT"/boot/grub/menu.lst -a -e "$BUILD_OUTPUT"/boot/grub/grub.cfg ] ; then
910 sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/menu.lst
911 sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/grub.cfg
914 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
915 if ! [ -r "$DPKG_LIST" ] ; then
916 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
918 einfo "Storing package list information as /GRML/${GRML_NAME}-packages.txt on ISO."
919 cp "$DPKG_LIST" "${BUILD_OUTPUT}/GRML/${GRML_NAME}-packages.txt"
923 # autostart for Windows:
924 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
925 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
928 FORCE_ISO_REBUILD=true
929 einfo "Finished execution of stage 'boot'" ; eend 0
933 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
934 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
938 # support installation of local files into the chroot/ISO
939 if [ -n "$CHROOT_INSTALL" ] ; then
940 if ! [ -d "$CHROOT_INSTALL" ] ; then
941 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
942 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
944 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
945 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
946 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
948 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
949 FORCE_ISO_REBUILD=true
953 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
954 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
955 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
956 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
957 log "Skipping stage 'squashfs' as requested via option -q or -N"
958 ewarn "Skipping stage 'squashfs' as requested via option -q or -N" ; eend 0
960 [ -d "$BUILD_OUTPUT"/live ] || mkdir "$BUILD_OUTPUT"/live
961 # make sure we don't leave (even an empty) base.tgz:
962 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
964 # if unconfigured default to squashfs-tools' mksquashfs binary
965 if [ -z "$SQUASHFS_BINARY" ] ; then
966 SQUASHFS_BINARY='mksquashfs'
969 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
970 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
971 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
973 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
974 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
978 # use sane defaults if $SQUASHFS_OPTIONS isn't set
979 if [ -z "$SQUASHFS_OPTIONS" ] ; then
980 # use blocksize 256k as this gives best result with regards to time + compression
981 SQUASHFS_OPTIONS="-b 256k"
983 # set lzma/xz compression by default, unless -z option has been specified on command line
984 if [ -z "$SQUASHFS_ZLIB" ] ; then
985 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
987 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
991 # support exclusion of files via exclude-file:
992 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
993 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE -wildcards"
996 # get rid of unnecessary files when building grml-small for final release:
997 if echo "$CLASSES" | grep -q GRML_SMALL ; then
998 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
1002 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
1004 # informational stuff
1005 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1006 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1007 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1009 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1011 if $SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \
1012 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1013 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/filesystem.module
1014 log "Finished execution of stage 'squashfs' [$(date)]"
1015 einfo "Finished execution of stage 'squashfs'" ; eend 0
1017 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1018 log "$(cat $SQUASHFS_STDERR)"
1019 eerror "Error: there was a critical error executing stage 'squashfs':"
1020 cat "${SQUASHFS_STDERR}"
1025 FORCE_ISO_REBUILD=true
1028 # create md5sum file:
1029 if [ -z "$BOOTSTRAP_ONLY" ] ; then
1030 ( cd $BUILD_OUTPUT/GRML &&
1031 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1035 # ISO_OUTPUT - mkisofs {{{
1036 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1037 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1039 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1040 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1041 elif [ "$BOOT_METHOD" = "grub" ] ; then
1042 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/grub/stage2"
1043 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1044 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1047 # Just until http://bts.grml.org/grml/issue945 has been resolved.
1048 # HYBRID_METHOD defaults to manifold, so make sure the default works OOTB.
1049 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1050 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1051 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1052 HYBRID_METHOD='grub2'
1056 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1057 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1058 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1059 elif [ -n "$SKIP_MKISOFS" ] ; then
1060 log "Skipping stage 'iso build' as requested via option -n or -N"
1061 ewarn "Skipping stage 'iso build' as requested via option -n or -N" ; eend 0
1063 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1065 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1066 log "Forcing rebuild of ISO because files on ISO have been modified."
1067 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1070 # support mkisofs as well as genisoimage
1071 if which mkisofs >/dev/null 2>&1; then
1073 elif which genisoimage >/dev/null 2>&1; then
1074 MKISOFS='genisoimage'
1076 log "Error: neither mkisofs nor genisoimage available - can not create ISO."
1077 eerror "Error: neither mkisofs nor genisoimage available - can not create ISO." ; eend 1
1082 if cd "$BUILD_OUTPUT" ; then
1083 if [ "$BOOT_METHOD" = "grub2" ]; then
1084 # make a 2048-byte bootsector for El Torito
1085 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1086 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1087 echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
1088 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1090 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1091 "$MKISOFS" -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1092 -l -r -J $BOOT_ARGS -no-pad \
1093 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1094 # both of these need core.img there, so it’s easier to write it here
1095 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1096 # must be <= 30720 bytes
1097 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1098 conv=notrunc bs=512 seek=4 2>/dev/null
1101 # pad the output ISO to multiples of 256 KiB for partition table support
1102 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1103 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1104 siz=$((cyls * 16 * 32 * 512)) # size after padding
1105 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1106 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1108 # support disabling hybrid ISO image
1109 if [ "$HYBRID_METHOD" = "disable" ] ; then\
1110 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1111 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1113 # use isohybrid only on request
1114 elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
1115 if ! which isohybrid >/dev/null 2>&1 ; then
1116 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1118 log "Creating hybrid ISO file with isohybrid method"
1119 einfo "Creating hybrid ISO file with isohybrid method"
1120 # Notes for consideration:
1121 # "-entry 4 -type 1c"
1122 # * using 4 as the partition number is supposed to help with BIOSes
1123 # that only support USB-Zip boot
1124 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1125 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1126 # to get the BIOS even look at the partition created by isohybrid
1127 isohybrid "${ISO_OUTPUT}/${ISO_NAME}"
1130 # by default use our manifold boot method:
1132 # isoinfo is part of both mkisofs and genisoimage so we're good
1133 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1134 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN;1 *$/s//\1/p')
1135 if ! [ -r boot/grub/core.img ] ; then
1136 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1137 elif [ "${bootoff:-0}" -lt 1 ] ; then
1138 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1140 log "Creating hybrid ISO file with manifold method"
1141 einfo "Creating hybrid ISO file with manifold method"
1142 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1143 # 512 bytes: MBR, partition table, load GRUB 2
1144 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1146 # read only one but 2048-byte sized (scale: << 2) sector
1147 echo $bootoff $bootoff | \
1148 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1149 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1154 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1155 case $CLASSES in *RELEASE*)
1158 if cd $ISO_OUTPUT ; then
1159 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1160 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1161 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1162 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1171 if [ "$RC" = 0 ] ; then
1172 log "Finished execution of stage 'iso build' [$(date)]"
1173 einfo "Finished execution of stage 'iso build'" ; eend 0
1175 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1176 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1182 # log build information to database if grml-live-db is installed and enabled {{{
1184 if [ -d /usr/share/grml-live-db ] ; then
1187 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1188 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1189 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1190 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1192 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1193 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1194 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1198 # disable by default for now, not sure whether really everyone is using a local db file
1199 #if ! touch "$DPKG_DATABASE" ; then
1200 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1204 if ! [ -r "$DPKG_LIST" ] ; then
1205 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1206 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1208 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1209 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1210 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1213 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1229 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1230 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1232 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1234 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1238 ## END OF FILE #################################################################
1239 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=2