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; values: etch, lenny, squeeze, sid
68 -t <template_directory> place of the templates
69 -u update existing chroot instead of rebuilding it from scratch
70 -U <username> arrange output to be owned by specified username
71 -v <version_number> specify version number of the release
72 -V increase verbosity in the build process
73 -z use ZLIB instead of LZMA/XZ compression
78 $PN -c GRMLBASE,GRML_FULL,AMD64 -o /dev/shm/grml
79 $PN -c GRMLBASE,GRML_FULL,AMD64 -i grml_0.0-1.iso -v 0.0-1
80 $PN -c GRMLBASE,GRML_FULL,AMD64 -s sid -V -r 'grml-live rocks'
82 More details: man grml-live + /usr/share/doc/grml-live/grml-live.html
83 http://grml.org/grml-live/
85 Please send your bug reports and feedback to the grml-team: http://grml.org/bugs/
87 [ "$(id -u 2>/dev/null)" != 0 ] && echo "Please notice that this script requires root permissions."
90 # make sure it's possible to get usage information without being
91 # root or actually executing the script
92 if [ "$1" = '-h' -o "$1" = '--help' ] ; then
98 # some runtime checks {{{
99 # we need root permissions for the build-process:
100 if [ "$(id -u 2>/dev/null)" != 0 ] ; then
101 echo "Error: please run this script with uid 0 (root)." >&2
105 if [ -r /var/run/fai/FAI_INSTALLATION_IN_PROGRESS ] ; then
106 echo "/usr/sbin/fai already running or was aborted before.">&2
107 echo "You may remove /var/run/fai/FAI_INSTALLATION_IN_PROGRESS and try again.">&2
112 if [ -r /var/run/fai/fai_softupdate_is_running ] ; then
113 echo "/usr/sbin/fai softupdate already running or was aborted before.">&2
114 echo "You may remove /var/run/fai/fai_softupdate_is_running and try again.">&2
119 # lsb-functions and configuration stuff {{{
120 # make sure they are not set by default
131 # don't use colors/escape sequences
132 if [ -r /lib/lsb/init-functions ] ; then
133 . /lib/lsb/init-functions
134 ! log_use_fancy_output && NOCOLORS=true
137 if [ -r /etc/grml/lsb-functions ] ; then
138 . /etc/grml/lsb-functions
140 einfo() { echo " [*] $*" ;}
141 eerror() { echo " [!] $*">&2 ;}
142 ewarn() { echo " [x] $*" ;}
144 eindent() { return 0 ;}
145 eoutdent() { return 0 ;}
148 # source main configuration file:
149 LIVE_CONF=/etc/grml/grml-live.conf
153 # umount all directories {{{
155 # make sure we don't leave any mounts - FAI doesn't remove them always
156 umount $CHROOT_OUTPUT/proc/sys/fs/binfmt_misc 2>/dev/null || /bin/true
157 umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
158 umount $CHROOT_OUTPUT/run 2>/dev/null || /bin/true
159 umount $CHROOT_OUTPUT/sys 2>/dev/null || /bin/true
160 umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
161 umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
163 if [ -n "$EXTRACT_ISO_NAME" ] ; then
164 umount "$EXTRACT_ISO_NAME" 2>/dev/null || /bin/true
167 # certain FAI versions sadly leave a ramdisk behind, so better safe than sorry
168 if [ -x /usr/lib/fai/mkramdisk ] ; then
169 /usr/lib/fai/mkramdisk -u "$(readlink -f ${CHROOT_OUTPUT}/var/lib/dpkg)" >/dev/null 2>&1 || /bin/true
172 umount "${CHROOT_OUTPUT}/grml-live/sources/" 2>/dev/null || /bin/true
173 [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
179 rm -f /var/run/fai/fai_softupdate_is_running \
180 /var/run/fai/FAI_INSTALLATION_IN_PROGRESS
181 [ -n "$CONFIGDUMP" ] && rm -f "$CONFIGDUMP"
182 [ -n "$SQUASHFS_STDERR" ] && rm -rf "$SQUASHFS_STDERR"
184 [ -n "$1" ] && EXIT="$1" || EXIT="1"
185 [ -n "$2" ] && eerror "$2">&2
186 if [ -n "$CLEAN_ARTIFACTS" ]; then
189 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
190 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
194 # get rid of automatically generated conffiles
195 rm -f ${GRML_FAI_CONFIG}/nfsroot.conf
196 rm -f ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf
198 if [ -n "$CHOWN_USER" ]; then
199 log "Setting ownership"
200 einfo "Setting ownership"
201 [ -n "${OUTPUT}" -a -d "${OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${OUTPUT}"
202 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${BUILD_OUTPUT}"
203 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${CHROOT_OUTPUT}"
204 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${ISO_OUTPUT}"
205 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${LOG_OUTPUT}"
206 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && chown -R "${CHOWN_USER}:" "${NETBOOT}"
209 log "------------------------------------------------------------------------------"
212 trap bailout 1 2 3 3 6 9 14 15
216 # some important functions {{{
219 # usage: log "string to log"
220 log() { [ -n "$LOGFILE" ] && echo "$*" >> $LOGFILE ; }
222 # cut string at character number int = $1
223 # usage: cut_string 5 "1234567890" will output "12345"
225 [ -n "$2" ] || return 1
226 echo "$2" | head -c "$1"; echo -ne "\n"
229 # prepend int = $1 spaces before string = $2
230 # usage: extend_string_begin 5 "123" will output " 123"
231 extend_string_begin() {
232 [ -n "$2" ] || return 1
233 local COUNT="$(echo $2 | wc -c)"
234 local FILL="$(expr $COUNT - $1)"
235 while [ "$FILL" -gt 1 ] ; do
237 local FILL=$(expr $FILL - 1)
239 while [ "$FILL" -lt 1 ] ; do
241 local FILL=$(expr $FILL + 1)
243 echo "$2" | head -c "$1"; echo -ne "\n"
246 # append int = $1 spaces to string = $2
247 # usage: extend_string_begin 5 "123" will output "123 "
248 extend_string_end() {
249 [ -n "$2" ] || return 1
250 echo -n "$2" | head -c "$1"
251 local COUNT="$(echo $2 | wc -c)"
252 local FILL="$(expr $COUNT - $1)"
253 while [ "$FILL" -gt 1 ] ; do
255 local FILL=$(expr $FILL - 1)
257 while [ "$FILL" -lt 1 ] ; do
259 local FILL=$(expr $FILL + 1)
264 # Copy addonfile $1 from either
265 # * the chroot (via $2, the system path),
266 # * or from TEMPLATE_DIRECTORY/compat (if exists),
267 # * or from the host system (again, using $2),
268 # or warn about the missing file.
271 # * We assume that the chroot always has a "good" version of
272 # the file. Also it makes sources handling easier.
273 # * On unstable, we Recommend the Debian packages containing
274 # these files. The user can override them by putting his
275 # "better" version into the chroot.
276 # * On stable, the Debian packages are probably not available,
277 # or outdated, so we look in TEMPLATE_DIRECTORY/compat first, where
278 # our grml-live-compat package installs current file versions.
280 DEST="${BUILD_OUTPUT}/boot/$3"
281 if [ ! -d "${DEST}/" ]; then
284 if [ -e "$CHROOT_OUTPUT/$2/$1" ]; then
285 log "Copying $1 from chroot"
286 cp "$CHROOT_OUTPUT/$2/$1" "${DEST}/"
289 if [ -e "${TEMPLATE_DIRECTORY}/compat/$3/$1" ]; then
290 log "Copying $1 from grml-live-compat"
291 cp "${TEMPLATE_DIRECTORY}/compat/$3/$1" "${DEST}/"
294 if [ -e "$2/$1" ]; then
295 log "Copying $1 from system"
296 cp "$2/$1" "${DEST}/"
300 msg="Missing addon file: \"$1\""
301 ewarn "$msg" ; eend 1
302 log "copy_addon_file: $msg"
306 # command line parsing {{{
307 while getopts "a:C:c:d:D:e:g:i:I:o:r:s:t:U:v:AbBFhnNqQuVz" opt; do
310 A) CLEAN_ARTIFACTS=1 ;;
313 c) CLASSES="$OPTARG" ;;
314 C) LOCAL_CONFIG="$(readlink -f $OPTARG)" ;;
316 D) GRML_FAI_CONFIG="$(readlink -f $OPTARG)" ;;
317 e) EXTRACT_ISO_NAME="$(readlink -f $OPTARG)" ;;
318 g) GRML_NAME="$OPTARG" ;;
319 h) usage ; bailout 0 ;;
320 i) ISO_NAME="$OPTARG" ;;
321 I) CHROOT_INSTALL="$OPTARG" ;;
323 N) BOOTSTRAP_ONLY=1; SKIP_MKISOFS=1; SKIP_MKSQUASHFS=1 ;;
324 o) OUTPUT="$(readlink -f $OPTARG)" ;;
325 q) SKIP_MKSQUASHFS=1 ;;
327 r) RELEASENAME="$OPTARG" ;;
328 s) SUITE="$OPTARG" ;;
329 t) TEMPLATE_DIRECTORY="$OPTARG";;
330 v) VERSION="$OPTARG" ;;
333 U) CHOWN_USER="$OPTARG" ;;
335 z) SQUASHFS_ZLIB=1 ;;
336 ?) echo "invalid option -$OPTARG" >&2; usage; bailout 1 ;;
339 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
341 if [ -n "$1" ] ; then
342 echo "Error: unknown argument '$1' in options. Exiting to avoid possible data loss." >&2
347 # read local (non-packaged) configuration {{{
348 if [ -z "$LOCAL_CONFIG" ]; then
349 if [ -r "/etc/grml/grml-live.local" ]; then
350 LOCAL_CONFIG="/etc/grml/grml-live.local"
353 if [ -n "$LOCAL_CONFIG" ]; then
354 if [ -r "$LOCAL_CONFIG" ]; then
357 eerror "Could not read specified local configuration file \"$LOCAL_CONFIG\"."
360 LOCAL_CONFIG=$(readlink -f "$LOCAL_CONFIG")
365 if [ -n "${GRML_LIVE_SOURCES:-}" ] ; then
366 eerror "Config variable \$GRML_LIVE_SOURCES is set. This variable has been deprecated."
367 ewarn "Please set up \${GRML_FAI_CONFIG}/config/files/etc/apt/sources.list.d/* instead."
372 # assume sane defaults (if not set already) {{{
373 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
374 [ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux'
375 [ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_FULL,$(echo ${ARCH} | tr 'a-z' 'A-Z')"
376 [ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)"
377 [ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators'
378 [ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml"
379 [ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png'
380 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
381 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai'
382 [ -n "$GRML_NAME" ] || GRML_NAME='grml'
383 [ -n "$HOSTNAME" ] || HOSTNAME='grml'
384 [ -n "$HYBRID_METHOD" ] || HYBRID_METHOD='isohybrid'
385 [ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks'
386 [ -n "$SQUASHFS_EXCLUDES_FILE" ] || SQUASHFS_EXCLUDES_FILE="${GRML_FAI_CONFIG}/config/grml/squashfs-excludes"
387 [ -n "$SUITE" ] || SUITE='testing'
388 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
389 [ -n "$USERNAME" ] || USERNAME='grml'
390 [ -n "$VERSION" ] || VERSION='0.0.1'
392 # output specific stuff, depends on $OUTPUT (iff not set):
393 [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live'
394 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
395 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
396 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
397 [ -n "$LOG_OUTPUT" ] || LOG_OUTPUT="$OUTPUT/grml_logs"
398 [ -n "$REPORTS" ] || REPORTS="${LOG_OUTPUT}/reports/"
399 [ -n "$NETBOOT" ] || NETBOOT="${OUTPUT}/netboot/"
402 # some misc checks before executing FAI {{{
403 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
404 specify it on the command line using the -c option."
405 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
406 specify it on the command line using the -o option."
408 # trim characters that are known to cause problems inside $GRML_NAME;
409 # for example isolinux does not like '-' inside the directory name
410 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
412 # export variables to have them available in fai scripts:
413 [ -n "$GRML_NAME" ] && export GRML_NAME="$GRML_NAME"
414 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
417 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
418 # this was default behaviour until grml-live 0.9.34:
419 if [ -n "$ZERO_LOGFILE" ] ; then
420 PRESERVE_LOGFILE='' # make sure it's cleaned then
421 ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
422 ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
427 # ask user whether the setup is ok {{{
428 if [ -z "$FORCE" ] ; then
430 echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
432 echo " FAI classes: $CLASSES"
433 [ -n "$LOCAL_CONFIG" ] && echo " Configuration: $LOCAL_CONFIG"
434 [ -n "$GRML_FAI_CONFIG" ] && echo " Config directory: $GRML_FAI_CONFIG"
435 echo " main directory: $OUTPUT"
436 [ -n "$EXTRACT_ISO_NAME" ] && echo " Extract ISO: $EXTRACT_ISO_NAME"
437 [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT"
438 [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT"
439 [ -n "$ISO_OUTPUT" ] && echo " ISO target: $ISO_OUTPUT"
440 [ -n "$GRML_NAME" ] && echo " Grml name: $GRML_NAME"
441 [ -n "$RELEASENAME" ] && echo " Release name: $RELEASENAME"
442 [ -n "$DATE" ] && echo " Build date: $DATE"
443 [ -n "$VERSION" ] && echo " Grml version: $VERSION"
444 [ -n "$SUITE" ] && echo " Debian suite: $SUITE"
445 [ -n "$ARCH" ] && echo " Architecture: $ARCH"
446 [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD"
447 [ -n "$HYBRID_METHOD" ] && echo " Hybrid method: $HYBRID_METHOD"
448 [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY"
449 [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL"
450 [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID"
451 [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature."
452 [ -n "$CHOWN_USER" ] && echo " Output owner: $CHOWN_USER"
453 [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
454 [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS"
455 [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE"
456 [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA/XZ) compression."
457 [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
458 [ -n "$VERBOSE" ] && echo " Using VERBOSE mode."
459 [ -n "$CLEAN_ARTIFACTS" ] && echo " Will clean output before and after running."
460 [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation."
461 if [ -n "$BOOTSTRAP_ONLY" ] ; then
462 echo " Bootstrapping only and not building (files for) ISO."
464 [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file."
465 [ -n "$SKIP_NETBOOT" ] && echo " Skipping creation of NETBOOT package."
466 [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file."
467 [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE."
468 [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched."
471 echo -n "Is this ok for you? [y/N] "
473 if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
475 echo "Exiting as requested."
482 # clean up before start {{{
483 if [ -n "${CLEAN_ARTIFACTS}" ]; then
484 echo "Wiping old artifacts"
485 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
486 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
487 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && rm -r "${ISO_OUTPUT}"
488 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && rm -r "${LOG_OUTPUT}"
489 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && rm -r "${NETBOOT}"
493 # create log file {{{
494 [ -n "$LOGFILE" ] || LOGFILE=${LOG_OUTPUT}/grml-live.log
495 mkdir -p $(dirname "${LOGFILE}")
497 chown root:adm $LOGFILE
501 # clean/zero/remove logfiles {{{
503 if [ -n "$PRESERVE_LOGFILE" ] ; then
504 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
506 # make sure it is empty (as it is e.g. appended to grml-live-db)
510 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
511 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
512 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
513 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
514 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
515 rm -f /var/log/fai/"$HOSTNAME"/last \
516 /var/log/fai/"$HOSTNAME"/last-dirinstall \
517 /var/log/fai/"$HOSTNAME"/last-softupdate
522 # source config and startup {{{
523 if [ -n "$CONFIG" ] ; then
524 if ! [ -f "$CONFIG" ] ; then
525 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
526 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
529 log "Sourcing $CONFIG"
534 start_seconds=$(cut -d . -f 1 /proc/uptime)
535 log "------------------------------------------------------------------------------"
536 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
537 log "Using local config file: $LOCAL_CONFIG"
538 log "Executed grml-live command line:"
541 einfo "Logging actions to logfile $LOGFILE"
544 # dump config variables into file, for script access {{{
547 '^(GRML_NAME|RELEASENAME|DATE|VERSION|SUITE|ARCH|DISTRI_NAME|USERNAME|HOSTNAME|APT_PROXY)=' \
551 # unpack iso/squashfs {{{
553 if [ -n "$EXTRACT_ISO_NAME" ]; then
554 log "Unpacking ISO from ${EXTRACT_ISO_NAME}"
555 einfo "Unpacking ISO from ${EXTRACT_ISO_NAME}"
556 local mountpoint=$(mktemp -d)
558 mount -o loop "${EXTRACT_ISO_NAME}" "$mountpoint" ; rc=$?
559 if [ "$rc" != 0 ]; then
562 eerror "mount failed"
567 if ls "${mountpoint}"/live/*/*.squashfs 2>/dev/null | grep -q . ; then # ISOs >=2011.12
568 log "Using ${mountpoint}/live/*/*.squashfs for unsquashfs"
569 unsquashfs -d "${CHROOT_OUTPUT}" "${mountpoint}"/live/*/*.squashfs ; rc=$?
570 elif ls "${mountpoint}"/live/*.squashfs 2>/dev/null | grep -q . ; then # ISOs before 2011.12
571 log "Using ${mountpoint}/live/*.squashfs for unsquashfs"
572 unsquashfs -d "${CHROOT_OUTPUT}" "${mountpoint}"/live/*.squashfs ; rc=$?
574 log "Error: Could not find any *.squashfs files on the ISO"
575 eerror "Error: Could not find any *.squashfs files on the ISO"
582 if [ "$rc" != 0 ]; then
583 log "unsquashfs failed"
584 eerror "unsquashfs failed"
593 # on-the-fly configuration {{{
595 # does this suck? YES!
596 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
598 unstable) SUITE='sid' ; CLASSES="DEBIAN_UNSTABLE,$CLASSES" ;;
599 *) CLASSES="DEBIAN_$(echo $SUITE | tr 'a-z' 'A-Z'),$CLASSES";;
601 export SUITE # make sure it's available in FAI scripts
603 # validate whether the specified architecture class matches the
604 # architecture (option), otherwise installation of kernel will fail
605 if echo $CLASSES | grep -qw I386 ; then
606 if ! [[ "$ARCH" == "i386" ]] ; then
607 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
608 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
609 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
613 elif echo $CLASSES | grep -qi amd64 ; then
614 if ! [[ "$ARCH" == "amd64" ]] ; then
615 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
616 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
617 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
623 # generate nfsroot configuration for FAI on the fly
624 if [ -z "$FAI_DEBOOTSTRAP" ] ; then
625 FAI_DEBOOTSTRAP="$SUITE http://cdn.debian.net/debian"
628 if [ -z "$FAI_DEBOOTSTRAP_OPTS" ] ; then
629 FAI_DEBOOTSTRAP_OPTS="--exclude=info,tasksel,tasksel-data --arch $ARCH"
632 # create backup of old (not yet automatically generated) config file
633 if [ -f "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" ] ; then
634 if ! grep -q 'This is an automatically generated file by grml-live' "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" ; then
635 ewarn "Found old ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf - moving to ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf.outdated"
636 mv "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf.outdated"
641 echo "# This is an automatically generated file by grml-live.
642 # Do NOT edit this file, your changes will be lost.
643 FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"
644 FAI_DEBOOTSTRAP_OPTS=\"$FAI_DEBOOTSTRAP_OPTS\"
645 # EOF " > "${GRML_FAI_CONFIG}/nfsroot.conf"
646 # support FAI <=3.4.8, versions >=4.0 use nfsroot.conf
647 ( cd ${GRML_FAI_CONFIG} && ln -sf nfsroot.conf make-fai-nfsroot.conf )
650 # CHROOT_OUTPUT - execute FAI {{{
651 if [ -n "$BUILD_DIRTY" ]; then
652 log "Skipping stage 'fai' as requested via option -B"
653 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
655 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
657 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
658 FAI_ACTION=softupdate
660 FAI_ACTION=dirinstall
663 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
664 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
665 log "Error: does not look like you have a working chroot. Updating/building not possible."
666 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
672 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
673 log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
674 ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
676 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
678 if [ -n "${MIRROR_DIRECTORY}" ] ; then
679 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
680 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
683 mkdir -p "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
684 mount --bind "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
686 log "Executed FAI command line:"
687 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"
688 BUILD_ONLY="$BUILD_ONLY" BOOTSTRAP_ONLY="$BOOTSTRAP_ONLY" GRML_LIVE_CONFIG="$CONFIGDUMP" fai $VERBOSE \
689 -C "$GRML_FAI_CONFIG" -s "file:///$GRML_FAI_CONFIG/config" -c"$CLASSES" \
690 -u "$HOSTNAME" "$FAI_ACTION" "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
691 RC="$PIPESTATUS" # notice: bash-only
693 # provide inform fai about the ISO we build, needs to be provided
694 # *after* FAI stage, otherwise FAI skips the debootstrap stage if
695 # there is not BASEFILE (as it checks for presence of /etc) :(
696 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
697 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
698 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
700 FORCE_ISO_REBUILD=true
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 # move fai logs into grml_logs directory
709 mkdir -p "$LOG_OUTPUT"/fai/
710 cp -r "$CHROOT_OUTPUT"/var/log/fai/"$HOSTNAME"/last/* "$LOG_OUTPUT"/fai/
711 rm -rf "$CHROOT_OUTPUT"/var/log/fai
713 # store copy of autogenerated configuration file
714 cp ${GRML_FAI_CONFIG}/nfsroot.conf "$LOG_OUTPUT"/fai/
716 # copy fai package list
717 cp "$CHROOT_OUTPUT"/var/log/install_packages.list "$LOG_OUTPUT"/fai/
719 chown root:adm "$LOG_OUTPUT"/fai/*
720 chmod 664 "$LOG_OUTPUT"/fai/*
724 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
726 CHECKLOG="$LOG_OUTPUT"/fai/
727 if [ -r "$CHECKLOG/software.log" ] ; then
728 # 1 errors during executing of commands
729 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
730 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
731 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
732 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
733 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
736 if [ -r "$CHECKLOG/shell.log" ] ; then
737 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
740 if [ -n "$ERROR" ] ; then
741 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
742 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
743 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
747 log "Finished execution of stage 'fai dirinstall' [$(date)]"
748 einfo "Finished execution of stage 'fai dirinstall'"
754 # package validator {{{
755 CHECKLOG=/var/log/fai/$HOSTNAME/last
756 if [ -r "$CHECKLOG/dpkg.selections" ] ; then
757 package_count=$(wc -l "$CHECKLOG/dpkg.selections" | awk '{print $1}')
759 package_count="unknown"
763 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
765 # check for missing packages
766 if ! [ -s "$CHECKLOG/package_errors.log" ] ; then
767 einfo "No missing packages found, generating empty junit report."
769 cat > "${REPORT_MISSING_PACKAGES}" << EOF
770 <?xml version="1.0" encoding="UTF-8"?>
771 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="0" errors="0" skipped="0" assertions="0">
772 <testcase name="test_missing_packages" time="0" assertions="0">
782 einfo "Missing packages found, generating junit report."
784 if [ -r "$CHECKLOG/package_errors.log" ] ; then
785 package_errors=$(wc -l "$CHECKLOG/package_errors.log" | awk '{print $1}')
787 package_errors="unknown"
791 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
793 cat > "${REPORT_MISSING_PACKAGES}" << EOF
794 <?xml version="1.0" encoding="UTF-8"?>
795 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="${package_errors}" errors="${package_errors}" skipped="0" assertions="0">
798 for package in $(awk '{print $1}' "${CHECKLOG}/package_errors.log") ; do
799 failure_reason="$(awk "/$package/ {print \$2}" "${CHECKLOG}/package_errors.log")"
800 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
801 <testcase name="test_missing_packages_${package}" time="0" assertions="0">
802 <failure type="${failure_reason}" message="Package ${package} is missing">
803 Package $package is missing in chroot (${failure_reason})
809 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
818 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
819 eerror "The following packages were requested for installation but could not be processed:"
820 cat "$CHECKLOG/package_errors.log"
821 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
825 ewarn "The following packages were requested for installation but could not be processed:"
826 cat "$CHECKLOG/package_errors.log"
832 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
833 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
834 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
837 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
838 if [ -n "$BOOTSTRAP_ONLY" ] ; then
839 log "Skipping stage 'boot' as building with bootstrap only."
840 ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0
842 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
843 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
844 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
847 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
848 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
850 # if we don't have an initrd we a) can't boot and b) there was an error
851 # during build, so check for the file:
852 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
853 if [ -n "$INITRD" ] ; then
854 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.img
855 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
857 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
858 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
862 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
863 if [ -n "$KERNEL_IMAGE" ] ; then
864 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/vmlinuz
866 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
867 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
872 if [ -r "${CHROOT_OUTPUT}/boot/efi.img" -a -r "${CHROOT_OUTPUT}/boot/bootx64.efi" ] ; then
873 einfo "Moving EFI boot files into ISO path."
874 log "Moving EFI boot files into ISO path."
876 mv "${CHROOT_OUTPUT}/boot/efi.img" "${BUILD_OUTPUT}/boot/" || RC=$?
877 mkdir -p "${BUILD_OUTPUT}/efi/boot/" || RC=$?
878 mv "${CHROOT_OUTPUT}/boot/bootx64.efi" "${BUILD_OUTPUT}/efi/boot/bootx64.efi" || RC=$?
882 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
883 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
884 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
885 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
889 # copy _required_ isolinux files
890 for file in ifcpu64.c32 isolinux.bin vesamenu.c32; do
891 copy_addon_file "${file}" /usr/lib/syslinux isolinux
894 # *always* copy files to output directory so the variables
895 # get adjusted according to the build.
896 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
898 if [ -n "$NO_ADDONS" ] ; then
899 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
900 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
902 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
903 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
904 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
906 # copy addons from system packages or grml-live-compat
907 copy_addon_file ipxe.lkrn /usr/lib/ipxe addons
908 copy_addon_file pci.ids /usr/share/misc addons
909 copy_addon_file memtest86+.bin /boot addons
910 for file in memdisk chain.c32 hdt.c32 mboot.c32 menu.c32; do
911 copy_addon_file "${file}" /usr/lib/syslinux addons
914 # make memtest filename FAT16/8.3 compatible
915 mv "${BUILD_OUTPUT}/boot/addons/memtest86+.bin" \
916 "${BUILD_OUTPUT}/boot/addons/memtest"
918 # copy only files so we can handle bsd4grml on its own
919 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
920 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
923 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
924 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
925 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
927 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
928 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
930 log "Missing addon file: bsd4grml"
931 ewarn "Missing addon file: bsd4grml" ; eend 0
935 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
938 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
939 mkdir -p "${BUILD_OUTPUT}/boot/grub"
941 cp -a ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
943 # generate loopback.cfg config file without depending on grub's regexp module
944 # which isn't available in Debian/squeeze
945 echo "## grub2 loopback configuration" > "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
946 echo "source /boot/grub/header.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
947 for config in "${BUILD_OUTPUT}"/boot/grub/*_default.cfg "${BUILD_OUTPUT}"/boot/grub/*_options.cfg ; do
948 [ -r "$config" ] || continue
949 echo "source ${config##$BUILD_OUTPUT}" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
951 echo "source /boot/grub/addons.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
952 echo "source /boot/grub/footer.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
954 # copy grub files from target
955 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.mod "${BUILD_OUTPUT}"/boot/grub/
956 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.o "${BUILD_OUTPUT}"/boot/grub/
957 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.lst "${BUILD_OUTPUT}"/boot/grub/
958 cp -a "${CHROOT_OUTPUT}"/usr/share/grub/ascii.pf2 "${BUILD_OUTPUT}"/boot/grub/
959 cp -a "${CHROOT_OUTPUT}"/boot/grub/core.img "${BUILD_OUTPUT}"/boot/grub/
960 cp -a "${CHROOT_OUTPUT}"/boot/grub/grub.img "${BUILD_OUTPUT}"/boot/grub/
962 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
963 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
964 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
968 mkdir -p "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
969 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
971 # adjust boot splash information:
972 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
973 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
974 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
976 if [ -r "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version ] ; then
977 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
978 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
981 # make sure the squashfs filename is set accordingly:
982 SQUASHFS_NAME="$GRML_NAME.squashfs"
984 if [ -n "$NO_BOOTID" ] ; then
985 log 'Skipping bootid feature as requested via $NO_BOOTID.'
986 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
988 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
989 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
990 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
991 log "Generating /conf/bootid.txt with entry ${BOOTID}."
992 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
996 # adjust all variables in the templates with the according distribution information
997 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
998 "${BUILD_OUTPUT}"/boot/grub/* ; do
999 if [ -r "${file}" ] && [ -f "${file}" ] ; then
1000 sed -i "s/%ARCH%/$ARCH/g" "${file}"
1001 sed -i "s/%DATE%/$DATE/g" "${file}"
1002 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
1003 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
1004 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
1005 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
1006 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
1007 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
1008 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
1009 sed -i "s/%VERSION%/$VERSION/g" "${file}"
1011 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s; boot=live; boot=live $DEFAULT_BOOTOPTIONS;" "${file}"
1013 if [ -n "$NO_BOOTID" ] ; then
1014 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
1016 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
1021 for param in ARCH DATE DISTRI_INFO DISTRI_NAME DISTRI_SPLASH GRML_NAME SQUASHFS_NAME \
1022 RELEASE_INFO SHORT_NAME VERSION ; do
1023 for file in $(find "${BUILD_OUTPUT}" -name "*%$param%*") ; do
1024 value="$(eval echo '$'"$param")"
1025 mv ${file} ${file/\%${param}\%/$value}
1029 # adjust bootsplash accordingly but make sure the string has the according lenght
1030 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
1031 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
1032 for file in f4 f5 ; do
1033 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
1034 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
1035 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
1039 # generate addon list
1040 rm -f "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
1041 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
1042 include_name=$(basename "$name")
1043 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
1046 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
1047 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1048 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1049 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1050 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1051 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1053 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
1054 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1057 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1058 if [ ! -n "$NO_ADDONS" ] ; then
1059 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1061 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1062 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1063 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1064 else # assume we are building a custom distribution:
1065 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
1066 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
1067 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1068 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1070 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1074 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1075 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1076 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1080 # use old style console based isolinux method only if requested:
1081 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
1082 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1083 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1084 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1085 einfo "include for console.cfg already found, nothing to do."
1088 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1089 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1090 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1094 log 'Using graphical boot menu.'
1095 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
1096 log "include for vesamenu.cfg already found, nothing to do."
1098 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1099 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1103 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
1104 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
1107 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
1108 if ! [ -r "$DPKG_LIST" ] ; then
1109 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
1111 einfo "Storing package list information as /GRML/${GRML_NAME}/packages.txt on ISO."
1112 cp "$DPKG_LIST" "${BUILD_OUTPUT}"/GRML/"${GRML_NAME}"/packages.txt
1116 # autostart for Windows:
1117 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
1118 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
1121 FORCE_ISO_REBUILD=true
1122 einfo "Finished execution of stage 'boot'" ; eend 0
1126 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
1127 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
1131 # support installation of local files into the chroot/ISO
1132 if [ -n "$CHROOT_INSTALL" ] ; then
1133 if ! [ -d "$CHROOT_INSTALL" ] ; then
1134 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1135 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1137 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1138 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1139 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
1141 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
1142 FORCE_ISO_REBUILD=true
1146 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1147 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
1148 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
1149 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
1150 log "Skipping stage 'squashfs' as requested via option -q or -N"
1151 ewarn "Skipping stage 'squashfs' as requested via option -q or -N" ; eend 0
1153 mkdir -p "$BUILD_OUTPUT"/live/"${GRML_NAME}"/
1154 # make sure we don't leave (even an empty) base.tgz:
1155 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
1157 # if unconfigured default to squashfs-tools' mksquashfs binary
1158 if [ -z "$SQUASHFS_BINARY" ] ; then
1159 SQUASHFS_BINARY='mksquashfs'
1162 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
1163 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
1164 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
1166 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
1167 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
1171 # use sane defaults if $SQUASHFS_OPTIONS isn't set
1172 if [ -z "$SQUASHFS_OPTIONS" ] ; then
1173 # use blocksize 256k as this gives best result with regards to time + compression
1174 SQUASHFS_OPTIONS="-b 256k"
1176 # set lzma/xz compression by default, unless -z option has been specified on command line
1177 if [ -z "$SQUASHFS_ZLIB" ] ; then
1178 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
1180 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
1184 # support exclusion of files via exclude-file:
1185 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
1186 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE -wildcards"
1189 # get rid of unnecessary files when building grml-small for final release:
1190 if echo "$CLASSES" | grep -q GRML_SMALL ; then
1191 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
1195 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
1197 # informational stuff
1198 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1199 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1200 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1202 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/${GRML_NAME}/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1204 if $SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/"${GRML_NAME}"/"${GRML_NAME}".squashfs \
1205 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1206 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/"${GRML_NAME}"/filesystem.module
1207 log "Finished execution of stage 'squashfs' [$(date)]"
1208 einfo "Finished execution of stage 'squashfs'" ; eend 0
1210 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1211 log "$(cat $SQUASHFS_STDERR)"
1212 eerror "Error: there was a critical error executing stage 'squashfs':"
1213 cat "${SQUASHFS_STDERR}"
1218 FORCE_ISO_REBUILD=true
1221 # create md5sum file:
1222 if [ -z "$BOOTSTRAP_ONLY" ] ; then
1223 ( cd $BUILD_OUTPUT/GRML/"${GRML_NAME}" &&
1224 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1228 # ISO_OUTPUT - mkisofs {{{
1229 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1230 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1232 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1233 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1234 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1235 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1238 # Work around http://bts.grml.org/grml/issue945
1239 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1240 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1241 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1242 HYBRID_METHOD='grub2'
1246 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1247 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1248 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1249 elif [ -n "$SKIP_MKISOFS" ] ; then
1250 log "Skipping stage 'iso build' as requested via option -n or -N"
1251 ewarn "Skipping stage 'iso build' as requested via option -n or -N" ; eend 0
1253 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1255 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1256 log "Forcing rebuild of ISO because files on ISO have been modified."
1257 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1260 # support xorriso as well mkisofs and genisoimage
1261 if which xorriso >/dev/null 2>&1 ; then
1262 MKISOFS='xorriso -as mkisofs'
1263 elif which mkisofs >/dev/null 2>&1; then
1265 elif which genisoimage >/dev/null 2>&1; then
1266 MKISOFS='genisoimage'
1268 log "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO."
1269 eerror "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO." ; eend 1
1273 einfo "Using ${MKISOFS} to build ISO." ; eend 0
1274 case "${ARCH}-${MKISOFS}" in
1275 # using -eltorito-alt-boot is limited to xorriso for now
1279 if ! dpkg --compare-versions $(dpkg-query -W -f='${Version}\n' xorriso 2>/dev/null) gt-nl 1.1.6-1 ; then
1280 log "Disabling (U)EFI boot support because xorriso version is too old."
1281 ewarn "Disabling (U)EFI boot support because xorriso version is too old." ; eend 0
1283 if [ -r "${BUILD_OUTPUT}"/boot/efi.img ] ; then
1284 einfo "Enabling (U)EFI boot."
1285 log "Enabling (U)EFI boot."
1286 BOOT_ARGS="$BOOT_ARGS -boot-info-table -eltorito-alt-boot -e boot/efi.img -no-emul-boot"
1289 log "Disabling (U)EFI boot support because /boot/efi.img is missing."
1290 ewarn "Disabling (U)EFI boot support because /boot/efi.img is missing." ; eend 0
1299 if cd "$BUILD_OUTPUT" ; then
1300 if [ "$BOOT_METHOD" = "grub2" ]; then
1301 # make a 2048-byte bootsector for El Torito
1302 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1303 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1304 echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
1305 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1307 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1308 $MKISOFS -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1309 -l -r -J $BOOT_ARGS -no-pad \
1310 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1311 # both of these need core.img there, so it’s easier to write it here
1312 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1313 # must be <= 30720 bytes
1314 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1315 conv=notrunc bs=512 seek=4 2>/dev/null
1318 # pad the output ISO to multiples of 256 KiB for partition table support
1319 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1320 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1321 siz=$((cyls * 16 * 32 * 512)) # size after padding
1322 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1323 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1325 # support disabling hybrid ISO image
1326 if [ "$HYBRID_METHOD" = "disable" ] ; then
1327 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1328 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1330 elif [ "$HYBRID_METHOD" = "manifold" ] || [ "$HYBRID_METHOD" = "grub2" ] ; then
1331 # isoinfo is part of both mkisofs and genisoimage so we're good
1332 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1333 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN[;1]* *$/s//\1/p')
1335 if ! [ -r boot/grub/core.img ] ; then
1336 log "boot/grub/core.img not found, not creating manifold boot ISO file"
1337 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1338 elif [ "${bootoff:-0}" -lt 1 ] ; then
1339 log "isolinux.bin not found on the ISO file, disabling manifold boot"
1340 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1342 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1343 log "Creating hybrid ISO file with manifold/grub2 method"
1344 einfo "Creating hybrid ISO file with manifold/grub2 method"
1345 # 512 bytes: MBR, partition table, load GRUB 2
1346 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1348 log "Creating hybrid ISO file with manifold method"
1349 einfo "Creating hybrid ISO file with manifold method"
1350 # read only one but 2048-byte sized (scale: << 2) sector
1351 echo $bootoff $bootoff | \
1352 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1353 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1356 elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
1357 if ! which isohybrid >/dev/null 2>&1 ; then
1358 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1360 log "Creating hybrid ISO file with isohybrid method"
1361 einfo "Creating hybrid ISO file with isohybrid method"
1362 # Notes for consideration:
1363 # "-entry 4 -type 1c"
1364 # * using 4 as the partition number is supposed to help with BIOSes
1365 # that only support USB-Zip boot
1366 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1367 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1368 # to get the BIOS even look at the partition created by isohybrid
1369 if isohybrid --help | grep -q -- --uefi ; then
1370 if echo $CLASSES | grep -qw I386 ; then
1371 log "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring."
1372 einfo "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring."
1374 log "Detected uefi support for isohybrid, enabling"
1375 einfo "Detected uefi support for isohybrid, enabling"
1376 ISOHYBRID_OPTIONS=--uefi
1380 log "isohybrid $ISOHYBRID_OPTIONS ${ISO_OUTPUT}/${ISO_NAME}"
1381 isohybrid $ISOHYBRID_OPTIONS "${ISO_OUTPUT}/${ISO_NAME}"
1385 bailout 12 "Unknown HYBRID_METHOD [${HYBRID_METHOD}]. Supported values: disable, isohybrid, grub2, manifold"
1388 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1389 case $CLASSES in *RELEASE*)
1392 if cd $ISO_OUTPUT ; then
1393 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1394 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1395 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1396 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1405 if [ "$RC" = 0 ] ; then
1406 log "Finished execution of stage 'iso build' [$(date)]"
1407 einfo "Finished execution of stage 'iso build'" ; eend 0
1409 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1410 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1416 # netboot package {{{
1417 create_netbootpackage() {
1418 local OUTPUT_FILE="${NETBOOT}/grml_netboot_package_${GRML_NAME}_${VERSION}.tar.bz2"
1420 if [ -f "${OUTPUT_FILE}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1421 log "Skipping stage 'netboot' as $OUTPUT_FILE exists already."
1422 ewarn "Skipping stage 'netboot' as $OUTPUT_FILE exists already." ; eend 0
1424 elif [ -n "$SKIP_NETBOOT" ] ; then
1425 log "Skipping stage 'netboot' as requested via option -Q"
1426 ewarn "Skipping stage 'netboot' as requested via option -Q" ; eend 0
1432 if ! [ -r "${CHROOT}/usr/lib/syslinux/pxelinux.0" ] ; then
1433 ewarn "File /usr/lib/syslinux/pxelinux.0 not found in build chroot." ; eend 0
1435 einfo "Install syslinux[-common] package in chroot to get a netboot package."
1440 local OUTPUTDIR="${NETBOOT}/build_tmp"
1441 local WORKING_DIR="${OUTPUTDIR}/grml_netboot_package_${GRML_NAME}_${VERSION}/tftpboot/"
1443 mkdir -p "$WORKING_DIR"
1445 cp "${CHROOT_OUTPUT}"/boot/vmlinuz-* "$WORKING_DIR"/vmlinuz
1446 cp "${CHROOT_OUTPUT}"/boot/initrd.img-* "$WORKING_DIR"/initrd.img
1447 cp "${CHROOT_OUTPUT}"/usr/lib/syslinux/pxelinux.0 "${WORKING_DIR}/pxelinux.0"
1449 mkdir -p "${WORKING_DIR}/pxelinux.cfg"
1450 if [ -r "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" ] ; then
1451 cp "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" "${WORKING_DIR}/pxelinux.cfg/default"
1453 log "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found."
1454 ewarn "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found."
1456 log "Hint: Are you using custom templates which do not provide netboot.cfg?"
1457 ewarn "Hint: Are you using custom templates which do not provide netboot.cfg?" ; eend 0
1461 if tar -C "$OUTPUTDIR" -jcf "${OUTPUT_FILE}" "grml_netboot_package_${GRML_NAME}_${VERSION}" ; then
1463 cd $(dirname "${OUTPUT_FILE}")
1464 sha1sum $(basename "${OUTPUT_FILE}") > "${OUTPUT_FILE}.sha1"
1466 einfo "Generated netboot package ${OUTPUT_FILE}" ; eend 0
1467 rm -rf "${OUTPUTDIR}"
1469 rm -rf "${OUTPUTDIR}"
1470 eerror "Could not generate netboot package ${OUTPUT_FILE}" ; eend 1
1475 create_netbootpackage
1478 # log build information to database if grml-live-db is installed and enabled {{{
1480 if [ -d /usr/share/grml-live-db ] ; then
1483 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1484 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1485 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1486 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1488 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1489 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1490 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1494 # disable by default for now, not sure whether really everyone is using a local db file
1495 #if ! touch "$DPKG_DATABASE" ; then
1496 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1500 if ! [ -r "$DPKG_LIST" ] ; then
1501 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1502 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1504 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1505 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1506 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1509 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1525 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1526 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1528 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1530 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1534 ## END OF FILE #################################################################
1535 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=2