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 # avoid leaking into chroots
18 # define function getfilesize before "set -e"
19 if stat --help >/dev/null 2>&1; then
20 getfilesize='stat -c %s' # GNU stat
22 getfilesize='stat -f %z' # BSD stat
26 # disable for now since it seems to cause some problems
29 # The line following this line is patched by debian/rules.
30 GRML_LIVE_VERSION='***UNRELEASED***'
35 ADDONS_LIST_FILE='/boot/isolinux/addons_list.cfg'
38 # usage information {{{
42 $PN - build process script for generating a (grml based) Linux Live-ISO
44 Usage: $PN [options, see as follows]
46 -a <architecture> architecture; available values: i386 and amd64
47 -A clean build directories before and after running
48 -b build the ISO without updating the chroot via FAI
49 -B build the ISO without touching the chroot (skips cleanup)
50 -c <classe[s]> classes to be used for building the ISO via FAI
51 -C <configfile> configuration file for grml-live
52 -d <date> use specified date instead of build time as date of release
53 -D <configdir> use specified configuration directory instead of /etc/grml/fai
54 -e <iso_name> extract ISO and squashfs contents from iso_name
55 -F force execution without prompting
56 -g <grml_name> set the grml flavour name
57 -h display short usage information and exit
58 -i <iso_name> name of ISO
59 -I <src_directory> directory which provides files that should become
60 part of the chroot/ISO
61 -n skip generation of ISO
62 -N bootstrap (build chroot) only, do not create files for ISO
63 -o <output_directory> main output directory of the build process
65 -Q skip netboot package build
66 -r <release_name> release name
67 -s <suite> Debian suite/release, like: stable, testing, unstable
68 -S <script_directory> place of scripts (defaults to /usr/share/grml-live/scripts)
69 -t <template_directory> place of the templates
70 -u update existing chroot instead of rebuilding it from scratch
71 -U <username> arrange output to be owned by specified username
72 -v <version_number> specify version number of the release
73 -V increase verbosity in the build process
74 -w <date> wayback machine, build system using Debian archives
76 -z use ZLIB instead of LZMA/XZ compression
81 $PN -c GRMLBASE,GRML_FULL,AMD64 -o /dev/shm/grml
82 $PN -c GRMLBASE,GRML_FULL,AMD64 -i grml_0.0-1.iso -v 0.0-1
83 $PN -c GRMLBASE,GRML_FULL,AMD64 -s stable -V -r 'grml-ftw'
85 More details: man grml-live + /usr/share/doc/grml-live/grml-live.html
86 http://grml.org/grml-live/
88 Please send your bug reports and feedback to the grml-team: http://grml.org/bugs/
90 [ "$(id -u 2>/dev/null)" != 0 ] && echo "Please notice that this script requires root permissions."
93 # make sure it's possible to get usage information without being
94 # root or actually executing the script
95 if [ "$1" = '-h' -o "$1" = '--help' ] ; then
101 # some runtime checks {{{
102 # we need root permissions for the build-process:
103 if [ "$(id -u 2>/dev/null)" != 0 ] ; then
104 echo "Error: please run this script with uid 0 (root)." >&2
108 if [ -r /var/run/fai/FAI_INSTALLATION_IN_PROGRESS ] ; then
109 echo "/usr/sbin/fai already running or was aborted before.">&2
110 echo "You may remove /var/run/fai/FAI_INSTALLATION_IN_PROGRESS and try again.">&2
115 if [ -r /var/run/fai/fai_softupdate_is_running ] ; then
116 echo "/usr/sbin/fai softupdate already running or was aborted before.">&2
117 echo "You may remove /var/run/fai/fai_softupdate_is_running and try again.">&2
122 # lsb-functions and configuration stuff {{{
123 # make sure they are not set by default
134 # don't use colors/escape sequences
135 if [ -r /lib/lsb/init-functions ] ; then
136 . /lib/lsb/init-functions
137 ! log_use_fancy_output && NOCOLORS=true
140 if [ -r /etc/grml/lsb-functions ] ; then
141 . /etc/grml/lsb-functions
143 einfo() { echo " [*] $*" ;}
144 eerror() { echo " [!] $*">&2 ;}
145 ewarn() { echo " [x] $*" ;}
147 eindent() { return 0 ;}
148 eoutdent() { return 0 ;}
151 # source main configuration file:
152 [ -z "$LIVE_CONF" ] && LIVE_CONF='/etc/grml/grml-live.conf'
153 if ! [ -r "$LIVE_CONF" ] ; then
154 ewarn "Configuration file $LIVE_CONF can not be read, ignoring"
156 einfo "Sourcing configuration file $LIVE_CONF"
162 # umount all directories {{{
164 # make sure we don't leave any mounts - FAI doesn't remove them always
165 umount $CHROOT_OUTPUT/proc/sys/fs/binfmt_misc 2>/dev/null || /bin/true
166 umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
167 umount $CHROOT_OUTPUT/run 2>/dev/null || /bin/true
168 umount $CHROOT_OUTPUT/sys 2>/dev/null || /bin/true
169 umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
170 umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
172 if [ -n "$EXTRACT_ISO_NAME" ] ; then
173 umount "$EXTRACT_ISO_NAME" 2>/dev/null || /bin/true
176 # certain FAI versions sadly leave a ramdisk behind, so better safe than sorry
177 if [ -x /usr/lib/fai/mkramdisk ] ; then
178 /usr/lib/fai/mkramdisk -u "$(readlink -f ${CHROOT_OUTPUT}/var/lib/dpkg)" >/dev/null 2>&1 || /bin/true
181 umount "${CHROOT_OUTPUT}/grml-live/sources/" 2>/dev/null || /bin/true
182 [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
188 rm -f /var/run/fai/fai_softupdate_is_running \
189 /var/run/fai/FAI_INSTALLATION_IN_PROGRESS
190 [ -n "$CONFIGDUMP" ] && rm -f "$CONFIGDUMP"
191 [ -n "$SQUASHFS_STDERR" ] && rm -rf "$SQUASHFS_STDERR"
193 [ -n "$1" ] && EXIT="$1" || EXIT="1"
194 [ -n "$2" ] && eerror "$2">&2
195 if [ -n "$CLEAN_ARTIFACTS" ]; then
198 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
199 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
203 # get rid of automatically generated conffiles
204 rm -f ${GRML_FAI_CONFIG}/nfsroot.conf
205 rm -f ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf
207 if [ -n "$CHOWN_USER" ]; then
208 log "Setting ownership"
209 einfo "Setting ownership"
210 [ -n "${OUTPUT}" -a -d "${OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${OUTPUT}"
211 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${BUILD_OUTPUT}"
212 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${CHROOT_OUTPUT}"
213 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${ISO_OUTPUT}"
214 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${LOG_OUTPUT}"
215 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && chown -R "${CHOWN_USER}:" "${NETBOOT}"
218 log "------------------------------------------------------------------------------"
221 trap bailout 1 2 3 3 6 9 14 15
225 # some important functions {{{
228 # usage: log "string to log"
229 log() { [ -n "$LOGFILE" ] && echo "$*" >> $LOGFILE ; }
231 # cut string at character number int = $1
232 # usage: cut_string 5 "1234567890" will output "12345"
234 [ -n "$2" ] || return 1
235 echo "$2" | head -c "$1"; echo -ne "\n"
238 # prepend int = $1 spaces before string = $2
239 # usage: extend_string_begin 5 "123" will output " 123"
240 extend_string_begin() {
241 [ -n "$2" ] || return 1
242 local COUNT="$(echo $2 | wc -c)"
243 local FILL="$(expr $COUNT - $1)"
244 while [ "$FILL" -gt 1 ] ; do
246 local FILL=$(expr $FILL - 1)
248 while [ "$FILL" -lt 1 ] ; do
250 local FILL=$(expr $FILL + 1)
252 echo "$2" | head -c "$1"; echo -ne "\n"
255 # append int = $1 spaces to string = $2
256 # usage: extend_string_begin 5 "123" will output "123 "
257 extend_string_end() {
258 [ -n "$2" ] || return 1
259 echo -n "$2" | head -c "$1"
260 local COUNT="$(echo $2 | wc -c)"
261 local FILL="$(expr $COUNT - $1)"
262 while [ "$FILL" -gt 1 ] ; do
264 local FILL=$(expr $FILL - 1)
266 while [ "$FILL" -lt 1 ] ; do
268 local FILL=$(expr $FILL + 1)
273 # Copy addonfile $1 from either
274 # * the chroot (via $2, the system path),
275 # * or from TEMPLATE_DIRECTORY/compat (if exists),
276 # * or from the host system (again, using $2),
277 # or warn about the missing file.
280 # * We assume that the chroot always has a "good" version of
281 # the file. Also it makes sources handling easier.
282 # * On unstable, we recommend the Debian packages containing
283 # these files. The user can override them by putting his
284 # "better" version into the chroot.
285 # * With older releases the Debian packages are probably
286 # not available, so we look in TEMPLATE_DIRECTORY/compat,
287 # where a (custom) package might install current file versions.
289 DEST="${BUILD_OUTPUT}/boot/$3"
290 if [ ! -d "${DEST}/" ]; then
293 if [ -e "$CHROOT_OUTPUT/$2/$1" ]; then
294 log "Copying $1 from chroot"
295 cp "$CHROOT_OUTPUT/$2/$1" "${DEST}/"
298 if [ -e "${TEMPLATE_DIRECTORY}/compat/$3/$1" ]; then
299 log "Copying $1 from ${TEMPLATE_DIRECTORY}/compat"
300 cp "${TEMPLATE_DIRECTORY}/compat/$3/$1" "${DEST}/"
303 if [ -e "$2/$1" ]; then
304 log "Copying $1 from system"
305 cp "$2/$1" "${DEST}/"
309 msg="Missing addon file: \"$1\""
310 ewarn "$msg" ; eend 1
311 log "copy_addon_file: $msg"
315 # command line parsing {{{
316 while getopts "a:C:c:d:D:e:g:i:I:o:r:s:S:t:U:v:w:AbBFhnNqQuVz" opt; do
319 A) CLEAN_ARTIFACTS=1 ;;
322 c) CLASSES="$OPTARG" ;;
323 C) LOCAL_CONFIG="$(readlink -f $OPTARG)" ;;
325 D) GRML_FAI_CONFIG="$(readlink -f $OPTARG)" ;;
326 e) EXTRACT_ISO_NAME="$(readlink -f $OPTARG)" ;;
327 g) GRML_NAME="$OPTARG" ;;
328 h) usage ; bailout 0 ;;
329 i) ISO_NAME="$OPTARG" ;;
330 I) CHROOT_INSTALL="$OPTARG" ;;
332 N) BOOTSTRAP_ONLY=1; SKIP_MKISOFS=1; SKIP_MKSQUASHFS=1 ;;
333 o) OUTPUT="$(readlink -f $OPTARG)" ;;
334 q) SKIP_MKSQUASHFS=1 ;;
336 r) RELEASENAME="$OPTARG" ;;
337 s) SUITE="$OPTARG" ;;
338 S) SCRIPTS_DIRECTORY="$OPTARG";;
339 t) TEMPLATE_DIRECTORY="$OPTARG";;
340 v) VERSION="$OPTARG" ;;
343 U) CHOWN_USER="$OPTARG" ;;
345 w) export WAYBACK_DATE="$OPTARG" ;;
346 z) SQUASHFS_ZLIB=1 ;;
347 ?) echo "invalid option -$OPTARG" >&2; usage; bailout 1 ;;
350 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
352 if [ -n "$1" ] ; then
353 echo "Error: unknown argument '$1' in options. Exiting to avoid possible data loss." >&2
358 # read local (non-packaged) configuration {{{
359 if [ -z "$LOCAL_CONFIG" ]; then
360 if [ -r "/etc/grml/grml-live.local" ]; then
361 LOCAL_CONFIG="/etc/grml/grml-live.local"
364 if [ -n "$LOCAL_CONFIG" ]; then
365 if [ -r "$LOCAL_CONFIG" ]; then
368 eerror "Could not read specified local configuration file \"$LOCAL_CONFIG\"."
371 LOCAL_CONFIG=$(readlink -f "$LOCAL_CONFIG")
376 if [ -n "${GRML_LIVE_SOURCES:-}" ] ; then
377 eerror "Config variable \$GRML_LIVE_SOURCES is set. This variable has been deprecated."
378 ewarn "Please set up \${GRML_FAI_CONFIG}/config/files/etc/apt/sources.list.d/* instead."
383 # assume sane defaults (if not set already) {{{
384 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
385 [ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux'
386 [ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_FULL,$(echo ${ARCH} | tr 'a-z' 'A-Z')"
387 [ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)"
388 [ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators'
389 [ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml"
390 [ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png'
391 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
392 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai'
393 [ -n "$GRML_NAME" ] || GRML_NAME='grml'
394 [ -n "$HOSTNAME" ] || HOSTNAME='grml'
395 [ -n "$HYBRID_METHOD" ] || HYBRID_METHOD='isohybrid'
396 [ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks'
397 [ -n "$SQUASHFS_EXCLUDES_FILE" ] || SQUASHFS_EXCLUDES_FILE="${GRML_FAI_CONFIG}/config/grml/squashfs-excludes"
398 [ -n "$SUITE" ] || SUITE='testing'
399 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
400 [ -n "$SCRIPTS_DIRECTORY" ] || SCRIPTS_DIRECTORY='/usr/share/grml-live/scripts'
401 [ -n "$USERNAME" ] || USERNAME='grml'
402 [ -n "$VERSION" ] || VERSION='0.0.1'
404 # output specific stuff, depends on $OUTPUT (iff not set):
405 [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live'
406 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
407 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
408 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
409 [ -n "$LOG_OUTPUT" ] || LOG_OUTPUT="$OUTPUT/grml_logs"
410 [ -n "$REPORTS" ] || REPORTS="${LOG_OUTPUT}/reports/"
411 [ -n "$NETBOOT" ] || NETBOOT="${OUTPUT}/netboot/"
414 # some misc checks before executing FAI {{{
415 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
416 specify it on the command line using the -c option."
417 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
418 specify it on the command line using the -o option."
420 # trim characters that are known to cause problems inside $GRML_NAME;
421 # for example isolinux does not like '-' inside the directory name
422 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
424 # export variables to have them available in fai scripts:
425 [ -n "$GRML_NAME" ] && export GRML_NAME="$GRML_NAME"
426 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
429 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
430 # this was default behaviour until grml-live 0.9.34:
431 if [ -n "$ZERO_LOGFILE" ] ; then
432 PRESERVE_LOGFILE='' # make sure it's cleaned then
433 ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
434 ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
439 # ask user whether the setup is ok {{{
440 if [ -z "$FORCE" ] ; then
442 echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
444 echo " FAI classes: $CLASSES"
445 [ -n "$LOCAL_CONFIG" ] && echo " Configuration: $LOCAL_CONFIG"
446 [ -n "$GRML_FAI_CONFIG" ] && echo " Config directory: $GRML_FAI_CONFIG"
447 echo " main directory: $OUTPUT"
448 [ -n "$EXTRACT_ISO_NAME" ] && echo " Extract ISO: $EXTRACT_ISO_NAME"
449 [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT"
450 [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT"
451 [ -n "$ISO_OUTPUT" ] && echo " ISO target: $ISO_OUTPUT"
452 [ -n "$GRML_NAME" ] && echo " Grml name: $GRML_NAME"
453 [ -n "$RELEASENAME" ] && echo " Release name: $RELEASENAME"
454 [ -n "$DATE" ] && echo " Build date: $DATE"
455 [ -n "$VERSION" ] && echo " Grml version: $VERSION"
456 [ -n "$SUITE" ] && echo " Debian suite: $SUITE"
457 [ -n "$ARCH" ] && echo " Architecture: $ARCH"
458 [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD"
459 [ -n "$HYBRID_METHOD" ] && echo " Hybrid method: $HYBRID_METHOD"
460 [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY"
461 [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL"
462 [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID"
463 [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature."
464 [ -n "$CHOWN_USER" ] && echo " Output owner: $CHOWN_USER"
465 [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
466 [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS"
467 [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE"
468 [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA/XZ) compression."
469 [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
470 [ -n "$VERBOSE" ] && echo " Using VERBOSE mode."
471 [ -n "$CLEAN_ARTIFACTS" ] && echo " Will clean output before and after running."
472 [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation."
473 if [ -n "$BOOTSTRAP_ONLY" ] ; then
474 echo " Bootstrapping only and not building (files for) ISO."
476 [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file."
477 [ -n "$SKIP_NETBOOT" ] && echo " Skipping creation of NETBOOT package."
478 [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file."
479 [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE."
480 [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched."
483 echo -n "Is this ok for you? [y/N] "
485 if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
487 echo "Exiting as requested."
494 # clean up before start {{{
495 if [ -n "${CLEAN_ARTIFACTS}" ]; then
496 echo "Wiping old artifacts"
497 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
498 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
499 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && rm -r "${ISO_OUTPUT}"
500 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && rm -r "${LOG_OUTPUT}"
501 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && rm -r "${NETBOOT}"
505 # create log file {{{
506 [ -n "$LOGFILE" ] || LOGFILE=${LOG_OUTPUT}/grml-live.log
507 mkdir -p $(dirname "${LOGFILE}")
509 chown root:adm $LOGFILE
513 # clean/zero/remove logfiles {{{
515 if [ -n "$PRESERVE_LOGFILE" ] ; then
516 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
518 # make sure it is empty (as it is e.g. appended to grml-live-db)
522 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
523 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
524 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
525 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
526 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
527 rm -f /var/log/fai/"$HOSTNAME"/last \
528 /var/log/fai/"$HOSTNAME"/last-dirinstall \
529 /var/log/fai/"$HOSTNAME"/last-softupdate
534 # source config and startup {{{
535 if [ -n "$CONFIG" ] ; then
536 if ! [ -f "$CONFIG" ] ; then
537 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
538 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
541 log "Sourcing $CONFIG"
546 start_seconds=$(cut -d . -f 1 /proc/uptime)
547 log "------------------------------------------------------------------------------"
548 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
549 log "Using local config file: $LOCAL_CONFIG"
550 log "Executed grml-live command line:"
553 einfo "Logging actions to logfile $LOGFILE"
556 # dump config variables into file, for script access {{{
559 '^(GRML_NAME|RELEASENAME|DATE|VERSION|SUITE|ARCH|DISTRI_NAME|USERNAME|HOSTNAME|APT_PROXY)=' \
563 # unpack iso/squashfs {{{
565 if [ -n "$EXTRACT_ISO_NAME" ]; then
566 log "Unpacking ISO from ${EXTRACT_ISO_NAME}"
567 einfo "Unpacking ISO from ${EXTRACT_ISO_NAME}"
568 local mountpoint=$(mktemp -d)
570 mount -o loop "${EXTRACT_ISO_NAME}" "$mountpoint" ; rc=$?
571 if [ "$rc" != 0 ]; then
574 eerror "mount failed"
579 if ls "${mountpoint}"/live/*/*.squashfs 2>/dev/null | grep -q . ; then # ISOs >=2011.12
580 log "Using ${mountpoint}/live/*/*.squashfs for unsquashfs"
581 unsquashfs -d "${CHROOT_OUTPUT}" "${mountpoint}"/live/*/*.squashfs ; rc=$?
582 elif ls "${mountpoint}"/live/*.squashfs 2>/dev/null | grep -q . ; then # ISOs before 2011.12
583 log "Using ${mountpoint}/live/*.squashfs for unsquashfs"
584 unsquashfs -d "${CHROOT_OUTPUT}" "${mountpoint}"/live/*.squashfs ; rc=$?
586 log "Error: Could not find any *.squashfs files on the ISO"
587 eerror "Error: Could not find any *.squashfs files on the ISO"
594 if [ "$rc" != 0 ]; then
595 log "unsquashfs failed"
596 eerror "unsquashfs failed"
605 # on-the-fly configuration {{{
607 # does this suck? YES!
608 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
610 unstable) SUITE='sid' ; CLASSES="DEBIAN_UNSTABLE,$CLASSES" ;;
611 *) CLASSES="DEBIAN_$(echo $SUITE | tr 'a-z' 'A-Z'),$CLASSES";;
613 export SUITE # make sure it's available in FAI scripts
615 # validate whether the specified architecture class matches the
616 # architecture (option), otherwise installation of kernel will fail
617 if echo $CLASSES | grep -qw I386 ; then
618 if ! [[ "$ARCH" == "i386" ]] ; then
619 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
620 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
621 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
625 elif echo $CLASSES | grep -qi amd64 ; then
626 if ! [[ "$ARCH" == "amd64" ]] ; then
627 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
628 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
629 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
635 # generate nfsroot configuration for FAI on the fly
636 if [ -z "$FAI_DEBOOTSTRAP" ] ; then
637 if [ -n "$WAYBACK_DATE" ] ; then
638 FAI_DEBOOTSTRAP="$SUITE http://snapshot.debian.org/archive/debian/$WAYBACK_DATE/"
640 FAI_DEBOOTSTRAP="$SUITE http://ftp.debian.org/debian"
644 if [ -z "$FAI_DEBOOTSTRAP_OPTS" ] ; then
645 FAI_DEBOOTSTRAP_OPTS="--exclude=info,tasksel,tasksel-data --include=aptitude --arch $ARCH"
648 # create backup of old (not yet automatically generated) config file
649 if [ -f "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" ] ; then
650 if ! grep -q 'This is an automatically generated file by grml-live' "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" ; then
651 ewarn "Found old ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf - moving to ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf.outdated"
652 mv "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf.outdated"
657 echo "# This is an automatically generated file by grml-live.
658 # Do NOT edit this file, your changes will be lost.
659 FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"
660 FAI_DEBOOTSTRAP_OPTS=\"$FAI_DEBOOTSTRAP_OPTS\"
661 # EOF " > "${GRML_FAI_CONFIG}/nfsroot.conf"
662 # support FAI <=3.4.8, versions >=4.0 use nfsroot.conf
663 ( cd ${GRML_FAI_CONFIG} && ln -sf nfsroot.conf make-fai-nfsroot.conf )
666 # CHROOT_OUTPUT - execute FAI {{{
667 if [ -n "$BUILD_DIRTY" ]; then
668 log "Skipping stage 'fai' as requested via option -B"
669 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
671 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
673 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
674 FAI_ACTION=softupdate
676 FAI_ACTION=dirinstall
679 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
680 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
681 log "Error: does not look like you have a working chroot. Updating/building not possible."
682 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
688 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
689 log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
690 ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
692 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
694 if [ -n "${MIRROR_DIRECTORY}" ] ; then
695 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
696 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
699 mkdir -p "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
700 mount --bind "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
702 log "Executed FAI command line:"
703 log "BUILD_ONLY=$BUILD_ONLY BOOTSTRAP_ONLY=$BOOTSTRAP_ONLY GRML_LIVE_CONFIG=$CONFIGDUMP WAYBACK_DATE=$WAYBACK_DATE fai $VERBOSE -C $GRML_FAI_CONFIG -s file:///$GRML_FAI_CONFIG/config -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS"
704 BUILD_ONLY="$BUILD_ONLY" BOOTSTRAP_ONLY="$BOOTSTRAP_ONLY" GRML_LIVE_CONFIG="$CONFIGDUMP" fai $VERBOSE \
705 -C "$GRML_FAI_CONFIG" -s "file:///$GRML_FAI_CONFIG/config" -c"$CLASSES" \
706 -u "$HOSTNAME" "$FAI_ACTION" "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
707 RC="$PIPESTATUS" # notice: bash-only
709 if [ "$RC" != 0 ] ; then
710 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
711 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
715 # provide inform fai about the ISO we build, needs to be provided
716 # *after* FAI stage, otherwise FAI skips the debootstrap stage if
717 # there is not BASEFILE (as it checks for presence of /etc) :(
718 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
719 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
720 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
722 FORCE_ISO_REBUILD=true
724 # move fai logs into grml_logs directory
725 mkdir -p "$LOG_OUTPUT"/fai/
726 cp -r "$CHROOT_OUTPUT"/var/log/fai/"$HOSTNAME"/last/* "$LOG_OUTPUT"/fai/
727 rm -rf "$CHROOT_OUTPUT"/var/log/fai
729 # store copy of autogenerated configuration file
730 cp ${GRML_FAI_CONFIG}/nfsroot.conf "$LOG_OUTPUT"/fai/
732 # copy fai package list
733 cp "$CHROOT_OUTPUT"/var/log/install_packages.list "$LOG_OUTPUT"/fai/
735 chown root:adm "$LOG_OUTPUT"/fai/*
736 chmod 664 "$LOG_OUTPUT"/fai/*
740 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
742 CHECKLOG="$LOG_OUTPUT"/fai/
743 if [ -r "$CHECKLOG/software.log" ] ; then
744 # 1 errors during executing of commands
745 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
746 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
747 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
748 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
749 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
752 if [ -r "$CHECKLOG/shell.log" ] ; then
753 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
756 if [ -r "$CHECKLOG/fai.log" ] ; then
757 grep 'updatebase.*FAILED with exit code' "$CHECKLOG/fai.log" >> "$LOGFILE" && ERROR=7
758 grep 'instsoft.*FAILED with exit code' "$CHECKLOG/fai.log" >> "$LOGFILE" && ERROR=8
761 if [ -n "$ERROR" ] ; then
762 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
763 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
764 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
768 log "Finished execution of stage 'fai dirinstall' [$(date)]"
769 einfo "Finished execution of stage 'fai dirinstall'"
775 # package validator {{{
776 CHECKLOG=/var/log/fai/$HOSTNAME/last
777 if [ -r "$CHECKLOG/dpkg.selections" ] ; then
778 package_count=$(wc -l "$CHECKLOG/dpkg.selections" | awk '{print $1}')
780 package_count="unknown"
784 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
786 # check for missing packages
787 if ! [ -s "$CHECKLOG/package_errors.log" ] ; then
788 einfo "No missing packages found, generating empty junit report."
790 cat > "${REPORT_MISSING_PACKAGES}" << EOF
791 <?xml version="1.0" encoding="UTF-8"?>
792 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="0" errors="0" skipped="0" assertions="0">
793 <testcase name="test_missing_packages" time="0" assertions="0">
803 einfo "Missing packages found, generating junit report."
805 if [ -r "$CHECKLOG/package_errors.log" ] ; then
806 package_errors=$(wc -l "$CHECKLOG/package_errors.log" | awk '{print $1}')
808 package_errors="unknown"
812 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
814 cat > "${REPORT_MISSING_PACKAGES}" << EOF
815 <?xml version="1.0" encoding="UTF-8"?>
816 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="${package_errors}" errors="${package_errors}" skipped="0" assertions="0">
819 for package in $(awk '{print $1}' "${CHECKLOG}/package_errors.log" | sed 's;/;\\/;') ; do
820 failure_reason="$(awk "/$package/ {print \$2}" "${CHECKLOG}/package_errors.log")"
821 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
822 <testcase name="test_missing_packages_${package}" time="0" assertions="0">
823 <failure type="${failure_reason}" message="Package ${package} is missing">
824 Package $package is missing in chroot (${failure_reason})
830 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
839 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
840 eerror "The following packages were requested for installation but could not be processed:"
841 cat "$CHECKLOG/package_errors.log"
842 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
846 ewarn "The following packages were requested for installation but could not be processed:"
847 cat "$CHECKLOG/package_errors.log"
853 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
854 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
855 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
858 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
859 if [ -n "$BOOTSTRAP_ONLY" ] ; then
860 log "Skipping stage 'boot' as building with bootstrap only."
861 ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0
863 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
864 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
865 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
868 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
869 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
871 # if we don't have an initrd we a) can't boot and b) there was an error
872 # during build, so check for the file:
873 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
874 if [ -n "$INITRD" ] ; then
875 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.img
876 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
878 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
879 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
883 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
884 if [ -n "$KERNEL_IMAGE" ] ; then
885 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/vmlinuz
887 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
888 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
893 if [ -r "${CHROOT_OUTPUT}/boot/efi.img" -a -r "${CHROOT_OUTPUT}/boot/bootx64.efi" ] ; then
894 einfo "Moving EFI boot files into ISO path."
895 log "Moving EFI boot files into ISO path."
897 mv "${CHROOT_OUTPUT}/boot/efi.img" "${BUILD_OUTPUT}/boot/" || RC=$?
898 mkdir -p "${BUILD_OUTPUT}/efi/boot/" || RC=$?
899 mv "${CHROOT_OUTPUT}/boot/bootx64.efi" "${BUILD_OUTPUT}/efi/boot/bootx64.efi" || RC=$?
903 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
904 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
905 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
906 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
910 # copy _required_ isolinux files
911 if [ -d "${CHROOT_OUTPUT}/usr/lib/ISOLINUX" ] ; then
912 copy_addon_file isolinux.bin /usr/lib/ISOLINUX isolinux
913 for file in ${CHROOT_OUTPUT}/usr/lib/syslinux/modules/bios/*.c32 ; do
914 copy_addon_file "$(basename "$file")" /usr/lib/syslinux/modules/bios/ isolinux
916 else # syslinux versions <= 3:4.05+dfsg-6+deb8u1
917 copy_addon_file isolinux.bin /usr/lib/syslinux isolinux
918 copy_addon_file ifcpu64.c32 /usr/lib/syslinux isolinux
919 copy_addon_file vesamenu.c32 /usr/lib/syslinux isolinux
922 # *always* copy files to output directory so the variables
923 # get adjusted according to the build.
924 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
926 mkdir -p "${BUILD_OUTPUT}/boot/grub"
927 cp -a ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
929 if [ -n "$NO_ADDONS" ] ; then
930 rm -f "$BUILD_OUTPUT"/boot/grub/addons.cfg
931 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
932 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
934 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
935 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
936 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
938 # copy addons from system packages or grml-live-addons
939 copy_addon_file ipxe.lkrn /usr/lib/ipxe addons
940 copy_addon_file pci.ids /usr/share/misc addons
941 copy_addon_file memtest86+.bin /boot addons
943 # since syslinux(-common) v3:6.03~pre1+dfsg-4 the files are in a
944 # different directory :(
945 if [ -d "${CHROOT_OUTPUT}/usr/lib/syslinux/modules/bios/" ] ; then
946 syslinux_modules_dir=/usr/lib/syslinux/modules/bios/
948 syslinux_modules_dir=/usr/lib/syslinux
950 for file in chain.c32 hdt.c32 mboot.c32 menu.c32; do
951 copy_addon_file "${file}" "${syslinux_modules_dir}" addons
954 copy_addon_file memdisk /usr/lib/syslinux addons
956 # make memtest filename FAT16/8.3 compatible
957 mv "${BUILD_OUTPUT}/boot/addons/memtest86+.bin" \
958 "${BUILD_OUTPUT}/boot/addons/memtest"
960 # copy only files so we can handle bsd4grml on its own
961 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
962 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
965 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
966 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
967 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
969 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
970 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
972 log "Missing addon file: bsd4grml"
973 ewarn "Missing addon file: bsd4grml" ; eend 0
977 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
980 # generate loopback.cfg config file without depending on grub's regexp module
981 # which isn't available in Debian/squeeze
982 echo "## grub2 loopback configuration" > "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
983 echo "source /boot/grub/header.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
984 for config in "${BUILD_OUTPUT}"/boot/grub/*_default.cfg "${BUILD_OUTPUT}"/boot/grub/*_options.cfg ; do
985 [ -r "$config" ] || continue
986 echo "source ${config##$BUILD_OUTPUT}" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
988 if [ -z "$NO_ADDONS" ] ; then
989 echo "source /boot/grub/addons.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
991 echo "source /boot/grub/footer.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
993 # copy grub files from target
994 mkdir -p "${BUILD_OUTPUT}"/boot/grub/i386-pc/
995 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.mod "${BUILD_OUTPUT}"/boot/grub/i386-pc/
996 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.o "${BUILD_OUTPUT}"/boot/grub/i386-pc/
997 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.lst "${BUILD_OUTPUT}"/boot/grub/i386-pc/
998 cp -a "${CHROOT_OUTPUT}"/usr/share/grub/ascii.pf2 "${BUILD_OUTPUT}"/boot/grub/
999 cp -a "${CHROOT_OUTPUT}"/boot/grub/core.img "${BUILD_OUTPUT}"/boot/grub/
1000 cp -a "${CHROOT_OUTPUT}"/boot/grub/grub.img "${BUILD_OUTPUT}"/boot/grub/
1002 # copy modules for UEFI grub
1003 mkdir -p "${BUILD_OUTPUT}"/boot/grub/x86_64-efi/
1004 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/x86_64-efi/*.{mod,lst} "${BUILD_OUTPUT}"/boot/grub/x86_64-efi/
1006 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
1007 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
1008 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
1012 mkdir -p "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
1013 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
1015 # adjust boot splash information:
1016 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
1017 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
1018 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
1020 if [ -r "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version ] ; then
1021 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
1022 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
1025 # make sure the squashfs filename is set accordingly:
1026 SQUASHFS_NAME="$GRML_NAME.squashfs"
1028 if [ -n "$NO_BOOTID" ] ; then
1029 log 'Skipping bootid feature as requested via $NO_BOOTID.'
1030 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
1032 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
1033 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
1034 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
1035 log "Generating /conf/bootid.txt with entry ${BOOTID}."
1036 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
1040 # adjust all variables in the templates with the according distribution information
1041 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
1042 "${BUILD_OUTPUT}"/boot/grub/* ; do
1043 if [ -r "${file}" ] && [ -f "${file}" ] ; then
1044 sed -i "s/%ARCH%/$ARCH/g" "${file}"
1045 sed -i "s/%DATE%/$DATE/g" "${file}"
1046 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
1047 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
1048 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
1049 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
1050 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
1051 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
1052 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
1053 sed -i "s/%VERSION%/$VERSION/g" "${file}"
1055 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s; boot=live; boot=live $DEFAULT_BOOTOPTIONS;" "${file}"
1057 if [ -n "$NO_BOOTID" ] ; then
1058 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
1060 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
1065 for param in ARCH DATE DISTRI_INFO DISTRI_NAME DISTRI_SPLASH GRML_NAME SQUASHFS_NAME \
1066 RELEASE_INFO SHORT_NAME VERSION ; do
1067 for file in $(find "${BUILD_OUTPUT}" -name "*%$param%*") ; do
1068 value="$(eval echo '$'"$param")"
1069 mv ${file} ${file/\%${param}\%/$value}
1073 # adjust bootsplash accordingly but make sure the string has the according lenght
1074 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
1075 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
1076 for file in f4 f5 ; do
1077 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
1078 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
1079 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
1083 # generate addon list
1084 rm -f "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
1085 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
1086 include_name=$(basename "$name")
1087 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
1090 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
1091 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1092 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1093 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1094 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1095 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1097 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
1098 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1101 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1102 if [ -z "$NO_ADDONS" ] ; then
1103 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1105 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1106 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1107 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1108 else # assume we are building a custom distribution:
1109 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
1110 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
1111 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1112 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1114 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1118 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1119 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1120 if [ -z "$NO_ADDONS" ] ; then
1121 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1126 # use old style console based isolinux method only if requested:
1127 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
1128 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1129 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1130 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1131 einfo "include for console.cfg already found, nothing to do."
1134 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1135 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1136 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1140 log 'Using graphical boot menu.'
1141 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
1142 log "include for vesamenu.cfg already found, nothing to do."
1144 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1145 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1149 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
1150 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
1153 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
1154 if ! [ -r "$DPKG_LIST" ] ; then
1155 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
1157 einfo "Storing package list information as /GRML/${GRML_NAME}/packages.txt on ISO."
1158 cp "$DPKG_LIST" "${BUILD_OUTPUT}"/GRML/"${GRML_NAME}"/packages.txt
1162 # autostart for Windows:
1163 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
1164 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
1167 FORCE_ISO_REBUILD=true
1168 einfo "Finished execution of stage 'boot'" ; eend 0
1172 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
1173 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
1177 # support installation of local files into the chroot/ISO
1178 if [ -n "$CHROOT_INSTALL" ] ; then
1179 if ! [ -d "$CHROOT_INSTALL" ] ; then
1180 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1181 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1183 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1184 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1185 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
1187 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
1188 FORCE_ISO_REBUILD=true
1192 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1193 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
1194 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
1195 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
1196 log "Skipping stage 'squashfs' as requested via option -q or -N"
1197 ewarn "Skipping stage 'squashfs' as requested via option -q or -N" ; eend 0
1199 mkdir -p "$BUILD_OUTPUT"/live/"${GRML_NAME}"/
1200 # make sure we don't leave (even an empty) base.tgz:
1201 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
1203 # if unconfigured default to squashfs-tools' mksquashfs binary
1204 if [ -z "$SQUASHFS_BINARY" ] ; then
1205 SQUASHFS_BINARY='mksquashfs'
1208 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
1209 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
1210 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
1212 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
1213 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
1217 # use sane defaults if $SQUASHFS_OPTIONS isn't set
1218 if [ -z "$SQUASHFS_OPTIONS" ] ; then
1219 # use blocksize 256k as this gives best result with regards to time + compression
1220 SQUASHFS_OPTIONS="-b 256k"
1222 # set lzma/xz compression by default, unless -z option has been specified on command line
1223 if [ -z "$SQUASHFS_ZLIB" ] ; then
1224 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
1226 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
1230 # support exclusion of files via exclude-file:
1231 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
1232 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE -wildcards"
1235 # get rid of unnecessary files when building grml-small for final release:
1236 if echo "$CLASSES" | grep -q GRML_SMALL ; then
1237 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
1241 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
1243 # informational stuff
1244 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1245 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1246 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1248 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/${GRML_NAME}/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1250 if $SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/"${GRML_NAME}"/"${GRML_NAME}".squashfs \
1251 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1252 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/"${GRML_NAME}"/filesystem.module
1253 log "Finished execution of stage 'squashfs' [$(date)]"
1254 einfo "Finished execution of stage 'squashfs'" ; eend 0
1256 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1257 log "$(cat $SQUASHFS_STDERR)"
1258 eerror "Error: there was a critical error executing stage 'squashfs':"
1259 cat "${SQUASHFS_STDERR}"
1264 FORCE_ISO_REBUILD=true
1267 # create md5sum file:
1268 if [ -z "$BOOTSTRAP_ONLY" ] ; then
1269 ( cd $BUILD_OUTPUT/GRML/"${GRML_NAME}" &&
1270 find ../.. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1274 # ISO_OUTPUT - mkisofs {{{
1275 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1276 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1278 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1279 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1280 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1281 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1284 # Work around http://bts.grml.org/grml/issue945
1285 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1286 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1287 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1288 HYBRID_METHOD='grub2'
1292 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1293 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1294 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1295 elif [ -n "$SKIP_MKISOFS" ] ; then
1296 log "Skipping stage 'iso build' as requested via option -n or -N"
1297 ewarn "Skipping stage 'iso build' as requested via option -n or -N" ; eend 0
1299 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1301 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1302 log "Forcing rebuild of ISO because files on ISO have been modified."
1303 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1306 # support xorriso as well mkisofs and genisoimage
1307 if which xorriso >/dev/null 2>&1 ; then
1308 MKISOFS='xorriso -as mkisofs'
1309 elif which mkisofs >/dev/null 2>&1; then
1311 elif which genisoimage >/dev/null 2>&1; then
1312 MKISOFS='genisoimage'
1314 log "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO."
1315 eerror "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO." ; eend 1
1319 einfo "Using ${MKISOFS} to build ISO." ; eend 0
1320 case "${ARCH}-${MKISOFS}" in
1321 # using -eltorito-alt-boot is limited to xorriso for now
1325 if ! dpkg --compare-versions $(dpkg-query -W -f='${Version}\n' xorriso 2>/dev/null) gt-nl 1.1.6-1 ; then
1326 log "Disabling (U)EFI boot support because xorriso version is too old."
1327 ewarn "Disabling (U)EFI boot support because xorriso version is too old." ; eend 0
1329 if [ -r "${BUILD_OUTPUT}"/boot/efi.img ] ; then
1330 einfo "Enabling (U)EFI boot."
1331 log "Enabling (U)EFI boot."
1332 BOOT_ARGS="$BOOT_ARGS -boot-info-table -eltorito-alt-boot -e boot/efi.img -no-emul-boot"
1335 log "Disabling (U)EFI boot support because /boot/efi.img is missing."
1336 ewarn "Disabling (U)EFI boot support because /boot/efi.img is missing." ; eend 0
1345 if cd "$BUILD_OUTPUT" ; then
1346 if [ "$BOOT_METHOD" = "grub2" ]; then
1347 # make a 2048-byte bootsector for El Torito
1348 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1349 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1350 echo 1 16 | mksh "${SCRIPTS_DIRECTORY}/bootgrub.mksh" -B 11 | \
1351 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1353 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1354 $MKISOFS -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1355 -l -r -J $BOOT_ARGS -no-pad \
1356 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1357 # both of these need core.img there, so it’s easier to write it here
1358 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1359 # must be <= 30720 bytes
1360 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1361 conv=notrunc bs=512 seek=4 2>/dev/null
1364 # pad the output ISO to multiples of 256 KiB for partition table support
1365 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1366 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1367 siz=$((cyls * 16 * 32 * 512)) # size after padding
1368 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1369 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1371 # support disabling hybrid ISO image
1372 if [ "$HYBRID_METHOD" = "disable" ] ; then
1373 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1374 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1376 elif [ "$HYBRID_METHOD" = "manifold" ] || [ "$HYBRID_METHOD" = "grub2" ] ; then
1377 # isoinfo is part of both mkisofs and genisoimage so we're good
1378 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1379 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN[;1]* *$/s//\1/p')
1381 if ! [ -r boot/grub/core.img ] ; then
1382 log "boot/grub/core.img not found, not creating manifold boot ISO file"
1383 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1384 elif [ "${bootoff:-0}" -lt 1 ] ; then
1385 log "isolinux.bin not found on the ISO file, disabling manifold boot"
1386 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1388 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1389 log "Creating hybrid ISO file with manifold/grub2 method"
1390 einfo "Creating hybrid ISO file with manifold/grub2 method"
1391 # 512 bytes: MBR, partition table, load GRUB 2
1392 echo 4 63 | mksh "${SCRIPTS_DIRECTORY}/bootgrub.mksh" -A -M 4:0x96 -g $cyls:16:32
1394 log "Creating hybrid ISO file with manifold method"
1395 einfo "Creating hybrid ISO file with manifold method"
1396 # read only one but 2048-byte sized (scale: << 2) sector
1397 echo $bootoff $bootoff | \
1398 mksh ${SCRIPTS_DIRECTORY}/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1399 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1402 elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
1403 if ! which isohybrid >/dev/null 2>&1 ; then
1404 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common/syslinux-utils"
1406 log "Creating hybrid ISO file with isohybrid method"
1407 einfo "Creating hybrid ISO file with isohybrid method"
1408 # Notes for consideration:
1409 # "-entry 4 -type 1c"
1410 # * using 4 as the partition number is supposed to help with BIOSes
1411 # that only support USB-Zip boot
1412 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1413 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1414 # to get the BIOS even look at the partition created by isohybrid
1415 if isohybrid --help | grep -q -- --uefi ; then
1416 if echo $CLASSES | grep -qw I386 ; then
1417 log "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring."
1418 einfo "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring."
1420 log "Detected uefi support for isohybrid, enabling"
1421 einfo "Detected uefi support for isohybrid, enabling"
1422 ISOHYBRID_OPTIONS=--uefi
1426 log "isohybrid $ISOHYBRID_OPTIONS ${ISO_OUTPUT}/${ISO_NAME}"
1427 isohybrid $ISOHYBRID_OPTIONS "${ISO_OUTPUT}/${ISO_NAME}"
1431 bailout 12 "Unknown HYBRID_METHOD [${HYBRID_METHOD}]. Supported values: disable, isohybrid, grub2, manifold"
1434 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1435 case $CLASSES in *RELEASE*)
1438 if cd $ISO_OUTPUT ; then
1439 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1440 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1441 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1442 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1443 sha256sum ${ISO_NAME} > ${ISO_NAME}.sha256 && \
1444 touch -r ${ISO_NAME} ${ISO_NAME}.sha256
1445 sha512sum ${ISO_NAME} > ${ISO_NAME}.sha512 && \
1446 touch -r ${ISO_NAME} ${ISO_NAME}.sha512
1455 if [ "$RC" = 0 ] ; then
1456 log "Finished execution of stage 'iso build' [$(date)]"
1457 einfo "Finished execution of stage 'iso build'" ; eend 0
1459 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1460 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1466 # netboot package {{{
1467 create_netbootpackage() {
1468 local OUTPUT_FILE="${NETBOOT}/grml_netboot_package_${GRML_NAME}_${VERSION}.tar.bz2"
1470 if [ -f "${OUTPUT_FILE}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1471 log "Skipping stage 'netboot' as $OUTPUT_FILE exists already."
1472 ewarn "Skipping stage 'netboot' as $OUTPUT_FILE exists already." ; eend 0
1474 elif [ -n "$SKIP_NETBOOT" ] ; then
1475 log "Skipping stage 'netboot' as requested via option -Q"
1476 ewarn "Skipping stage 'netboot' as requested via option -Q" ; eend 0
1482 # since syslinux v3:6.03~pre1+dfsg-4 the pxelinux.0 has been split into a
1483 # separate pxelinux package
1484 if [ -d "${CHROOT_OUTPUT}/usr/lib/PXELINUX/" ] ; then
1485 local pxelinux_dir=/usr/lib/PXELINUX
1487 local pxelinux_dir=/usr/lib/syslinux
1490 if ! [ -r "${CHROOT_OUTPUT}/${pxelinux_dir}/pxelinux.0" ] ; then
1491 ewarn "File ${pxelinux_dir}/pxelinux.0 not found in build chroot." ; eend 0
1493 einfo "Install syslinux[-common]/pxelinux package in chroot to get a netboot package."
1498 local OUTPUTDIR="${NETBOOT}/build_tmp"
1499 local WORKING_DIR="${OUTPUTDIR}/grml_netboot_package_${GRML_NAME}_${VERSION}/tftpboot/"
1501 mkdir -p "$WORKING_DIR"
1503 cp "${CHROOT_OUTPUT}"/boot/vmlinuz-* "$WORKING_DIR"/vmlinuz
1504 cp "${CHROOT_OUTPUT}"/boot/initrd.img-* "$WORKING_DIR"/initrd.img
1505 cp "${CHROOT_OUTPUT}/${pxelinux_dir}/pxelinux.0" "${WORKING_DIR}/pxelinux.0"
1507 if [ -r "${CHROOT_OUTPUT}"/usr/lib/syslinux/modules/bios/ldlinux.c32 ] ; then
1508 cp "${CHROOT_OUTPUT}"/usr/lib/syslinux/modules/bios/ldlinux.c32 "${WORKING_DIR}"/
1511 mkdir -p "${WORKING_DIR}/pxelinux.cfg"
1512 if [ -r "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" ] ; then
1513 cp "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" "${WORKING_DIR}/pxelinux.cfg/default"
1515 log "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found."
1516 ewarn "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found."
1518 log "Hint: Are you using custom templates which do not provide netboot.cfg?"
1519 ewarn "Hint: Are you using custom templates which do not provide netboot.cfg?" ; eend 0
1523 if tar -C "$OUTPUTDIR" -jcf "${OUTPUT_FILE}" "grml_netboot_package_${GRML_NAME}_${VERSION}" ; then
1525 cd $(dirname "${OUTPUT_FILE}")
1526 sha1sum $(basename "${OUTPUT_FILE}") > "${OUTPUT_FILE}.sha1"
1527 sha256sum $(basename "${OUTPUT_FILE}") > "${OUTPUT_FILE}.sha256"
1528 sha512sum $(basename "${OUTPUT_FILE}") > "${OUTPUT_FILE}.sha512"
1530 einfo "Generated netboot package ${OUTPUT_FILE}" ; eend 0
1531 rm -rf "${OUTPUTDIR}"
1533 rm -rf "${OUTPUTDIR}"
1534 eerror "Could not generate netboot package ${OUTPUT_FILE}" ; eend 1
1539 create_netbootpackage
1542 # log build information to database if grml-live-db is installed and enabled {{{
1544 if [ -d /usr/share/grml-live-db ] ; then
1547 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1548 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1549 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1550 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1552 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1553 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1554 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1558 # disable by default for now, not sure whether really everyone is using a local db file
1559 #if ! touch "$DPKG_DATABASE" ; then
1560 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1564 if ! [ -r "$DPKG_LIST" ] ; then
1565 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1566 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1568 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1569 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1570 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1573 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1589 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1590 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1592 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1594 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1598 ## END OF FILE #################################################################
1599 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=2