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 -z use ZLIB instead of LZMA/XZ compression
79 $PN -c GRMLBASE,GRML_FULL,AMD64 -o /dev/shm/grml
80 $PN -c GRMLBASE,GRML_FULL,AMD64 -i grml_0.0-1.iso -v 0.0-1
81 $PN -c GRMLBASE,GRML_FULL,AMD64 -s stable -V -r 'grml-ftw'
83 More details: man grml-live + /usr/share/doc/grml-live/grml-live.html
84 http://grml.org/grml-live/
86 Please send your bug reports and feedback to the grml-team: http://grml.org/bugs/
88 [ "$(id -u 2>/dev/null)" != 0 ] && echo "Please notice that this script requires root permissions."
91 # make sure it's possible to get usage information without being
92 # root or actually executing the script
93 if [ "$1" = '-h' -o "$1" = '--help' ] ; then
99 # some runtime checks {{{
100 # we need root permissions for the build-process:
101 if [ "$(id -u 2>/dev/null)" != 0 ] ; then
102 echo "Error: please run this script with uid 0 (root)." >&2
106 if [ -r /var/run/fai/FAI_INSTALLATION_IN_PROGRESS ] ; then
107 echo "/usr/sbin/fai already running or was aborted before.">&2
108 echo "You may remove /var/run/fai/FAI_INSTALLATION_IN_PROGRESS and try again.">&2
113 if [ -r /var/run/fai/fai_softupdate_is_running ] ; then
114 echo "/usr/sbin/fai softupdate already running or was aborted before.">&2
115 echo "You may remove /var/run/fai/fai_softupdate_is_running and try again.">&2
120 # lsb-functions and configuration stuff {{{
121 # make sure they are not set by default
132 # don't use colors/escape sequences
133 if [ -r /lib/lsb/init-functions ] ; then
134 . /lib/lsb/init-functions
135 ! log_use_fancy_output && NOCOLORS=true
138 if [ -r /etc/grml/lsb-functions ] ; then
139 . /etc/grml/lsb-functions
141 einfo() { echo " [*] $*" ;}
142 eerror() { echo " [!] $*">&2 ;}
143 ewarn() { echo " [x] $*" ;}
145 eindent() { return 0 ;}
146 eoutdent() { return 0 ;}
149 # source main configuration file:
150 [ -z "$LIVE_CONF" ] && LIVE_CONF='/etc/grml/grml-live.conf'
151 if ! [ -r "$LIVE_CONF" ] ; then
152 ewarn "Configuration file $LIVE_CONF can not be read, ignoring"
154 einfo "Sourcing configuration file $LIVE_CONF"
160 # umount all directories {{{
162 # make sure we don't leave any mounts - FAI doesn't remove them always
163 umount $CHROOT_OUTPUT/proc/sys/fs/binfmt_misc 2>/dev/null || /bin/true
164 umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
165 umount $CHROOT_OUTPUT/run 2>/dev/null || /bin/true
166 umount $CHROOT_OUTPUT/sys 2>/dev/null || /bin/true
167 umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
168 umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
170 if [ -n "$EXTRACT_ISO_NAME" ] ; then
171 umount "$EXTRACT_ISO_NAME" 2>/dev/null || /bin/true
174 # certain FAI versions sadly leave a ramdisk behind, so better safe than sorry
175 if [ -x /usr/lib/fai/mkramdisk ] ; then
176 /usr/lib/fai/mkramdisk -u "$(readlink -f ${CHROOT_OUTPUT}/var/lib/dpkg)" >/dev/null 2>&1 || /bin/true
179 umount "${CHROOT_OUTPUT}/grml-live/sources/" 2>/dev/null || /bin/true
180 [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
186 rm -f /var/run/fai/fai_softupdate_is_running \
187 /var/run/fai/FAI_INSTALLATION_IN_PROGRESS
188 [ -n "$CONFIGDUMP" ] && rm -f "$CONFIGDUMP"
189 [ -n "$SQUASHFS_STDERR" ] && rm -rf "$SQUASHFS_STDERR"
191 [ -n "$1" ] && EXIT="$1" || EXIT="1"
192 [ -n "$2" ] && eerror "$2">&2
193 if [ -n "$CLEAN_ARTIFACTS" ]; then
196 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
197 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
201 # get rid of automatically generated conffiles
202 rm -f ${GRML_FAI_CONFIG}/nfsroot.conf
203 rm -f ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf
205 if [ -n "$CHOWN_USER" ]; then
206 log "Setting ownership"
207 einfo "Setting ownership"
208 [ -n "${OUTPUT}" -a -d "${OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${OUTPUT}"
209 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${BUILD_OUTPUT}"
210 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${CHROOT_OUTPUT}"
211 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${ISO_OUTPUT}"
212 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${LOG_OUTPUT}"
213 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && chown -R "${CHOWN_USER}:" "${NETBOOT}"
216 log "------------------------------------------------------------------------------"
219 trap bailout 1 2 3 3 6 9 14 15
223 # some important functions {{{
226 # usage: log "string to log"
227 log() { [ -n "$LOGFILE" ] && echo "$*" >> $LOGFILE ; }
229 # cut string at character number int = $1
230 # usage: cut_string 5 "1234567890" will output "12345"
232 [ -n "$2" ] || return 1
233 echo "$2" | head -c "$1"; echo -ne "\n"
236 # prepend int = $1 spaces before string = $2
237 # usage: extend_string_begin 5 "123" will output " 123"
238 extend_string_begin() {
239 [ -n "$2" ] || return 1
240 local COUNT="$(echo $2 | wc -c)"
241 local FILL="$(expr $COUNT - $1)"
242 while [ "$FILL" -gt 1 ] ; do
244 local FILL=$(expr $FILL - 1)
246 while [ "$FILL" -lt 1 ] ; do
248 local FILL=$(expr $FILL + 1)
250 echo "$2" | head -c "$1"; echo -ne "\n"
253 # append int = $1 spaces to string = $2
254 # usage: extend_string_begin 5 "123" will output "123 "
255 extend_string_end() {
256 [ -n "$2" ] || return 1
257 echo -n "$2" | head -c "$1"
258 local COUNT="$(echo $2 | wc -c)"
259 local FILL="$(expr $COUNT - $1)"
260 while [ "$FILL" -gt 1 ] ; do
262 local FILL=$(expr $FILL - 1)
264 while [ "$FILL" -lt 1 ] ; do
266 local FILL=$(expr $FILL + 1)
271 # Copy addonfile $1 from either
272 # * the chroot (via $2, the system path),
273 # * or from TEMPLATE_DIRECTORY/compat (if exists),
274 # * or from the host system (again, using $2),
275 # or warn about the missing file.
278 # * We assume that the chroot always has a "good" version of
279 # the file. Also it makes sources handling easier.
280 # * On unstable, we Recommend the Debian packages containing
281 # these files. The user can override them by putting his
282 # "better" version into the chroot.
283 # * On stable, the Debian packages are probably not available,
284 # or outdated, so we look in TEMPLATE_DIRECTORY/compat first, where
285 # our grml-live-compat package installs current file versions.
287 DEST="${BUILD_OUTPUT}/boot/$3"
288 if [ ! -d "${DEST}/" ]; then
291 if [ -e "$CHROOT_OUTPUT/$2/$1" ]; then
292 log "Copying $1 from chroot"
293 cp "$CHROOT_OUTPUT/$2/$1" "${DEST}/"
296 if [ -e "${TEMPLATE_DIRECTORY}/compat/$3/$1" ]; then
297 log "Copying $1 from grml-live-compat"
298 cp "${TEMPLATE_DIRECTORY}/compat/$3/$1" "${DEST}/"
301 if [ -e "$2/$1" ]; then
302 log "Copying $1 from system"
303 cp "$2/$1" "${DEST}/"
307 msg="Missing addon file: \"$1\""
308 ewarn "$msg" ; eend 1
309 log "copy_addon_file: $msg"
313 # command line parsing {{{
314 while getopts "a:C:c:d:D:e:g:i:I:o:r:s:S:t:U:v:AbBFhnNqQuVz" opt; do
317 A) CLEAN_ARTIFACTS=1 ;;
320 c) CLASSES="$OPTARG" ;;
321 C) LOCAL_CONFIG="$(readlink -f $OPTARG)" ;;
323 D) GRML_FAI_CONFIG="$(readlink -f $OPTARG)" ;;
324 e) EXTRACT_ISO_NAME="$(readlink -f $OPTARG)" ;;
325 g) GRML_NAME="$OPTARG" ;;
326 h) usage ; bailout 0 ;;
327 i) ISO_NAME="$OPTARG" ;;
328 I) CHROOT_INSTALL="$OPTARG" ;;
330 N) BOOTSTRAP_ONLY=1; SKIP_MKISOFS=1; SKIP_MKSQUASHFS=1 ;;
331 o) OUTPUT="$(readlink -f $OPTARG)" ;;
332 q) SKIP_MKSQUASHFS=1 ;;
334 r) RELEASENAME="$OPTARG" ;;
335 s) SUITE="$OPTARG" ;;
336 S) SCRIPTS_DIRECTORY="$OPTARG";;
337 t) TEMPLATE_DIRECTORY="$OPTARG";;
338 v) VERSION="$OPTARG" ;;
341 U) CHOWN_USER="$OPTARG" ;;
343 z) SQUASHFS_ZLIB=1 ;;
344 ?) echo "invalid option -$OPTARG" >&2; usage; bailout 1 ;;
347 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
349 if [ -n "$1" ] ; then
350 echo "Error: unknown argument '$1' in options. Exiting to avoid possible data loss." >&2
355 # read local (non-packaged) configuration {{{
356 if [ -z "$LOCAL_CONFIG" ]; then
357 if [ -r "/etc/grml/grml-live.local" ]; then
358 LOCAL_CONFIG="/etc/grml/grml-live.local"
361 if [ -n "$LOCAL_CONFIG" ]; then
362 if [ -r "$LOCAL_CONFIG" ]; then
365 eerror "Could not read specified local configuration file \"$LOCAL_CONFIG\"."
368 LOCAL_CONFIG=$(readlink -f "$LOCAL_CONFIG")
373 if [ -n "${GRML_LIVE_SOURCES:-}" ] ; then
374 eerror "Config variable \$GRML_LIVE_SOURCES is set. This variable has been deprecated."
375 ewarn "Please set up \${GRML_FAI_CONFIG}/config/files/etc/apt/sources.list.d/* instead."
380 # assume sane defaults (if not set already) {{{
381 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
382 [ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux'
383 [ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_FULL,$(echo ${ARCH} | tr 'a-z' 'A-Z')"
384 [ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)"
385 [ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators'
386 [ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml"
387 [ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png'
388 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
389 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai'
390 [ -n "$GRML_NAME" ] || GRML_NAME='grml'
391 [ -n "$HOSTNAME" ] || HOSTNAME='grml'
392 [ -n "$HYBRID_METHOD" ] || HYBRID_METHOD='isohybrid'
393 [ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks'
394 [ -n "$SQUASHFS_EXCLUDES_FILE" ] || SQUASHFS_EXCLUDES_FILE="${GRML_FAI_CONFIG}/config/grml/squashfs-excludes"
395 [ -n "$SUITE" ] || SUITE='testing'
396 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
397 [ -n "$SCRIPTS_DIRECTORY" ] || SCRIPTS_DIRECTORY='/usr/share/grml-live/scripts'
398 [ -n "$USERNAME" ] || USERNAME='grml'
399 [ -n "$VERSION" ] || VERSION='0.0.1'
401 # output specific stuff, depends on $OUTPUT (iff not set):
402 [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live'
403 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
404 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
405 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
406 [ -n "$LOG_OUTPUT" ] || LOG_OUTPUT="$OUTPUT/grml_logs"
407 [ -n "$REPORTS" ] || REPORTS="${LOG_OUTPUT}/reports/"
408 [ -n "$NETBOOT" ] || NETBOOT="${OUTPUT}/netboot/"
411 # some misc checks before executing FAI {{{
412 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
413 specify it on the command line using the -c option."
414 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
415 specify it on the command line using the -o option."
417 # trim characters that are known to cause problems inside $GRML_NAME;
418 # for example isolinux does not like '-' inside the directory name
419 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
421 # export variables to have them available in fai scripts:
422 [ -n "$GRML_NAME" ] && export GRML_NAME="$GRML_NAME"
423 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
426 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
427 # this was default behaviour until grml-live 0.9.34:
428 if [ -n "$ZERO_LOGFILE" ] ; then
429 PRESERVE_LOGFILE='' # make sure it's cleaned then
430 ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
431 ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
436 # ask user whether the setup is ok {{{
437 if [ -z "$FORCE" ] ; then
439 echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
441 echo " FAI classes: $CLASSES"
442 [ -n "$LOCAL_CONFIG" ] && echo " Configuration: $LOCAL_CONFIG"
443 [ -n "$GRML_FAI_CONFIG" ] && echo " Config directory: $GRML_FAI_CONFIG"
444 echo " main directory: $OUTPUT"
445 [ -n "$EXTRACT_ISO_NAME" ] && echo " Extract ISO: $EXTRACT_ISO_NAME"
446 [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT"
447 [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT"
448 [ -n "$ISO_OUTPUT" ] && echo " ISO target: $ISO_OUTPUT"
449 [ -n "$GRML_NAME" ] && echo " Grml name: $GRML_NAME"
450 [ -n "$RELEASENAME" ] && echo " Release name: $RELEASENAME"
451 [ -n "$DATE" ] && echo " Build date: $DATE"
452 [ -n "$VERSION" ] && echo " Grml version: $VERSION"
453 [ -n "$SUITE" ] && echo " Debian suite: $SUITE"
454 [ -n "$ARCH" ] && echo " Architecture: $ARCH"
455 [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD"
456 [ -n "$HYBRID_METHOD" ] && echo " Hybrid method: $HYBRID_METHOD"
457 [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY"
458 [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL"
459 [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID"
460 [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature."
461 [ -n "$CHOWN_USER" ] && echo " Output owner: $CHOWN_USER"
462 [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
463 [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS"
464 [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE"
465 [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA/XZ) compression."
466 [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
467 [ -n "$VERBOSE" ] && echo " Using VERBOSE mode."
468 [ -n "$CLEAN_ARTIFACTS" ] && echo " Will clean output before and after running."
469 [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation."
470 if [ -n "$BOOTSTRAP_ONLY" ] ; then
471 echo " Bootstrapping only and not building (files for) ISO."
473 [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file."
474 [ -n "$SKIP_NETBOOT" ] && echo " Skipping creation of NETBOOT package."
475 [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file."
476 [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE."
477 [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched."
480 echo -n "Is this ok for you? [y/N] "
482 if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
484 echo "Exiting as requested."
491 # clean up before start {{{
492 if [ -n "${CLEAN_ARTIFACTS}" ]; then
493 echo "Wiping old artifacts"
494 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
495 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
496 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && rm -r "${ISO_OUTPUT}"
497 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && rm -r "${LOG_OUTPUT}"
498 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && rm -r "${NETBOOT}"
502 # create log file {{{
503 [ -n "$LOGFILE" ] || LOGFILE=${LOG_OUTPUT}/grml-live.log
504 mkdir -p $(dirname "${LOGFILE}")
506 chown root:adm $LOGFILE
510 # clean/zero/remove logfiles {{{
512 if [ -n "$PRESERVE_LOGFILE" ] ; then
513 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
515 # make sure it is empty (as it is e.g. appended to grml-live-db)
519 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
520 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
521 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
522 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
523 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
524 rm -f /var/log/fai/"$HOSTNAME"/last \
525 /var/log/fai/"$HOSTNAME"/last-dirinstall \
526 /var/log/fai/"$HOSTNAME"/last-softupdate
531 # source config and startup {{{
532 if [ -n "$CONFIG" ] ; then
533 if ! [ -f "$CONFIG" ] ; then
534 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
535 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
538 log "Sourcing $CONFIG"
543 start_seconds=$(cut -d . -f 1 /proc/uptime)
544 log "------------------------------------------------------------------------------"
545 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
546 log "Using local config file: $LOCAL_CONFIG"
547 log "Executed grml-live command line:"
550 einfo "Logging actions to logfile $LOGFILE"
553 # dump config variables into file, for script access {{{
556 '^(GRML_NAME|RELEASENAME|DATE|VERSION|SUITE|ARCH|DISTRI_NAME|USERNAME|HOSTNAME|APT_PROXY)=' \
560 # unpack iso/squashfs {{{
562 if [ -n "$EXTRACT_ISO_NAME" ]; then
563 log "Unpacking ISO from ${EXTRACT_ISO_NAME}"
564 einfo "Unpacking ISO from ${EXTRACT_ISO_NAME}"
565 local mountpoint=$(mktemp -d)
567 mount -o loop "${EXTRACT_ISO_NAME}" "$mountpoint" ; rc=$?
568 if [ "$rc" != 0 ]; then
571 eerror "mount failed"
576 if ls "${mountpoint}"/live/*/*.squashfs 2>/dev/null | grep -q . ; then # ISOs >=2011.12
577 log "Using ${mountpoint}/live/*/*.squashfs for unsquashfs"
578 unsquashfs -d "${CHROOT_OUTPUT}" "${mountpoint}"/live/*/*.squashfs ; rc=$?
579 elif ls "${mountpoint}"/live/*.squashfs 2>/dev/null | grep -q . ; then # ISOs before 2011.12
580 log "Using ${mountpoint}/live/*.squashfs for unsquashfs"
581 unsquashfs -d "${CHROOT_OUTPUT}" "${mountpoint}"/live/*.squashfs ; rc=$?
583 log "Error: Could not find any *.squashfs files on the ISO"
584 eerror "Error: Could not find any *.squashfs files on the ISO"
591 if [ "$rc" != 0 ]; then
592 log "unsquashfs failed"
593 eerror "unsquashfs failed"
602 # on-the-fly configuration {{{
604 # does this suck? YES!
605 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
607 unstable) SUITE='sid' ; CLASSES="DEBIAN_UNSTABLE,$CLASSES" ;;
608 *) CLASSES="DEBIAN_$(echo $SUITE | tr 'a-z' 'A-Z'),$CLASSES";;
610 export SUITE # make sure it's available in FAI scripts
612 # validate whether the specified architecture class matches the
613 # architecture (option), otherwise installation of kernel will fail
614 if echo $CLASSES | grep -qw I386 ; then
615 if ! [[ "$ARCH" == "i386" ]] ; then
616 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
617 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
618 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
622 elif echo $CLASSES | grep -qi amd64 ; then
623 if ! [[ "$ARCH" == "amd64" ]] ; then
624 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
625 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
626 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
632 # generate nfsroot configuration for FAI on the fly
633 if [ -z "$FAI_DEBOOTSTRAP" ] ; then
634 FAI_DEBOOTSTRAP="$SUITE http://ftp.debian.org/debian"
637 if [ -z "$FAI_DEBOOTSTRAP_OPTS" ] ; then
638 FAI_DEBOOTSTRAP_OPTS="--exclude=info,tasksel,tasksel-data --include=aptitude --arch $ARCH"
641 # create backup of old (not yet automatically generated) config file
642 if [ -f "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" ] ; then
643 if ! grep -q 'This is an automatically generated file by grml-live' "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" ; then
644 ewarn "Found old ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf - moving to ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf.outdated"
645 mv "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf.outdated"
650 echo "# This is an automatically generated file by grml-live.
651 # Do NOT edit this file, your changes will be lost.
652 FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"
653 FAI_DEBOOTSTRAP_OPTS=\"$FAI_DEBOOTSTRAP_OPTS\"
654 # EOF " > "${GRML_FAI_CONFIG}/nfsroot.conf"
655 # support FAI <=3.4.8, versions >=4.0 use nfsroot.conf
656 ( cd ${GRML_FAI_CONFIG} && ln -sf nfsroot.conf make-fai-nfsroot.conf )
659 # CHROOT_OUTPUT - execute FAI {{{
660 if [ -n "$BUILD_DIRTY" ]; then
661 log "Skipping stage 'fai' as requested via option -B"
662 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
664 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
666 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
667 FAI_ACTION=softupdate
669 FAI_ACTION=dirinstall
672 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
673 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
674 log "Error: does not look like you have a working chroot. Updating/building not possible."
675 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
681 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
682 log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
683 ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
685 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
687 if [ -n "${MIRROR_DIRECTORY}" ] ; then
688 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
689 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
692 mkdir -p "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
693 mount --bind "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
695 log "Executed FAI command line:"
696 log "BUILD_ONLY=$BUILD_ONLY BOOTSTRAP_ONLY=$BOOTSTRAP_ONLY GRML_LIVE_CONFIG=$CONFIGDUMP fai $VERBOSE -C $GRML_FAI_CONFIG -s file:///$GRML_FAI_CONFIG/config -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS"
697 BUILD_ONLY="$BUILD_ONLY" BOOTSTRAP_ONLY="$BOOTSTRAP_ONLY" GRML_LIVE_CONFIG="$CONFIGDUMP" fai $VERBOSE \
698 -C "$GRML_FAI_CONFIG" -s "file:///$GRML_FAI_CONFIG/config" -c"$CLASSES" \
699 -u "$HOSTNAME" "$FAI_ACTION" "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
700 RC="$PIPESTATUS" # notice: bash-only
702 if [ "$RC" != 0 ] ; then
703 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
704 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
708 # provide inform fai about the ISO we build, needs to be provided
709 # *after* FAI stage, otherwise FAI skips the debootstrap stage if
710 # there is not BASEFILE (as it checks for presence of /etc) :(
711 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
712 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
713 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
715 FORCE_ISO_REBUILD=true
717 # move fai logs into grml_logs directory
718 mkdir -p "$LOG_OUTPUT"/fai/
719 cp -r "$CHROOT_OUTPUT"/var/log/fai/"$HOSTNAME"/last/* "$LOG_OUTPUT"/fai/
720 rm -rf "$CHROOT_OUTPUT"/var/log/fai
722 # store copy of autogenerated configuration file
723 cp ${GRML_FAI_CONFIG}/nfsroot.conf "$LOG_OUTPUT"/fai/
725 # copy fai package list
726 cp "$CHROOT_OUTPUT"/var/log/install_packages.list "$LOG_OUTPUT"/fai/
728 chown root:adm "$LOG_OUTPUT"/fai/*
729 chmod 664 "$LOG_OUTPUT"/fai/*
733 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
735 CHECKLOG="$LOG_OUTPUT"/fai/
736 if [ -r "$CHECKLOG/software.log" ] ; then
737 # 1 errors during executing of commands
738 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
739 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
740 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
741 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
742 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
745 if [ -r "$CHECKLOG/shell.log" ] ; then
746 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
749 if [ -r "$CHECKLOG/fai.log" ] ; then
750 grep 'updatebase.*FAILED with exit code' "$CHECKLOG/fai.log" >> "$LOGFILE" && ERROR=7
751 grep 'instsoft.*FAILED with exit code' "$CHECKLOG/fai.log" >> "$LOGFILE" && ERROR=8
754 if [ -n "$ERROR" ] ; then
755 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
756 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
757 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
761 log "Finished execution of stage 'fai dirinstall' [$(date)]"
762 einfo "Finished execution of stage 'fai dirinstall'"
768 # package validator {{{
769 CHECKLOG=/var/log/fai/$HOSTNAME/last
770 if [ -r "$CHECKLOG/dpkg.selections" ] ; then
771 package_count=$(wc -l "$CHECKLOG/dpkg.selections" | awk '{print $1}')
773 package_count="unknown"
777 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
779 # check for missing packages
780 if ! [ -s "$CHECKLOG/package_errors.log" ] ; then
781 einfo "No missing packages found, generating empty junit report."
783 cat > "${REPORT_MISSING_PACKAGES}" << EOF
784 <?xml version="1.0" encoding="UTF-8"?>
785 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="0" errors="0" skipped="0" assertions="0">
786 <testcase name="test_missing_packages" time="0" assertions="0">
796 einfo "Missing packages found, generating junit report."
798 if [ -r "$CHECKLOG/package_errors.log" ] ; then
799 package_errors=$(wc -l "$CHECKLOG/package_errors.log" | awk '{print $1}')
801 package_errors="unknown"
805 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
807 cat > "${REPORT_MISSING_PACKAGES}" << EOF
808 <?xml version="1.0" encoding="UTF-8"?>
809 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="${package_errors}" errors="${package_errors}" skipped="0" assertions="0">
812 for package in $(awk '{print $1}' "${CHECKLOG}/package_errors.log") ; do
813 failure_reason="$(awk "/$package/ {print \$2}" "${CHECKLOG}/package_errors.log")"
814 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
815 <testcase name="test_missing_packages_${package}" time="0" assertions="0">
816 <failure type="${failure_reason}" message="Package ${package} is missing">
817 Package $package is missing in chroot (${failure_reason})
823 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
832 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
833 eerror "The following packages were requested for installation but could not be processed:"
834 cat "$CHECKLOG/package_errors.log"
835 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
839 ewarn "The following packages were requested for installation but could not be processed:"
840 cat "$CHECKLOG/package_errors.log"
846 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
847 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
848 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
851 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
852 if [ -n "$BOOTSTRAP_ONLY" ] ; then
853 log "Skipping stage 'boot' as building with bootstrap only."
854 ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0
856 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
857 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
858 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
861 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
862 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
864 # if we don't have an initrd we a) can't boot and b) there was an error
865 # during build, so check for the file:
866 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
867 if [ -n "$INITRD" ] ; then
868 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.img
869 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
871 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
872 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
876 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
877 if [ -n "$KERNEL_IMAGE" ] ; then
878 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/vmlinuz
880 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
881 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
886 if [ -r "${CHROOT_OUTPUT}/boot/efi.img" -a -r "${CHROOT_OUTPUT}/boot/bootx64.efi" ] ; then
887 einfo "Moving EFI boot files into ISO path."
888 log "Moving EFI boot files into ISO path."
890 mv "${CHROOT_OUTPUT}/boot/efi.img" "${BUILD_OUTPUT}/boot/" || RC=$?
891 mkdir -p "${BUILD_OUTPUT}/efi/boot/" || RC=$?
892 mv "${CHROOT_OUTPUT}/boot/bootx64.efi" "${BUILD_OUTPUT}/efi/boot/bootx64.efi" || RC=$?
896 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
897 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
898 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
899 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
903 # copy _required_ isolinux files
904 if [ -d "${CHROOT_OUTPUT}/usr/lib/ISOLINUX" ] ; then
905 copy_addon_file isolinux.bin /usr/lib/ISOLINUX isolinux
906 copy_addon_file ifcpu64.c32 /usr/lib/syslinux/modules/bios/ isolinux
907 copy_addon_file ldlinux.c32 /usr/lib/syslinux/modules/bios/ isolinux
908 copy_addon_file libcom32.c32 /usr/lib/syslinux/modules/bios/ isolinux
909 copy_addon_file libgpl.c32 /usr/lib/syslinux/modules/bios/ isolinux
910 copy_addon_file libmenu.c32 /usr/lib/syslinux/modules/bios/ isolinux
911 copy_addon_file libutil.c32 /usr/lib/syslinux/modules/bios/ isolinux
912 copy_addon_file vesamenu.c32 /usr/lib/syslinux/modules/bios/ isolinux
913 else # syslinux versions <= 3:4.05+dfsg-6+deb8u1
914 copy_addon_file isolinux.bin /usr/lib/syslinux isolinux
915 copy_addon_file ifcpu64.c32 /usr/lib/syslinux isolinux
916 copy_addon_file vesamenu.c32 /usr/lib/syslinux isolinux
919 # *always* copy files to output directory so the variables
920 # get adjusted according to the build.
921 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
923 mkdir -p "${BUILD_OUTPUT}/boot/grub"
924 cp -a ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
926 if [ -n "$NO_ADDONS" ] ; then
927 rm -f "$BUILD_OUTPUT"/boot/grub/addons.cfg
928 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
929 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
931 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
932 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
933 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
935 # copy addons from system packages or grml-live-compat
936 copy_addon_file ipxe.lkrn /usr/lib/ipxe addons
937 copy_addon_file pci.ids /usr/share/misc addons
938 copy_addon_file memtest86+.bin /boot addons
940 # since syslinux(-common) v3:6.03~pre1+dfsg-4 the files are in a
941 # different directory :(
942 if [ -d "${CHROOT_OUTPUT}/usr/lib/syslinux/modules/bios/" ] ; then
943 syslinux_modules_dir=/usr/lib/syslinux/modules/bios/
945 syslinux_modules_dir=/usr/lib/syslinux
947 for file in chain.c32 hdt.c32 mboot.c32 menu.c32; do
948 copy_addon_file "${file}" "${syslinux_modules_dir}" addons
951 copy_addon_file memdisk /usr/lib/syslinux addons
953 # make memtest filename FAT16/8.3 compatible
954 mv "${BUILD_OUTPUT}/boot/addons/memtest86+.bin" \
955 "${BUILD_OUTPUT}/boot/addons/memtest"
957 # copy only files so we can handle bsd4grml on its own
958 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
959 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
962 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
963 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
964 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
966 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
967 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
969 log "Missing addon file: bsd4grml"
970 ewarn "Missing addon file: bsd4grml" ; eend 0
974 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
977 # generate loopback.cfg config file without depending on grub's regexp module
978 # which isn't available in Debian/squeeze
979 echo "## grub2 loopback configuration" > "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
980 echo "source /boot/grub/header.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
981 for config in "${BUILD_OUTPUT}"/boot/grub/*_default.cfg "${BUILD_OUTPUT}"/boot/grub/*_options.cfg ; do
982 [ -r "$config" ] || continue
983 echo "source ${config##$BUILD_OUTPUT}" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
985 if [ -z "$NO_ADDONS" ] ; then
986 echo "source /boot/grub/addons.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
988 echo "source /boot/grub/footer.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
990 # copy grub files from target
991 mkdir -p "${BUILD_OUTPUT}"/boot/grub/i386-pc/
992 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.mod "${BUILD_OUTPUT}"/boot/grub/i386-pc/
993 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.o "${BUILD_OUTPUT}"/boot/grub/i386-pc/
994 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.lst "${BUILD_OUTPUT}"/boot/grub/i386-pc/
995 cp -a "${CHROOT_OUTPUT}"/usr/share/grub/ascii.pf2 "${BUILD_OUTPUT}"/boot/grub/
996 cp -a "${CHROOT_OUTPUT}"/boot/grub/core.img "${BUILD_OUTPUT}"/boot/grub/
997 cp -a "${CHROOT_OUTPUT}"/boot/grub/grub.img "${BUILD_OUTPUT}"/boot/grub/
999 # copy modules for UEFI grub
1000 mkdir -p "${BUILD_OUTPUT}"/boot/grub/x86_64-efi/
1001 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/x86_64-efi/*.{mod,lst} "${BUILD_OUTPUT}"/boot/grub/x86_64-efi/
1003 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
1004 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
1005 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
1009 mkdir -p "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
1010 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
1012 # adjust boot splash information:
1013 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
1014 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
1015 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
1017 if [ -r "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version ] ; then
1018 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
1019 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
1022 # make sure the squashfs filename is set accordingly:
1023 SQUASHFS_NAME="$GRML_NAME.squashfs"
1025 if [ -n "$NO_BOOTID" ] ; then
1026 log 'Skipping bootid feature as requested via $NO_BOOTID.'
1027 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
1029 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
1030 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
1031 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
1032 log "Generating /conf/bootid.txt with entry ${BOOTID}."
1033 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
1037 # adjust all variables in the templates with the according distribution information
1038 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
1039 "${BUILD_OUTPUT}"/boot/grub/* ; do
1040 if [ -r "${file}" ] && [ -f "${file}" ] ; then
1041 sed -i "s/%ARCH%/$ARCH/g" "${file}"
1042 sed -i "s/%DATE%/$DATE/g" "${file}"
1043 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
1044 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
1045 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
1046 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
1047 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
1048 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
1049 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
1050 sed -i "s/%VERSION%/$VERSION/g" "${file}"
1052 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s; boot=live; boot=live $DEFAULT_BOOTOPTIONS;" "${file}"
1054 if [ -n "$NO_BOOTID" ] ; then
1055 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
1057 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
1062 for param in ARCH DATE DISTRI_INFO DISTRI_NAME DISTRI_SPLASH GRML_NAME SQUASHFS_NAME \
1063 RELEASE_INFO SHORT_NAME VERSION ; do
1064 for file in $(find "${BUILD_OUTPUT}" -name "*%$param%*") ; do
1065 value="$(eval echo '$'"$param")"
1066 mv ${file} ${file/\%${param}\%/$value}
1070 # adjust bootsplash accordingly but make sure the string has the according lenght
1071 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
1072 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
1073 for file in f4 f5 ; do
1074 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
1075 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
1076 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
1080 # generate addon list
1081 rm -f "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
1082 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
1083 include_name=$(basename "$name")
1084 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
1087 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
1088 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1089 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1090 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1091 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1092 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1094 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
1095 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1098 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1099 if [ -z "$NO_ADDONS" ] ; then
1100 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1102 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1103 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1104 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1105 else # assume we are building a custom distribution:
1106 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
1107 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
1108 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1109 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1111 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1115 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1116 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1117 if [ -z "$NO_ADDONS" ] ; then
1118 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1123 # use old style console based isolinux method only if requested:
1124 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
1125 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1126 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1127 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1128 einfo "include for console.cfg already found, nothing to do."
1131 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1132 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1133 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1137 log 'Using graphical boot menu.'
1138 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
1139 log "include for vesamenu.cfg already found, nothing to do."
1141 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1142 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1146 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
1147 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
1150 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
1151 if ! [ -r "$DPKG_LIST" ] ; then
1152 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
1154 einfo "Storing package list information as /GRML/${GRML_NAME}/packages.txt on ISO."
1155 cp "$DPKG_LIST" "${BUILD_OUTPUT}"/GRML/"${GRML_NAME}"/packages.txt
1159 # autostart for Windows:
1160 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
1161 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
1164 FORCE_ISO_REBUILD=true
1165 einfo "Finished execution of stage 'boot'" ; eend 0
1169 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
1170 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
1174 # support installation of local files into the chroot/ISO
1175 if [ -n "$CHROOT_INSTALL" ] ; then
1176 if ! [ -d "$CHROOT_INSTALL" ] ; then
1177 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1178 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1180 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1181 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1182 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
1184 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
1185 FORCE_ISO_REBUILD=true
1189 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1190 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
1191 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
1192 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
1193 log "Skipping stage 'squashfs' as requested via option -q or -N"
1194 ewarn "Skipping stage 'squashfs' as requested via option -q or -N" ; eend 0
1196 mkdir -p "$BUILD_OUTPUT"/live/"${GRML_NAME}"/
1197 # make sure we don't leave (even an empty) base.tgz:
1198 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
1200 # if unconfigured default to squashfs-tools' mksquashfs binary
1201 if [ -z "$SQUASHFS_BINARY" ] ; then
1202 SQUASHFS_BINARY='mksquashfs'
1205 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
1206 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
1207 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
1209 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
1210 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
1214 # use sane defaults if $SQUASHFS_OPTIONS isn't set
1215 if [ -z "$SQUASHFS_OPTIONS" ] ; then
1216 # use blocksize 256k as this gives best result with regards to time + compression
1217 SQUASHFS_OPTIONS="-b 256k"
1219 # set lzma/xz compression by default, unless -z option has been specified on command line
1220 if [ -z "$SQUASHFS_ZLIB" ] ; then
1221 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
1223 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
1227 # support exclusion of files via exclude-file:
1228 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
1229 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE -wildcards"
1232 # get rid of unnecessary files when building grml-small for final release:
1233 if echo "$CLASSES" | grep -q GRML_SMALL ; then
1234 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
1238 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
1240 # informational stuff
1241 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1242 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1243 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1245 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/${GRML_NAME}/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1247 if $SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/"${GRML_NAME}"/"${GRML_NAME}".squashfs \
1248 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1249 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/"${GRML_NAME}"/filesystem.module
1250 log "Finished execution of stage 'squashfs' [$(date)]"
1251 einfo "Finished execution of stage 'squashfs'" ; eend 0
1253 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1254 log "$(cat $SQUASHFS_STDERR)"
1255 eerror "Error: there was a critical error executing stage 'squashfs':"
1256 cat "${SQUASHFS_STDERR}"
1261 FORCE_ISO_REBUILD=true
1264 # create md5sum file:
1265 if [ -z "$BOOTSTRAP_ONLY" ] ; then
1266 ( cd $BUILD_OUTPUT/GRML/"${GRML_NAME}" &&
1267 find ../.. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1271 # ISO_OUTPUT - mkisofs {{{
1272 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1273 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1275 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1276 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1277 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1278 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1281 # Work around http://bts.grml.org/grml/issue945
1282 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1283 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1284 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1285 HYBRID_METHOD='grub2'
1289 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1290 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1291 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1292 elif [ -n "$SKIP_MKISOFS" ] ; then
1293 log "Skipping stage 'iso build' as requested via option -n or -N"
1294 ewarn "Skipping stage 'iso build' as requested via option -n or -N" ; eend 0
1296 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1298 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1299 log "Forcing rebuild of ISO because files on ISO have been modified."
1300 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1303 # support xorriso as well mkisofs and genisoimage
1304 if which xorriso >/dev/null 2>&1 ; then
1305 MKISOFS='xorriso -as mkisofs'
1306 elif which mkisofs >/dev/null 2>&1; then
1308 elif which genisoimage >/dev/null 2>&1; then
1309 MKISOFS='genisoimage'
1311 log "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO."
1312 eerror "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO." ; eend 1
1316 einfo "Using ${MKISOFS} to build ISO." ; eend 0
1317 case "${ARCH}-${MKISOFS}" in
1318 # using -eltorito-alt-boot is limited to xorriso for now
1322 if ! dpkg --compare-versions $(dpkg-query -W -f='${Version}\n' xorriso 2>/dev/null) gt-nl 1.1.6-1 ; then
1323 log "Disabling (U)EFI boot support because xorriso version is too old."
1324 ewarn "Disabling (U)EFI boot support because xorriso version is too old." ; eend 0
1326 if [ -r "${BUILD_OUTPUT}"/boot/efi.img ] ; then
1327 einfo "Enabling (U)EFI boot."
1328 log "Enabling (U)EFI boot."
1329 BOOT_ARGS="$BOOT_ARGS -boot-info-table -eltorito-alt-boot -e boot/efi.img -no-emul-boot"
1332 log "Disabling (U)EFI boot support because /boot/efi.img is missing."
1333 ewarn "Disabling (U)EFI boot support because /boot/efi.img is missing." ; eend 0
1342 if cd "$BUILD_OUTPUT" ; then
1343 if [ "$BOOT_METHOD" = "grub2" ]; then
1344 # make a 2048-byte bootsector for El Torito
1345 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1346 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1347 echo 1 16 | mksh "${SCRIPTS_DIRECTORY}/bootgrub.mksh" -B 11 | \
1348 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1350 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1351 $MKISOFS -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1352 -l -r -J $BOOT_ARGS -no-pad \
1353 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1354 # both of these need core.img there, so it’s easier to write it here
1355 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1356 # must be <= 30720 bytes
1357 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1358 conv=notrunc bs=512 seek=4 2>/dev/null
1361 # pad the output ISO to multiples of 256 KiB for partition table support
1362 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1363 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1364 siz=$((cyls * 16 * 32 * 512)) # size after padding
1365 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1366 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1368 # support disabling hybrid ISO image
1369 if [ "$HYBRID_METHOD" = "disable" ] ; then
1370 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1371 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1373 elif [ "$HYBRID_METHOD" = "manifold" ] || [ "$HYBRID_METHOD" = "grub2" ] ; then
1374 # isoinfo is part of both mkisofs and genisoimage so we're good
1375 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1376 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN[;1]* *$/s//\1/p')
1378 if ! [ -r boot/grub/core.img ] ; then
1379 log "boot/grub/core.img not found, not creating manifold boot ISO file"
1380 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1381 elif [ "${bootoff:-0}" -lt 1 ] ; then
1382 log "isolinux.bin not found on the ISO file, disabling manifold boot"
1383 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1385 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1386 log "Creating hybrid ISO file with manifold/grub2 method"
1387 einfo "Creating hybrid ISO file with manifold/grub2 method"
1388 # 512 bytes: MBR, partition table, load GRUB 2
1389 echo 4 63 | mksh "${SCRIPTS_DIRECTORY}/bootgrub.mksh" -A -M 4:0x96 -g $cyls:16:32
1391 log "Creating hybrid ISO file with manifold method"
1392 einfo "Creating hybrid ISO file with manifold method"
1393 # read only one but 2048-byte sized (scale: << 2) sector
1394 echo $bootoff $bootoff | \
1395 mksh ${SCRIPTS_DIRECTORY}/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1396 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1399 elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
1400 if ! which isohybrid >/dev/null 2>&1 ; then
1401 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common/syslinux-utils"
1403 log "Creating hybrid ISO file with isohybrid method"
1404 einfo "Creating hybrid ISO file with isohybrid method"
1405 # Notes for consideration:
1406 # "-entry 4 -type 1c"
1407 # * using 4 as the partition number is supposed to help with BIOSes
1408 # that only support USB-Zip boot
1409 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1410 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1411 # to get the BIOS even look at the partition created by isohybrid
1412 if isohybrid --help | grep -q -- --uefi ; then
1413 if echo $CLASSES | grep -qw I386 ; then
1414 log "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring."
1415 einfo "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring."
1417 log "Detected uefi support for isohybrid, enabling"
1418 einfo "Detected uefi support for isohybrid, enabling"
1419 ISOHYBRID_OPTIONS=--uefi
1423 log "isohybrid $ISOHYBRID_OPTIONS ${ISO_OUTPUT}/${ISO_NAME}"
1424 isohybrid $ISOHYBRID_OPTIONS "${ISO_OUTPUT}/${ISO_NAME}"
1428 bailout 12 "Unknown HYBRID_METHOD [${HYBRID_METHOD}]. Supported values: disable, isohybrid, grub2, manifold"
1431 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1432 case $CLASSES in *RELEASE*)
1435 if cd $ISO_OUTPUT ; then
1436 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1437 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1438 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1439 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1448 if [ "$RC" = 0 ] ; then
1449 log "Finished execution of stage 'iso build' [$(date)]"
1450 einfo "Finished execution of stage 'iso build'" ; eend 0
1452 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1453 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1459 # netboot package {{{
1460 create_netbootpackage() {
1461 local OUTPUT_FILE="${NETBOOT}/grml_netboot_package_${GRML_NAME}_${VERSION}.tar.bz2"
1463 if [ -f "${OUTPUT_FILE}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1464 log "Skipping stage 'netboot' as $OUTPUT_FILE exists already."
1465 ewarn "Skipping stage 'netboot' as $OUTPUT_FILE exists already." ; eend 0
1467 elif [ -n "$SKIP_NETBOOT" ] ; then
1468 log "Skipping stage 'netboot' as requested via option -Q"
1469 ewarn "Skipping stage 'netboot' as requested via option -Q" ; eend 0
1475 # since syslinux v3:6.03~pre1+dfsg-4 the pxelinux.0 has been split into a
1476 # separate pxelinux package
1477 if [ -d "${CHROOT_OUTPUT}/usr/lib/PXELINUX/" ] ; then
1478 local pxelinux_dir=/usr/lib/PXELINUX
1480 local pxelinux_dir=/usr/lib/syslinux
1483 if ! [ -r "${CHROOT_OUTPUT}/${pxelinux_dir}/pxelinux.0" ] ; then
1484 ewarn "File ${pxelinux_dir}/pxelinux.0 not found in build chroot." ; eend 0
1486 einfo "Install syslinux[-common]/pxelinux package in chroot to get a netboot package."
1491 local OUTPUTDIR="${NETBOOT}/build_tmp"
1492 local WORKING_DIR="${OUTPUTDIR}/grml_netboot_package_${GRML_NAME}_${VERSION}/tftpboot/"
1494 mkdir -p "$WORKING_DIR"
1496 cp "${CHROOT_OUTPUT}"/boot/vmlinuz-* "$WORKING_DIR"/vmlinuz
1497 cp "${CHROOT_OUTPUT}"/boot/initrd.img-* "$WORKING_DIR"/initrd.img
1498 cp "${CHROOT_OUTPUT}/${pxelinux_dir}/pxelinux.0" "${WORKING_DIR}/pxelinux.0"
1500 mkdir -p "${WORKING_DIR}/pxelinux.cfg"
1501 if [ -r "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" ] ; then
1502 cp "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" "${WORKING_DIR}/pxelinux.cfg/default"
1504 log "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found."
1505 ewarn "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found."
1507 log "Hint: Are you using custom templates which do not provide netboot.cfg?"
1508 ewarn "Hint: Are you using custom templates which do not provide netboot.cfg?" ; eend 0
1512 if tar -C "$OUTPUTDIR" -jcf "${OUTPUT_FILE}" "grml_netboot_package_${GRML_NAME}_${VERSION}" ; then
1514 cd $(dirname "${OUTPUT_FILE}")
1515 sha1sum $(basename "${OUTPUT_FILE}") > "${OUTPUT_FILE}.sha1"
1517 einfo "Generated netboot package ${OUTPUT_FILE}" ; eend 0
1518 rm -rf "${OUTPUTDIR}"
1520 rm -rf "${OUTPUTDIR}"
1521 eerror "Could not generate netboot package ${OUTPUT_FILE}" ; eend 1
1526 create_netbootpackage
1529 # log build information to database if grml-live-db is installed and enabled {{{
1531 if [ -d /usr/share/grml-live-db ] ; then
1534 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1535 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1536 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1537 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1539 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1540 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1541 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1545 # disable by default for now, not sure whether really everyone is using a local db file
1546 #if ! touch "$DPKG_DATABASE" ; then
1547 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1551 if ! [ -r "$DPKG_LIST" ] ; then
1552 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1553 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1555 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1556 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1557 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1560 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1576 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1577 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1579 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1581 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1585 ## END OF FILE #################################################################
1586 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=2