3 # Purpose: build process script for generating a (grml based) Linux Live-ISO
4 # Authors: grml-team (grml.org),
5 # (c) Michael Prokop <mika@grml.org>,
6 # (c) Thorsten Glaser <tg@mirbsd.org>
7 # Bug-Reports: see http://grml.org/bugs/
8 # License: This file is licensed under the GPL v2 or any later version.
9 ################################################################################
11 # some misc and global stuff {{{
15 # define function getfilesize before "set -e"
16 if stat --help >/dev/null 2>&1; then
17 getfilesize='stat -c %s' # GNU stat
19 getfilesize='stat -f %z' # BSD stat
23 # disable for now since it seems to cause some problems
27 GRML_LIVE_VERSION='0.14.1'
30 SOURCES_LIST_FILE='/etc/grml/fai/apt/sources.list'
31 ADDONS_LIST_FILE='/boot/isolinux/addons_list.cfg'
34 # usage information {{{
38 $PN - build process script for generating a (grml based) Linux Live-ISO
40 Usage: $PN [options, see as follows]
42 -a <architecture> architecture; available values: i386 and amd64
43 -b build the ISO without updating the chroot via FAI
44 -B build the ISO without touching the chroot (skips cleanup)
45 -c <classe[s]> classes to be used for building the ISO via FAI
46 -C <configfile> configuration file for grml-live
47 -d <date> use specified date instead of build time as date of release
48 -F force execution without prompting
49 -g <grml_name> set the grml flavour name
50 -h display short usage information and exit
51 -i <iso_name> name of ISO
52 -I <src_directory> directory which provides files that should become
53 part of the chroot/ISO
54 -n skip generation of ISO
55 -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:g:i:I:o:r:s:t:v:bBFnNquVz" opt; do
236 c) CLASSES="$OPTARG" ;;
237 C) CONFIG="$OPTARG" ;;
239 g) GRML_NAME="$OPTARG" ;;
240 i) ISO_NAME="$OPTARG" ;;
241 I) CHROOT_INSTALL="$OPTARG" ;;
243 N) BOOTSTRAP_ONLY=1; SKIP_MKISOFS=1; SKIP_MKSQUASHFS=1 ;;
244 o) OUTPUT="$OPTARG" ;;
245 q) SKIP_MKSQUASHFS=1 ;;
246 r) RELEASENAME="$OPTARG" ;;
247 s) SUITE="$OPTARG" ;;
248 t) TEMPLATE_DIRECTORY="$OPTARG";;
249 v) VERSION="$OPTARG" ;;
253 z) SQUASHFS_ZLIB=1 ;;
254 ?) echo "invalid option -$OPTARG" >&2; bailout 1 ;;
257 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
260 # assume sane defaults (if not set already) {{{
261 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
262 [ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux'
263 [ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_MEDIUM,I386"
264 [ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)"
265 [ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators '
266 [ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml"
267 [ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png'
268 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
269 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai'
270 [ -n "$GRML_NAME" ] || GRML_NAME='grml'
271 [ -n "$HOSTNAME" ] || HOSTNAME='grml'
272 [ -n "$HYBRID_METHOD" ] || HYBRID_METHOD='manifold'
273 [ -n "$NFSROOT_CONF" ] || NFSROOT_CONF='/etc/grml/fai/make-fai-nfsroot.conf'
274 [ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks'
275 [ -n "$SQUASHFS_EXCLUDES_FILE " ] || SQUASHFS_EXCLUDES_FILE='/etc/grml/fai/squashfs-excludes'
276 [ -n "$SUITE" ] || SUITE='squeeze'
277 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
278 [ -n "$USERNAME" ] || USERNAME='grml'
279 [ -n "$VERSION" ] || VERSION='0.0.1'
281 # output specific stuff, depends on $OUTPUT (iff not set):
282 [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live'
283 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
284 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
285 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
288 # some misc checks before executing FAI {{{
289 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
290 specify it on the command line using the -c option."
291 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
292 specify it on the command line using the -o option."
294 # trim characters that are known to cause problems inside $GRML_NAME;
295 # for example isolinux does not like '-' inside the directory name
296 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
298 # export variables to have them available in fai scripts:
299 [ -n "$GRML_NAME" ] && export GRML_NAME="$GRML_NAME"
300 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
303 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
304 # this was default behaviour until grml-live 0.9.34:
305 if [ -n "$ZERO_LOGFILE" ] ; then
306 PRESERVE_LOGFILE='' # make sure it's cleaned then
307 ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
308 ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
313 # ask user whether the setup is ok {{{
314 if [ -z "$FORCE" ] ; then
316 echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
318 echo " FAI classes: $CLASSES"
319 [ -r "$LOCAL_CONFIG" ] && echo " Local config: /etc/grml/grml-live.local"
320 [ -n "$CONFIG" ] && echo " Configuration: $CONFIG"
321 echo " main directory: $OUTPUT"
322 [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT"
323 [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT"
324 [ -n "$ISO_OUTPUT" ] && echo " ISO target: $ISO_OUTPUT"
325 [ -n "$GRML_NAME" ] && echo " Grml name: $GRML_NAME"
326 [ -n "$RELEASENAME" ] && echo " Release name: $RELEASENAME"
327 [ -n "$DATE" ] && echo " Build date: $DATE"
328 [ -n "$VERSION" ] && echo " Grml version: $VERSION"
329 [ -n "$SUITE" ] && echo " Debian suite: $SUITE"
330 [ -n "$ARCH" ] && echo " Architecture: $ARCH"
331 [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD"
332 [ -n "$HYBRID_METHOD" ] && echo " Hybrid method: $HYBRID_METHOD"
333 [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY"
334 [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL"
335 [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID"
336 [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature."
337 [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
338 [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS"
339 [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE"
340 [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA/XZ) compression."
341 [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
342 [ -n "$VERBOSE" ] && echo " Using VERBOSE mode."
343 [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation."
344 if [ -n "$BOOTSTRAP_ONLY" ] ; then
345 echo " Bootstrapping only and not building (files for) ISO."
347 [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file."
348 [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file."
349 [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE."
350 [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched."
353 echo -n "Is this ok for you? [y/N] "
355 if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
356 bailout 1 "Exiting as requested."
362 # clean/zero/remove logfiles {{{
364 if [ -n "$PRESERVE_LOGFILE" ] ; then
365 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
367 # make sure it is empty (as it is e.g. appended to grml-live-db)
371 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
372 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
373 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
374 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
375 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
376 rm -f /var/log/fai/"$HOSTNAME"/last \
377 /var/log/fai/"$HOSTNAME"/last-dirinstall \
378 /var/log/fai/"$HOSTNAME"/last-softupdate
383 # source config and startup {{{
384 if [ -n "$CONFIG" ] ; then
385 if ! [ -f "$CONFIG" ] ; then
386 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
387 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
390 log "Sourcing $CONFIG"
395 start_seconds=$(cut -d . -f 1 /proc/uptime)
396 log "------------------------------------------------------------------------------"
397 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
398 log "Executed grml-live command line:"
401 einfo "Logging actions to logfile $LOGFILE"
404 # on-the-fly configuration {{{
405 if [ -n "$MIRROR_DIRECTORY" ] ; then
406 if ! [ -d "$MIRROR_DIRECTORY/debian" ] ; then
407 log "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting. [$(date)]"
408 eerror "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting." ; eend 1
411 cat > "$SOURCES_LIST_FILE" << EOF
412 # NOTE: This file is *NOT* meant for manual customisation! This file is
413 # modified by grml-live and any changes might be overridden.
414 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
415 # or FAI's fcopy command with /etc/grml/fai/config/files instead!
417 echo "$MIRROR_SOURCES" >> "$SOURCES_LIST_FILE"
418 if [ -n "$GRML_LIVE_SOURCES" ] ; then
419 echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
421 elif [ -n "$GRML_LIVE_SOURCES" ] ; then
422 cat > "$SOURCES_LIST_FILE" << EOF
423 # NOTE: This file is *NOT* meant for manual customisation! This file is
424 # modified by grml-live and any changes might be overridden.
425 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
426 # or FAI's fcopy command with /etc/grml/fai/config/files instead!
428 echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
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_FILE" | sponge "$SOURCES_LIST_FILE"
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_FILE" ; then
462 grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" || \
463 grep grml-stable "$SOURCES_LIST_FILE" | \
464 sed 's/grml-stable/grml-live/' >> "$SOURCES_LIST_FILE"
466 grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" && \
467 sed 's/.*grml-live.*/# removed grml-live repository/' "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
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 -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS"
548 BUILD_ONLY="$BUILD_ONLY" BOOTSTRAP_ONLY="$BOOTSTRAP_ONLY" fai $VERBOSE -C "$GRML_FAI_CONFIG" -c"$CLASSES" -u \
549 "$HOSTNAME" $FAI_ACTION "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
550 RC="$PIPESTATUS" # notice: bash-only
552 rm -f "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d/unsafe-io"
554 FORCE_ISO_REBUILD=true
556 if [ "$RC" != 0 ] ; then
557 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
558 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
561 log "Setting /etc/grml_version to $GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]"
562 echo "$GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]" > $CHROOT_OUTPUT/etc/grml_version
563 chmod 644 $CHROOT_OUTPUT/etc/grml_version
564 einfo "Rebuilding initramfs"
565 # make sure new /etc/grml_version reaches initramfs, iterate over all
566 # present kernel versions (note: we can't really handle more than one
567 # kernel version anyway right now)
568 # chroot $CHROOT_OUTPUT update-initramfs -u -t => might break when using kernel-package :(
569 for initrd in "$(basename $CHROOT_OUTPUT/boot/vmlinuz-*)" ; do
570 chroot $CHROOT_OUTPUT update-initramfs -k "${initrd##vmlinuz-}" -c
575 # Remove all FAI logs from chroot if class RELEASE is used:
576 if [ -f "$CHROOT_OUTPUT"/etc/grml_fai_release ] ; then
577 rm -rf "$CHROOT_OUTPUT"/var/log/fai/*
578 rm -f "$CHROOT_OUTPUT"/var/log/install_packages.list
583 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
585 CHECKLOG=/var/log/fai/$HOSTNAME/last
586 if [ -r "$CHECKLOG/software.log" ] ; then
587 # 1 errors during executing of commands
588 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
589 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
590 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
591 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
592 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
595 if [ -r "$CHECKLOG/shell.log" ] ; then
596 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
599 if [ -n "$ERROR" ] ; then
600 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
601 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
602 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
606 log "Finished execution of stage 'fai dirinstall' [$(date)]"
607 einfo "Finished execution of stage 'fai dirinstall'"
610 einfo "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
611 log "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
617 # package validator {{{
618 CHECKLOG=/var/log/fai/$HOSTNAME/last
620 if [ -r "$CHECKLOG/package_errors.log" ] && grep -q '[a-z]' "$CHECKLOG/package_errors.log" ; then
622 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
623 eerror "The following packages were requested for installation but could not be processed:"
624 cat $CHECKLOG/package_errors.log
625 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
629 ewarn "The following packages were requested for installation but could not be processed:"
630 cat $CHECKLOG/package_errors.log
636 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
637 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
638 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
641 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
642 if [ -n "$BOOTSTRAP_ONLY" ] ; then
643 log "Skipping stage 'boot' as building with bootstrap only."
644 ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0
646 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
647 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
648 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
651 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
652 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
654 if [ -z "$NO_ADDONS" ] ; then
655 [ -d "$BUILD_OUTPUT"/boot/addons ] || mkdir -p "$BUILD_OUTPUT"/boot/addons
656 if [ -r "$TEMPLATE_DIRECTORY"/boot/addons/memtest ] ; then
657 log "Installing $TEMPLATE_DIRECTORY/boot/addons/memtest"
658 cp "$TEMPLATE_DIRECTORY"/boot/addons/memtest "$BUILD_OUTPUT"/boot/addons/memtest
659 elif [ -r /boot/memtest86+.bin ] ; then
660 log "Installing /boot/memtest86+.bin"
661 cp /boot/memtest86+.bin "$BUILD_OUTPUT"/boot/addons/memtest
663 ewarn "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
664 log "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
669 # if we don't have an initrd we a) can't boot and b) there was an error
670 # during build, so check for the file:
671 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
672 if [ -n "$INITRD" ] ; then
673 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.gz
674 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
676 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
677 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
681 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
682 if [ -n "$KERNEL_IMAGE" ] ; then
683 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/linux26
685 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
686 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
690 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
691 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
692 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
693 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
697 # *always* copy files to output directory so the variables
698 # get adjusted according to the build
699 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
701 if [ -n "$NO_ADDONS" ] ; then
702 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
703 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
705 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
706 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
707 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
709 # copy only files so we can handle bsd4grml on its own
710 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
711 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
714 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
715 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
716 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
718 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
719 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
721 log "bsd4grml addon not found, skipping therefore."
722 ewarn "bsd4grml addon not found, skipping therefore." ; eend 0
726 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
729 if ! [ -d ${TEMPLATE_DIRECTORY}/boot/grub ] ; then
730 log "grub templates do not exist, skipping therefore."
731 ewarn "grub templates do not exist, skipping therefore." ; eend 0
733 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
734 cp -a ${TEMPLATE_DIRECTORY}/boot/grub "$BUILD_OUTPUT"/boot/
737 # make sure we have recent template files available, otherwise updating
738 # the strings like $GRML_NAME and $VERSION might be out of date
739 cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
742 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
743 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
744 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
748 [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML
749 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/
751 # adjust boot splash information:
752 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
753 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
754 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
756 if [ -r "$BUILD_OUTPUT"/GRML/grml-version ] ; then
757 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version
758 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/grml-version
761 # make sure the squashfs filename is set accordingly:
762 SQUASHFS_NAME="$GRML_NAME.squashfs"
764 if [ -n "$NO_BOOTID" ] ; then
765 log 'Skipping bootid feature as requested via $NO_BOOTID.'
766 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
768 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
769 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
770 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
771 log "Generating /conf/bootid.txt with entry ${BOOTID}."
772 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
776 # adjust all variables in the templates with the according distribution information
777 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
778 "${BUILD_OUTPUT}"/boot/grub/* ; do
779 if [ -r "${file}" ] ; then
780 sed -i "s/%ARCH%/$ARCH/g" "${file}"
781 sed -i "s/%DATE%/$DATE/g" "${file}"
782 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
783 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
784 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
785 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
786 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
787 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
788 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
789 sed -i "s/%VERSION%/$VERSION/g" "${file}"
791 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s/ boot=live/ boot=live $DEFAULT_BOOTOPTIONS/" "${file}"
793 if [ -n "$NO_BOOTID" ] ; then
794 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
796 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
801 # adjust bootsplash accordingly but make sure the string has the according lenght
802 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
803 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
804 for file in f4 f5 ; do
805 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
806 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
807 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
811 # generate addon list
812 rm "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
813 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
814 include_name=$(basename "$name")
815 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
818 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
819 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
820 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
821 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
822 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
823 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
825 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
826 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
829 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
830 if [ ! -n "$NO_ADDONS" ] ; then
831 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
833 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
834 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
835 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
836 else # assume we are building a custom distribution:
837 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
838 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
839 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
840 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
842 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
846 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
847 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
848 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
852 # use old style console based isolinux method only if requested:
853 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
854 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
855 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
856 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
857 einfo "include for console.cfg already foud, nothing to do."
860 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
861 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
862 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
866 log 'Using graphical boot menu.'
867 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
868 log "include for vesamenu.cfg already foud, nothing to do."
870 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
871 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
875 # jump back to grub from bsd4grml (/boot/grub/stage2):
878 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
879 if [ -e "$BUILD_OUTPUT"/boot/grub/core.img ]; then
885 for file in "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 \
886 "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.cfg \
887 "$BUILD_OUTPUT"/boot/isolinux/*.cfg \
888 "$BUILD_OUTPUT"/boot/grub/grub.cfg \
889 "$BUILD_OUTPUT"/boot/grub/menu.lst ; do
890 if [ -e "$file" ] ; then
891 sed -i -e "s!%GRUB_VERSION%!$GRUB_VERSION!g" \
892 -e "s!%GRUB_LEGACY%!$GRUB_LEGACY!g" "$file"
896 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
899 if [ -e "$BUILD_OUTPUT"/boot/grub/$GRUB_LEGACY ]; then
900 sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/menu.lst
901 sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/grub.cfg
902 elif [ -e "$BUILD_OUTPUT"/boot/grub/menu.lst -a -e "$BUILD_OUTPUT"/boot/grub/grub.cfg ] ; then
903 sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/menu.lst
904 sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/grub.cfg
907 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
908 if ! [ -r "$DPKG_LIST" ] ; then
909 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
911 einfo "Storing package list information as /GRML/${GRML_NAME}-packages.txt on ISO."
912 cp "$DPKG_LIST" "${BUILD_OUTPUT}/GRML/${GRML_NAME}-packages.txt"
916 # autostart for Windows:
917 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
918 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
921 FORCE_ISO_REBUILD=true
922 einfo "Finished execution of stage 'boot'" ; eend 0
926 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
927 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
931 # support installation of local files into the chroot/ISO
932 if [ -n "$CHROOT_INSTALL" ] ; then
933 if ! [ -d "$CHROOT_INSTALL" ] ; then
934 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
935 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
937 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
938 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
939 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
941 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
942 FORCE_ISO_REBUILD=true
946 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
947 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
948 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
949 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
950 log "Skipping stage 'squashfs' as requested via option -q or -N"
951 ewarn "Skipping stage 'squashfs' as requested via option -q or -N" ; eend 0
953 [ -d "$BUILD_OUTPUT"/live ] || mkdir "$BUILD_OUTPUT"/live
954 # make sure we don't leave (even an empty) base.tgz:
955 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
957 # if unconfigured default to squashfs-tools' mksquashfs binary
958 if [ -z "$SQUASHFS_BINARY" ] ; then
959 SQUASHFS_BINARY='mksquashfs'
962 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
963 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
964 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
966 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
967 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
971 # use sane defaults if $SQUASHFS_OPTIONS isn't set
972 if [ -z "$SQUASHFS_OPTIONS" ] ; then
973 # use blocksize 256k as this gives best result with regards to time + compression
974 SQUASHFS_OPTIONS="-b 256k"
976 # set lzma/xz compression by default, unless -z option has been specified on command line
977 if [ -z "$SQUASHFS_ZLIB" ] ; then
978 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
980 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
984 # support exclusion of files via exclude-file:
985 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
986 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE"
989 # get rid of unnecessary files when building grml-small for final release:
990 if echo "$CLASSES" | grep -q GRML_SMALL ; then
991 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
995 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
997 # informational stuff
998 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
999 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1000 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1002 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1004 if $SQUASHFS_BINARY $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \
1005 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1006 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/filesystem.module
1007 log "Finished execution of stage 'squashfs' [$(date)]"
1008 einfo "Finished execution of stage 'squashfs'" ; eend 0
1010 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1011 log "$(cat $SQUASHFS_STDERR)"
1012 eerror "Error: there was a critical error executing stage 'squashfs':"
1013 cat "${SQUASHFS_STDERR}"
1018 FORCE_ISO_REBUILD=true
1021 # create md5sum file:
1022 if [ -z "$BOOTSTRAP_ONLY" ] ; then
1023 ( cd $BUILD_OUTPUT/GRML &&
1024 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1028 # ISO_OUTPUT - mkisofs {{{
1029 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1030 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1032 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1033 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1034 elif [ "$BOOT_METHOD" = "grub" ] ; then
1035 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/grub/stage2"
1036 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1037 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1040 # Just until http://bts.grml.org/grml/issue945 has been resolved.
1041 # HYBRID_METHOD defaults to manifold, so make sure the default works OOTB.
1042 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1043 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1044 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1045 HYBRID_METHOD='grub2'
1049 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1050 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1051 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1052 elif [ -n "$SKIP_MKISOFS" ] ; then
1053 log "Skipping stage 'iso build' as requested via option -n or -N"
1054 ewarn "Skipping stage 'iso build' as requested via option -n or -N" ; eend 0
1056 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1058 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1059 log "Forcing rebuild of ISO because files on ISO have been modified."
1060 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1063 # support mkisofs as well as genisoimage
1064 if which mkisofs >/dev/null 2>&1; then
1066 elif which genisoimage >/dev/null 2>&1; then
1067 MKISOFS='genisoimage'
1069 log "Error: neither mkisofs nor genisoimage available - can not create ISO."
1070 eerror "Error: neither mkisofs nor genisoimage available - can not create ISO." ; eend 1
1075 if cd "$BUILD_OUTPUT" ; then
1076 if [ "$BOOT_METHOD" = "grub2" ]; then
1077 # make a 2048-byte bootsector for El Torito
1078 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1079 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1080 echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
1081 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1083 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1084 "$MKISOFS" -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1085 -l -r -J $BOOT_ARGS -no-pad \
1086 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1087 # both of these need core.img there, so it’s easier to write it here
1088 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1089 # must be <= 30720 bytes
1090 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1091 conv=notrunc bs=512 seek=4 2>/dev/null
1094 # pad the output ISO to multiples of 256 KiB for partition table support
1095 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1096 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1097 siz=$((cyls * 16 * 32 * 512)) # size after padding
1098 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1099 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1101 # support disabling hybrid ISO image
1102 if [ "$HYBRID_METHOD" = "disable" ] ; then\
1103 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1104 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1106 # use isohybrid only on request
1107 elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
1108 if ! which isohybrid >/dev/null 2>&1 ; then
1109 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1111 log "Creating hybrid ISO file with isohybrid method"
1112 einfo "Creating hybrid ISO file with isohybrid method"
1113 # Notes for consideration:
1114 # "-entry 4 -type 1c"
1115 # * using 4 as the partition number is supposed to help with BIOSes
1116 # that only support USB-Zip boot
1117 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1118 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1119 # to get the BIOS even look at the partition created by isohybrid
1120 isohybrid "${ISO_OUTPUT}/${ISO_NAME}"
1123 # by default use our manifold boot method:
1125 # isoinfo is part of both mkisofs and genisoimage so we're good
1126 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1127 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN;1 *$/s//\1/p')
1128 if ! [ -r boot/grub/core.img ] ; then
1129 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1130 elif [ "${bootoff:-0}" -lt 1 ] ; then
1131 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1133 log "Creating hybrid ISO file with manifold method"
1134 einfo "Creating hybrid ISO file with manifold method"
1135 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1136 # 512 bytes: MBR, partition table, load GRUB 2
1137 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1139 # read only one but 2048-byte sized (scale: << 2) sector
1140 echo $bootoff $bootoff | \
1141 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1142 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1147 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1148 case $CLASSES in *RELEASE*)
1151 if cd $ISO_OUTPUT ; then
1152 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1153 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1154 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1155 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1164 if [ "$RC" = 0 ] ; then
1165 log "Finished execution of stage 'iso build' [$(date)]"
1166 einfo "Finished execution of stage 'iso build'" ; eend 0
1168 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1169 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1175 # log build information to database if grml-live-db is installed and enabled {{{
1177 if [ -d /usr/share/grml-live-db ] ; then
1180 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1181 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1182 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1183 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1185 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1186 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1187 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1191 # disable by default for now, not sure whether really everyone is using a local db file
1192 #if ! touch "$DPKG_DATABASE" ; then
1193 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1197 if ! [ -r "$DPKG_LIST" ] ; then
1198 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1199 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1201 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1202 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1203 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1206 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1222 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1223 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1225 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1227 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1231 ## END OF FILE #################################################################
1232 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=3