3 # Purpose: build process script for generating a (grml based) Linux Live-ISO
4 # Authors: grml-team (grml.org),
5 # (c) Michael Prokop <mika@grml.org>,
6 # (c) Thorsten Glaser <tg@mirbsd.org>
7 # Bug-Reports: see http://grml.org/bugs/
8 # License: This file is licensed under the GPL v2 or any later version.
9 ################################################################################
11 # some misc and global stuff {{{
15 # define function getfilesize before "set -e"
16 if stat --help >/dev/null 2>&1; then
17 getfilesize='stat -c %s' # GNU stat
19 getfilesize='stat -f %z' # BSD stat
23 # disable for now since it seems to cause some problems
26 # The line following this line is patched by debian/rules.
27 GRML_LIVE_VERSION='***UNRELEASED***'
32 ADDONS_LIST_FILE='/boot/isolinux/addons_list.cfg'
35 # usage information {{{
39 $PN - build process script for generating a (grml based) Linux Live-ISO
41 Usage: $PN [options, see as follows]
43 -a <architecture> architecture; available values: i386 and amd64
44 -A clean build directories before and after running
45 -b build the ISO without updating the chroot via FAI
46 -B build the ISO without touching the chroot (skips cleanup)
47 -c <classe[s]> classes to be used for building the ISO via FAI
48 -C <configfile> configuration file for grml-live
49 -d <date> use specified date instead of build time as date of release
50 -D <configdir> use specified configuration directory instead of /etc/grml/fai
51 -e <iso_name> extract ISO and squashfs contents from iso_name
52 -F force execution without prompting
53 -g <grml_name> set the grml flavour name
54 -h display short usage information and exit
55 -i <iso_name> name of ISO
56 -I <src_directory> directory which provides files that should become
57 part of the chroot/ISO
58 -n skip generation of ISO
59 -N bootstrap (build chroot) only, do not create files for ISO
60 -o <output_directory> main output directory of the build process
62 -Q skip netboot package build
63 -r <release_name> release name
64 -s <suite> Debian suite; values: etch, lenny, squeeze, sid
65 -t <template_directory> place of the templates
66 -u update existing chroot instead of rebuilding it from scratch
67 -U <username> arrange output to be owned by specified username
68 -v <version_number> specify version number of the release
69 -V increase verbosity in the build process
70 -z use ZLIB instead of LZMA/XZ compression
75 $PN -c GRMLBASE,GRML_FULL,AMD64 -o /dev/shm/grml
76 $PN -c GRMLBASE,GRML_FULL,AMD64 -i grml_0.0-1.iso -v 0.0-1
77 $PN -c GRMLBASE,GRML_FULL,AMD64 -s sid -V -r 'grml-live rocks'
79 More details: man grml-live + /usr/share/doc/grml-live/grml-live.html
80 http://grml.org/grml-live/
82 Please send your bug reports and feedback to the grml-team: http://grml.org/bugs/
84 [ "$(id -u 2>/dev/null)" != 0 ] && echo "Please notice that this script requires root permissions."
87 # make sure it's possible to get usage information without being
88 # root or actually executing the script
89 if [ "$1" = '-h' -o "$1" = '--help' ] ; then
95 # some runtime checks {{{
96 # we need root permissions for the build-process:
97 if [ "$(id -u 2>/dev/null)" != 0 ] ; then
98 echo "Error: please run this script with uid 0 (root)." >&2
102 if [ -r /var/run/fai/FAI_INSTALLATION_IN_PROGRESS ] ; then
103 echo "/usr/sbin/fai already running or was aborted before.">&2
104 echo "You may remove /var/run/fai/FAI_INSTALLATION_IN_PROGRESS and try again.">&2
109 if [ -r /var/run/fai/fai_softupdate_is_running ] ; then
110 echo "/usr/sbin/fai softupdate already running or was aborted before.">&2
111 echo "You may remove /var/run/fai/fai_softupdate_is_running and try again.">&2
116 # lsb-functions and configuration stuff {{{
117 # make sure they are not set by default
128 # don't use colors/escape sequences
129 if [ -r /lib/lsb/init-functions ] ; then
130 . /lib/lsb/init-functions
131 ! log_use_fancy_output && NOCOLORS=true
134 if [ -r /etc/grml/lsb-functions ] ; then
135 . /etc/grml/lsb-functions
137 einfo() { echo " [*] $*" ;}
138 eerror() { echo " [!] $*">&2 ;}
139 ewarn() { echo " [x] $*" ;}
141 eindent() { return 0 ;}
142 eoutdent() { return 0 ;}
145 # source main configuration file:
146 LIVE_CONF=/etc/grml/grml-live.conf
150 # umount all directories {{{
152 # make sure we don't leave any mounts - FAI doesn't remove them always
153 umount $CHROOT_OUTPUT/proc/sys/fs/binfmt_misc 2>/dev/null || /bin/true
154 umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
155 umount $CHROOT_OUTPUT/run 2>/dev/null || /bin/true
156 umount $CHROOT_OUTPUT/sys 2>/dev/null || /bin/true
157 umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
158 umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
160 if [ -n "$EXTRACT_ISO_NAME" ] ; then
161 umount "$EXTRACT_ISO_NAME" 2>/dev/null || /bin/true
164 # certain FAI versions sadly leave a ramdisk behind, so better safe than sorry
165 if [ -x /usr/lib/fai/mkramdisk ] ; then
166 /usr/lib/fai/mkramdisk -u "$(readlink -f ${CHROOT_OUTPUT}/var/lib/dpkg)" >/dev/null 2>&1 || /bin/true
169 umount "${CHROOT_OUTPUT}/grml-live/sources/" 2>/dev/null || /bin/true
170 [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
176 rm -f /var/run/fai/fai_softupdate_is_running \
177 /var/run/fai/FAI_INSTALLATION_IN_PROGRESS
178 [ -n "$CONFIGDUMP" ] && rm -f "$CONFIGDUMP"
179 [ -n "$SQUASHFS_STDERR" ] && rm -rf "$SQUASHFS_STDERR"
181 [ -n "$1" ] && EXIT="$1" || EXIT="1"
182 [ -n "$2" ] && eerror "$2">&2
183 if [ -n "$CLEAN_ARTIFACTS" ]; then
186 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
187 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
191 # get rid of automatically generated conffiles
192 rm -f ${GRML_FAI_CONFIG}/nfsroot.conf
193 rm -f ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf
195 if [ -n "$CHOWN_USER" ]; then
196 log "Setting ownership"
197 einfo "Setting ownership"
198 [ -n "${OUTPUT}" -a -d "${OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${OUTPUT}"
199 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${BUILD_OUTPUT}"
200 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${CHROOT_OUTPUT}"
201 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${ISO_OUTPUT}"
202 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${LOG_OUTPUT}"
203 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && chown -R "${CHOWN_USER}:" "${NETBOOT}"
206 log "------------------------------------------------------------------------------"
209 trap bailout 1 2 3 3 6 9 14 15
213 # some important functions {{{
216 # usage: log "string to log"
217 log() { [ -n "$LOGFILE" ] && echo "$*" >> $LOGFILE ; }
219 # cut string at character number int = $1
220 # usage: cut_string 5 "1234567890" will output "12345"
222 [ -n "$2" ] || return 1
223 echo "$2" | head -c "$1"; echo -ne "\n"
226 # prepend int = $1 spaces before string = $2
227 # usage: extend_string_begin 5 "123" will output " 123"
228 extend_string_begin() {
229 [ -n "$2" ] || return 1
230 local COUNT="$(echo $2 | wc -c)"
231 local FILL="$(expr $COUNT - $1)"
232 while [ "$FILL" -gt 1 ] ; do
234 local FILL=$(expr $FILL - 1)
236 while [ "$FILL" -lt 1 ] ; do
238 local FILL=$(expr $FILL + 1)
240 echo "$2" | head -c "$1"; echo -ne "\n"
243 # append int = $1 spaces to string = $2
244 # usage: extend_string_begin 5 "123" will output "123 "
245 extend_string_end() {
246 [ -n "$2" ] || return 1
247 echo -n "$2" | head -c "$1"
248 local COUNT="$(echo $2 | wc -c)"
249 local FILL="$(expr $COUNT - $1)"
250 while [ "$FILL" -gt 1 ] ; do
252 local FILL=$(expr $FILL - 1)
254 while [ "$FILL" -lt 1 ] ; do
256 local FILL=$(expr $FILL + 1)
261 # Copy addonfile $1 from either
262 # * the chroot (via $2, the system path),
263 # * or from TEMPLATE_DIRECTORY/compat (if exists),
264 # * or from the host system (again, using $2),
265 # or warn about the missing file.
268 # * We assume that the chroot always has a "good" version of
269 # the file. Also it makes sources handling easier.
270 # * On unstable, we Recommend the Debian packages containing
271 # these files. The user can override them by putting his
272 # "better" version into the chroot.
273 # * On stable, the Debian packages are probably not available,
274 # or outdated, so we look in TEMPLATE_DIRECTORY/compat first, where
275 # our grml-live-compat package installs current file versions.
277 DEST="${BUILD_OUTPUT}/boot/$3"
278 if [ ! -d "${DEST}/" ]; then
281 if [ -e "$CHROOT_OUTPUT/$2/$1" ]; then
282 log "Copying $1 from chroot"
283 cp "$CHROOT_OUTPUT/$2/$1" "${DEST}/"
286 if [ -e "${TEMPLATE_DIRECTORY}/compat/$3/$1" ]; then
287 log "Copying $1 from grml-live-compat"
288 cp "${TEMPLATE_DIRECTORY}/compat/$3/$1" "${DEST}/"
291 if [ -e "$2/$1" ]; then
292 log "Copying $1 from system"
293 cp "$2/$1" "${DEST}/"
297 msg="Missing addon file: \"$1\""
298 ewarn "$msg" ; eend 1
299 log "copy_addon_file: $msg"
303 # command line parsing {{{
304 while getopts "a:C:c:d:D:e:g:i:I:o:r:s:t:U:v:AbBFhnNqQuVz" opt; do
307 A) CLEAN_ARTIFACTS=1 ;;
310 c) CLASSES="$OPTARG" ;;
311 C) LOCAL_CONFIG="$(readlink -f $OPTARG)" ;;
313 D) GRML_FAI_CONFIG="$(readlink -f $OPTARG)" ;;
314 e) EXTRACT_ISO_NAME="$(readlink -f $OPTARG)" ;;
315 g) GRML_NAME="$OPTARG" ;;
316 h) usage ; bailout 0 ;;
317 i) ISO_NAME="$OPTARG" ;;
318 I) CHROOT_INSTALL="$OPTARG" ;;
320 N) BOOTSTRAP_ONLY=1; SKIP_MKISOFS=1; SKIP_MKSQUASHFS=1 ;;
321 o) OUTPUT="$(readlink -f $OPTARG)" ;;
322 q) SKIP_MKSQUASHFS=1 ;;
324 r) RELEASENAME="$OPTARG" ;;
325 s) SUITE="$OPTARG" ;;
326 t) TEMPLATE_DIRECTORY="$OPTARG";;
327 v) VERSION="$OPTARG" ;;
330 U) CHOWN_USER="$OPTARG" ;;
332 z) SQUASHFS_ZLIB=1 ;;
333 ?) echo "invalid option -$OPTARG" >&2; bailout 1 ;;
336 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
339 # read local (non-packaged) configuration {{{
340 if [ -z "$LOCAL_CONFIG" ]; then
341 if [ -r "/etc/grml/grml-live.local" ]; then
342 LOCAL_CONFIG="/etc/grml/grml-live.local"
345 if [ -n "$LOCAL_CONFIG" ]; then
346 if [ -r "$LOCAL_CONFIG" ]; then
349 eerror "Could not read specified local configuration file \"$LOCAL_CONFIG\"."
352 LOCAL_CONFIG=$(readlink -f "$LOCAL_CONFIG")
357 if [ -n "${GRML_LIVE_SOURCES:-}" ] ; then
358 eerror "Config variable \$GRML_LIVE_SOURCES is set. This variable has been deprecated."
359 ewarn "Please set up \${GRML_FAI_CONFIG}/config/files/etc/apt/sources.list.d/* instead."
364 # assume sane defaults (if not set already) {{{
365 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
366 [ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux'
367 [ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_FULL,$(echo ${ARCH} | tr 'a-z' 'A-Z')"
368 [ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)"
369 [ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators'
370 [ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml"
371 [ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png'
372 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
373 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai'
374 [ -n "$GRML_NAME" ] || GRML_NAME='grml'
375 [ -n "$HOSTNAME" ] || HOSTNAME='grml'
376 [ -n "$HYBRID_METHOD" ] || HYBRID_METHOD='isohybrid'
377 [ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks'
378 [ -n "$SQUASHFS_EXCLUDES_FILE" ] || SQUASHFS_EXCLUDES_FILE="${GRML_FAI_CONFIG}/config/grml/squashfs-excludes"
379 [ -n "$SUITE" ] || SUITE='testing'
380 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
381 [ -n "$USERNAME" ] || USERNAME='grml'
382 [ -n "$VERSION" ] || VERSION='0.0.1'
384 # output specific stuff, depends on $OUTPUT (iff not set):
385 [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live'
386 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
387 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
388 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
389 [ -n "$LOG_OUTPUT" ] || LOG_OUTPUT="$OUTPUT/grml_logs"
390 [ -n "$REPORTS" ] || REPORTS="${LOG_OUTPUT}/reports/"
391 [ -n "$NETBOOT" ] || NETBOOT="${OUTPUT}/netboot/"
394 # some misc checks before executing FAI {{{
395 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
396 specify it on the command line using the -c option."
397 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
398 specify it on the command line using the -o option."
400 # trim characters that are known to cause problems inside $GRML_NAME;
401 # for example isolinux does not like '-' inside the directory name
402 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
404 # export variables to have them available in fai scripts:
405 [ -n "$GRML_NAME" ] && export GRML_NAME="$GRML_NAME"
406 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
409 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
410 # this was default behaviour until grml-live 0.9.34:
411 if [ -n "$ZERO_LOGFILE" ] ; then
412 PRESERVE_LOGFILE='' # make sure it's cleaned then
413 ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
414 ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
419 # ask user whether the setup is ok {{{
420 if [ -z "$FORCE" ] ; then
422 echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
424 echo " FAI classes: $CLASSES"
425 [ -n "$LOCAL_CONFIG" ] && echo " Configuration: $LOCAL_CONFIG"
426 [ -n "$GRML_FAI_CONFIG" ] && echo " Config directory: $GRML_FAI_CONFIG"
427 echo " main directory: $OUTPUT"
428 [ -n "$EXTRACT_ISO_NAME" ] && echo " Extract ISO: $EXTRACT_ISO_NAME"
429 [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT"
430 [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT"
431 [ -n "$ISO_OUTPUT" ] && echo " ISO target: $ISO_OUTPUT"
432 [ -n "$GRML_NAME" ] && echo " Grml name: $GRML_NAME"
433 [ -n "$RELEASENAME" ] && echo " Release name: $RELEASENAME"
434 [ -n "$DATE" ] && echo " Build date: $DATE"
435 [ -n "$VERSION" ] && echo " Grml version: $VERSION"
436 [ -n "$SUITE" ] && echo " Debian suite: $SUITE"
437 [ -n "$ARCH" ] && echo " Architecture: $ARCH"
438 [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD"
439 [ -n "$HYBRID_METHOD" ] && echo " Hybrid method: $HYBRID_METHOD"
440 [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY"
441 [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL"
442 [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID"
443 [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature."
444 [ -n "$CHOWN_USER" ] && echo " Output owner: $CHOWN_USER"
445 [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
446 [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS"
447 [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE"
448 [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA/XZ) compression."
449 [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
450 [ -n "$VERBOSE" ] && echo " Using VERBOSE mode."
451 [ -n "$CLEAN_ARTIFACTS" ] && echo " Will clean output before and after running."
452 [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation."
453 if [ -n "$BOOTSTRAP_ONLY" ] ; then
454 echo " Bootstrapping only and not building (files for) ISO."
456 [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file."
457 [ -n "$SKIP_NETBOOT" ] && echo " Skipping creation of NETBOOT package."
458 [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file."
459 [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE."
460 [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched."
463 echo -n "Is this ok for you? [y/N] "
465 if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
467 bailout 1 "Exiting as requested."
473 # clean up before start {{{
474 if [ -n "${CLEAN_ARTIFACTS}" ]; then
475 echo "Wiping old artifacts"
476 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
477 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
478 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && rm -r "${ISO_OUTPUT}"
479 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && rm -r "${LOG_OUTPUT}"
480 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && rm -r "${NETBOOT}"
484 # create log file {{{
485 [ -n "$LOGFILE" ] || LOGFILE=${LOG_OUTPUT}/grml-live.log
486 mkdir -p $(dirname "${LOGFILE}")
488 chown root:adm $LOGFILE
492 # clean/zero/remove logfiles {{{
494 if [ -n "$PRESERVE_LOGFILE" ] ; then
495 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
497 # make sure it is empty (as it is e.g. appended to grml-live-db)
501 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
502 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
503 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
504 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
505 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
506 rm -f /var/log/fai/"$HOSTNAME"/last \
507 /var/log/fai/"$HOSTNAME"/last-dirinstall \
508 /var/log/fai/"$HOSTNAME"/last-softupdate
513 # source config and startup {{{
514 if [ -n "$CONFIG" ] ; then
515 if ! [ -f "$CONFIG" ] ; then
516 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
517 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
520 log "Sourcing $CONFIG"
525 start_seconds=$(cut -d . -f 1 /proc/uptime)
526 log "------------------------------------------------------------------------------"
527 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
528 log "Using local config file: $LOCAL_CONFIG"
529 log "Executed grml-live command line:"
532 einfo "Logging actions to logfile $LOGFILE"
535 # dump config variables into file, for script access {{{
538 '^(GRML_NAME|RELEASENAME|DATE|VERSION|SUITE|ARCH|DISTRI_NAME|USERNAME|HOSTNAME|APT_PROXY)=' \
542 # unpack iso/squashfs {{{
544 if [ -n "$EXTRACT_ISO_NAME" ]; then
545 log "Unpacking ISO from ${EXTRACT_ISO_NAME}"
546 einfo "Unpacking ISO from ${EXTRACT_ISO_NAME}"
547 local mountpoint=$(mktemp -d)
549 mount -o loop "${EXTRACT_ISO_NAME}" "$mountpoint" ; rc=$?
550 if [ "$rc" != 0 ]; then
553 eerror "mount failed"
558 if ls "${mountpoint}"/live/*/*.squashfs 2>/dev/null | grep -q . ; then # ISOs >=2011.12
559 log "Using ${mountpoint}/live/*/*.squashfs for unsquashfs"
560 unsquashfs -d "${CHROOT_OUTPUT}" "${mountpoint}"/live/*/*.squashfs ; rc=$?
561 elif ls "${mountpoint}"/live/*.squashfs 2>/dev/null | grep -q . ; then # ISOs before 2011.12
562 log "Using ${mountpoint}/live/*.squashfs for unsquashfs"
563 unsquashfs -d "${CHROOT_OUTPUT}" "${mountpoint}"/live/*.squashfs ; rc=$?
565 log "Error: Could not find any *.squashfs files on the ISO"
566 eerror "Error: Could not find any *.squashfs files on the ISO"
573 if [ "$rc" != 0 ]; then
574 log "unsquashfs failed"
575 eerror "unsquashfs failed"
584 # on-the-fly configuration {{{
586 # does this suck? YES!
587 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
589 unstable) SUITE='sid' ; CLASSES="DEBIAN_UNSTABLE,$CLASSES" ;;
590 *) CLASSES="DEBIAN_$(echo $SUITE | tr 'a-z' 'A-Z'),$CLASSES";;
592 export SUITE # make sure it's available in FAI scripts
594 # validate whether the specified architecture class matches the
595 # architecture (option), otherwise installation of kernel will fail
596 if echo $CLASSES | grep -qw I386 ; then
597 if ! [[ "$ARCH" == "i386" ]] ; then
598 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
599 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
600 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
604 elif echo $CLASSES | grep -qi amd64 ; then
605 if ! [[ "$ARCH" == "amd64" ]] ; then
606 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
607 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
608 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
614 # generate nfsroot configuration for FAI on the fly
615 if [ -z "$FAI_DEBOOTSTRAP" ] ; then
616 FAI_DEBOOTSTRAP="$SUITE http://cdn.debian.net/debian"
619 if [ -z "$FAI_DEBOOTSTRAP_OPTS" ] ; then
620 FAI_DEBOOTSTRAP_OPTS="--exclude=info,tasksel,tasksel-data --arch $ARCH"
623 # create backup of old (not yet automatically generated) config file
624 if [ -f "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" ] ; then
625 if ! grep -q 'This is an automatically generated file by grml-live' "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" ; then
626 ewarn "Found old ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf - moving to ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf.outdated"
627 mv "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf.outdated"
632 echo "# This is an automatically generated file by grml-live.
633 # Do NOT edit this file, your changes will be lost.
634 FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"
635 FAI_DEBOOTSTRAP_OPTS=\"$FAI_DEBOOTSTRAP_OPTS\"
636 # EOF " > "${GRML_FAI_CONFIG}/nfsroot.conf"
637 # support FAI <=3.4.8, versions >=4.0 use nfsroot.conf
638 ( cd ${GRML_FAI_CONFIG} && ln -sf nfsroot.conf make-fai-nfsroot.conf )
641 # CHROOT_OUTPUT - execute FAI {{{
642 if [ -n "$BUILD_DIRTY" ]; then
643 log "Skipping stage 'fai' as requested via option -B"
644 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
646 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
648 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
649 FAI_ACTION=softupdate
651 FAI_ACTION=dirinstall
654 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
655 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
656 log "Error: does not look like you have a working chroot. Updating/building not possible."
657 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
663 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
664 log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
665 ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
667 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
669 if [ -n "${MIRROR_DIRECTORY}" ] ; then
670 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
671 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
674 mkdir -p "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
675 mount --bind "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
677 log "Executed FAI command line:"
678 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"
679 BUILD_ONLY="$BUILD_ONLY" BOOTSTRAP_ONLY="$BOOTSTRAP_ONLY" GRML_LIVE_CONFIG="$CONFIGDUMP" fai $VERBOSE \
680 -C "$GRML_FAI_CONFIG" -s "file:///$GRML_FAI_CONFIG/config" -c"$CLASSES" \
681 -u "$HOSTNAME" "$FAI_ACTION" "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
682 RC="$PIPESTATUS" # notice: bash-only
684 # provide inform fai about the ISO we build, needs to be provided
685 # *after* FAI stage, otherwise FAI skips the debootstrap stage if
686 # there is not BASEFILE (as it checks for presence of /etc) :(
687 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
688 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
689 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
691 FORCE_ISO_REBUILD=true
693 if [ "$RC" != 0 ] ; then
694 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
695 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
699 # move fai logs into grml_logs directory
700 mkdir -p "$LOG_OUTPUT"/fai/
701 cp -r "$CHROOT_OUTPUT"/var/log/fai/"$HOSTNAME"/last/* "$LOG_OUTPUT"/fai/
702 rm -rf "$CHROOT_OUTPUT"/var/log/fai
704 # store copy of autogenerated configuration file
705 cp ${GRML_FAI_CONFIG}/nfsroot.conf "$LOG_OUTPUT"/fai/
707 # copy fai package list
708 cp "$CHROOT_OUTPUT"/var/log/install_packages.list "$LOG_OUTPUT"/fai/
710 chown root:adm "$LOG_OUTPUT"/fai/*
711 chmod 664 "$LOG_OUTPUT"/fai/*
715 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
717 CHECKLOG="$LOG_OUTPUT"/fai/
718 if [ -r "$CHECKLOG/software.log" ] ; then
719 # 1 errors during executing of commands
720 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
721 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
722 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
723 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
724 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
727 if [ -r "$CHECKLOG/shell.log" ] ; then
728 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
731 if [ -n "$ERROR" ] ; then
732 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
733 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
734 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
738 log "Finished execution of stage 'fai dirinstall' [$(date)]"
739 einfo "Finished execution of stage 'fai dirinstall'"
745 # package validator {{{
746 CHECKLOG=/var/log/fai/$HOSTNAME/last
747 if [ -r "$CHECKLOG/dpkg.selections" ] ; then
748 package_count=$(wc -l "$CHECKLOG/dpkg.selections" | awk '{print $1}')
750 package_count="unknown"
754 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
756 # check for missing packages
757 if ! [ -s "$CHECKLOG/package_errors.log" ] ; then
758 einfo "No missing packages found, generating empty junit report."
760 cat > "${REPORT_MISSING_PACKAGES}" << EOF
761 <?xml version="1.0" encoding="UTF-8"?>
762 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="0" errors="0" skipped="0" assertions="0">
763 <testcase name="test_missing_packages" time="0" assertions="0">
773 einfo "Missing packages found, generating junit report."
775 if [ -r "$CHECKLOG/package_errors.log" ] ; then
776 package_errors=$(wc -l "$CHECKLOG/package_errors.log" | awk '{print $1}')
778 package_errors="unknown"
782 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
784 cat > "${REPORT_MISSING_PACKAGES}" << EOF
785 <?xml version="1.0" encoding="UTF-8"?>
786 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="${package_errors}" errors="${package_errors}" skipped="0" assertions="0">
789 for package in $(awk '{print $1}' "${CHECKLOG}/package_errors.log") ; do
790 failure_reason="$(awk "/$package/ {print \$2}" "${CHECKLOG}/package_errors.log")"
791 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
792 <testcase name="test_missing_packages_${package}" time="0" assertions="0">
793 <failure type="${failure_reason}" message="Package ${package} is missing">
794 Package $package is missing in chroot (${failure_reason})
800 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
809 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
810 eerror "The following packages were requested for installation but could not be processed:"
811 cat "$CHECKLOG/package_errors.log"
812 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
816 ewarn "The following packages were requested for installation but could not be processed:"
817 cat "$CHECKLOG/package_errors.log"
823 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
824 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
825 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
828 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
829 if [ -n "$BOOTSTRAP_ONLY" ] ; then
830 log "Skipping stage 'boot' as building with bootstrap only."
831 ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0
833 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
834 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
835 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
838 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
839 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
841 # if we don't have an initrd we a) can't boot and b) there was an error
842 # during build, so check for the file:
843 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
844 if [ -n "$INITRD" ] ; then
845 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.img
846 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
848 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
849 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
853 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
854 if [ -n "$KERNEL_IMAGE" ] ; then
855 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/vmlinuz
857 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
858 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
863 if [ -r "${CHROOT_OUTPUT}/boot/efi.img" -a -r "${CHROOT_OUTPUT}/boot/bootx64.efi" ] ; then
864 einfo "Moving EFI boot files into ISO path."
865 log "Moving EFI boot files into ISO path."
867 mv "${CHROOT_OUTPUT}/boot/efi.img" "${BUILD_OUTPUT}/boot/" || RC=$?
868 mkdir -p "${BUILD_OUTPUT}/efi/boot/" || RC=$?
869 mv "${CHROOT_OUTPUT}/boot/bootx64.efi" "${BUILD_OUTPUT}/efi/boot/bootx64.efi" || RC=$?
873 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
874 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
875 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
876 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
880 # copy _required_ isolinux files
881 for file in ifcpu64.c32 isolinux.bin vesamenu.c32; do
882 copy_addon_file "${file}" /usr/lib/syslinux isolinux
885 # *always* copy files to output directory so the variables
886 # get adjusted according to the build.
887 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
889 if [ -n "$NO_ADDONS" ] ; then
890 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
891 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
893 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
894 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
895 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
897 # copy addons from system packages or grml-live-compat
898 copy_addon_file ipxe.lkrn /usr/lib/ipxe addons
899 copy_addon_file pci.ids /usr/share/misc addons
900 copy_addon_file memtest86+.bin /boot addons
901 for file in memdisk chain.c32 hdt.c32 mboot.c32 menu.c32; do
902 copy_addon_file "${file}" /usr/lib/syslinux addons
905 # make memtest filename FAT16/8.3 compatible
906 mv "${BUILD_OUTPUT}/boot/addons/memtest86+.bin" \
907 "${BUILD_OUTPUT}/boot/addons/memtest"
909 # copy only files so we can handle bsd4grml on its own
910 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
911 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
914 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
915 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
916 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
918 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
919 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
921 log "Missing addon file: bsd4grml"
922 ewarn "Missing addon file: bsd4grml" ; eend 0
926 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
929 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
930 mkdir -p "${BUILD_OUTPUT}/boot/grub"
932 cp -a ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
934 # generate loopback.cfg config file without depending on grub's regexp module
935 # which isn't available in Debian/squeeze
936 echo "## grub2 loopback configuration" > "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
937 echo "source /boot/grub/header.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
938 for config in "${BUILD_OUTPUT}"/boot/grub/*_default.cfg "${BUILD_OUTPUT}"/boot/grub/*_options.cfg ; do
939 [ -r "$config" ] || continue
940 echo "source ${config##$BUILD_OUTPUT}" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
942 echo "source /boot/grub/addons.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
943 echo "source /boot/grub/footer.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
945 # copy grub files from target
946 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.mod "${BUILD_OUTPUT}"/boot/grub/
947 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.o "${BUILD_OUTPUT}"/boot/grub/
948 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.lst "${BUILD_OUTPUT}"/boot/grub/
949 cp -a "${CHROOT_OUTPUT}"/usr/share/grub/ascii.pf2 "${BUILD_OUTPUT}"/boot/grub/
950 cp -a "${CHROOT_OUTPUT}"/boot/grub/core.img "${BUILD_OUTPUT}"/boot/grub/
951 cp -a "${CHROOT_OUTPUT}"/boot/grub/grub.img "${BUILD_OUTPUT}"/boot/grub/
953 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
954 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
955 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
959 mkdir -p "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
960 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
962 # adjust boot splash information:
963 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
964 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
965 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
967 if [ -r "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version ] ; then
968 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
969 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
972 # make sure the squashfs filename is set accordingly:
973 SQUASHFS_NAME="$GRML_NAME.squashfs"
975 if [ -n "$NO_BOOTID" ] ; then
976 log 'Skipping bootid feature as requested via $NO_BOOTID.'
977 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
979 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
980 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
981 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
982 log "Generating /conf/bootid.txt with entry ${BOOTID}."
983 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
987 # adjust all variables in the templates with the according distribution information
988 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
989 "${BUILD_OUTPUT}"/boot/grub/* ; do
990 if [ -r "${file}" ] && [ -f "${file}" ] ; then
991 sed -i "s/%ARCH%/$ARCH/g" "${file}"
992 sed -i "s/%DATE%/$DATE/g" "${file}"
993 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
994 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
995 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
996 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
997 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
998 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
999 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
1000 sed -i "s/%VERSION%/$VERSION/g" "${file}"
1002 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s; boot=live; boot=live $DEFAULT_BOOTOPTIONS;" "${file}"
1004 if [ -n "$NO_BOOTID" ] ; then
1005 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
1007 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
1012 for param in ARCH DATE DISTRI_INFO DISTRI_NAME DISTRI_SPLASH GRML_NAME SQUASHFS_NAME \
1013 RELEASE_INFO SHORT_NAME VERSION ; do
1014 for file in $(find "${BUILD_OUTPUT}" -name "*%$param%*") ; do
1015 value="$(eval echo '$'"$param")"
1016 mv ${file} ${file/\%${param}\%/$value}
1020 # adjust bootsplash accordingly but make sure the string has the according lenght
1021 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
1022 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
1023 for file in f4 f5 ; do
1024 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
1025 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
1026 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
1030 # generate addon list
1031 rm -f "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
1032 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
1033 include_name=$(basename "$name")
1034 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
1037 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
1038 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1039 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1040 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1041 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1042 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1044 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
1045 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1048 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1049 if [ ! -n "$NO_ADDONS" ] ; then
1050 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1052 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1053 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1054 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1055 else # assume we are building a custom distribution:
1056 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
1057 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
1058 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1059 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1061 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1065 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1066 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1067 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1071 # use old style console based isolinux method only if requested:
1072 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
1073 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1074 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1075 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1076 einfo "include for console.cfg already found, nothing to do."
1079 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1080 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1081 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1085 log 'Using graphical boot menu.'
1086 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
1087 log "include for vesamenu.cfg already found, nothing to do."
1089 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1090 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1094 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
1095 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
1098 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
1099 if ! [ -r "$DPKG_LIST" ] ; then
1100 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
1102 einfo "Storing package list information as /GRML/${GRML_NAME}/packages.txt on ISO."
1103 cp "$DPKG_LIST" "${BUILD_OUTPUT}"/GRML/"${GRML_NAME}"/packages.txt
1107 # autostart for Windows:
1108 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
1109 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
1112 FORCE_ISO_REBUILD=true
1113 einfo "Finished execution of stage 'boot'" ; eend 0
1117 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
1118 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
1122 # support installation of local files into the chroot/ISO
1123 if [ -n "$CHROOT_INSTALL" ] ; then
1124 if ! [ -d "$CHROOT_INSTALL" ] ; then
1125 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1126 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1128 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1129 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1130 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
1132 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
1133 FORCE_ISO_REBUILD=true
1137 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1138 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
1139 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
1140 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
1141 log "Skipping stage 'squashfs' as requested via option -q or -N"
1142 ewarn "Skipping stage 'squashfs' as requested via option -q or -N" ; eend 0
1144 mkdir -p "$BUILD_OUTPUT"/live/"${GRML_NAME}"/
1145 # make sure we don't leave (even an empty) base.tgz:
1146 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
1148 # if unconfigured default to squashfs-tools' mksquashfs binary
1149 if [ -z "$SQUASHFS_BINARY" ] ; then
1150 SQUASHFS_BINARY='mksquashfs'
1153 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
1154 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
1155 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
1157 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
1158 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
1162 # use sane defaults if $SQUASHFS_OPTIONS isn't set
1163 if [ -z "$SQUASHFS_OPTIONS" ] ; then
1164 # use blocksize 256k as this gives best result with regards to time + compression
1165 SQUASHFS_OPTIONS="-b 256k"
1167 # set lzma/xz compression by default, unless -z option has been specified on command line
1168 if [ -z "$SQUASHFS_ZLIB" ] ; then
1169 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
1171 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
1175 # support exclusion of files via exclude-file:
1176 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
1177 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE -wildcards"
1180 # get rid of unnecessary files when building grml-small for final release:
1181 if echo "$CLASSES" | grep -q GRML_SMALL ; then
1182 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
1186 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
1188 # informational stuff
1189 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1190 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1191 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1193 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/${GRML_NAME}/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1195 if $SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/"${GRML_NAME}"/"${GRML_NAME}".squashfs \
1196 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1197 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/"${GRML_NAME}"/filesystem.module
1198 log "Finished execution of stage 'squashfs' [$(date)]"
1199 einfo "Finished execution of stage 'squashfs'" ; eend 0
1201 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1202 log "$(cat $SQUASHFS_STDERR)"
1203 eerror "Error: there was a critical error executing stage 'squashfs':"
1204 cat "${SQUASHFS_STDERR}"
1209 FORCE_ISO_REBUILD=true
1212 # create md5sum file:
1213 if [ -z "$BOOTSTRAP_ONLY" ] ; then
1214 ( cd $BUILD_OUTPUT/GRML/"${GRML_NAME}" &&
1215 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1219 # ISO_OUTPUT - mkisofs {{{
1220 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1221 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1223 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1224 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1225 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1226 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1229 # Work around http://bts.grml.org/grml/issue945
1230 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1231 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1232 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1233 HYBRID_METHOD='grub2'
1237 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1238 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1239 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1240 elif [ -n "$SKIP_MKISOFS" ] ; then
1241 log "Skipping stage 'iso build' as requested via option -n or -N"
1242 ewarn "Skipping stage 'iso build' as requested via option -n or -N" ; eend 0
1244 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1246 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1247 log "Forcing rebuild of ISO because files on ISO have been modified."
1248 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1251 # support xorriso as well mkisofs and genisoimage
1252 if which xorriso >/dev/null 2>&1 ; then
1253 MKISOFS='xorriso -as mkisofs'
1254 elif which mkisofs >/dev/null 2>&1; then
1256 elif which genisoimage >/dev/null 2>&1; then
1257 MKISOFS='genisoimage'
1259 log "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO."
1260 eerror "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO." ; eend 1
1264 einfo "Using ${MKISOFS} to build ISO." ; eend 0
1265 case "${ARCH}-${MKISOFS}" in
1266 # using -eltorito-alt-boot is limited to xorriso for now
1270 if ! dpkg --compare-versions $(dpkg-query -W -f='${Version}\n' xorriso 2>/dev/null) gt-nl 1.1.6-1 ; then
1271 log "Disabling (U)EFI boot support because xorriso version is too old."
1272 ewarn "Disabling (U)EFI boot support because xorriso version is too old." ; eend 0
1274 if [ -r "${BUILD_OUTPUT}"/boot/efi.img ] ; then
1275 einfo "Enabling (U)EFI boot."
1276 log "Enabling (U)EFI boot."
1277 BOOT_ARGS="$BOOT_ARGS -boot-info-table -eltorito-alt-boot -e boot/efi.img -no-emul-boot"
1280 log "Disabling (U)EFI boot support because /boot/efi.img is missing."
1281 ewarn "Disabling (U)EFI boot support because /boot/efi.img is missing." ; eend 0
1290 if cd "$BUILD_OUTPUT" ; then
1291 if [ "$BOOT_METHOD" = "grub2" ]; then
1292 # make a 2048-byte bootsector for El Torito
1293 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1294 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1295 echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
1296 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1298 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1299 $MKISOFS -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1300 -l -r -J $BOOT_ARGS -no-pad \
1301 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1302 # both of these need core.img there, so it’s easier to write it here
1303 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1304 # must be <= 30720 bytes
1305 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1306 conv=notrunc bs=512 seek=4 2>/dev/null
1309 # pad the output ISO to multiples of 256 KiB for partition table support
1310 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1311 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1312 siz=$((cyls * 16 * 32 * 512)) # size after padding
1313 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1314 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1316 # support disabling hybrid ISO image
1317 if [ "$HYBRID_METHOD" = "disable" ] ; then
1318 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1319 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1321 elif [ "$HYBRID_METHOD" = "manifold" ] || [ "$HYBRID_METHOD" = "grub2" ] ; then
1322 # isoinfo is part of both mkisofs and genisoimage so we're good
1323 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1324 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN[;1]* *$/s//\1/p')
1326 if ! [ -r boot/grub/core.img ] ; then
1327 log "boot/grub/core.img not found, not creating manifold boot ISO file"
1328 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1329 elif [ "${bootoff:-0}" -lt 1 ] ; then
1330 log "isolinux.bin not found on the ISO file, disabling manifold boot"
1331 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1333 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1334 log "Creating hybrid ISO file with manifold/grub2 method"
1335 einfo "Creating hybrid ISO file with manifold/grub2 method"
1336 # 512 bytes: MBR, partition table, load GRUB 2
1337 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1339 log "Creating hybrid ISO file with manifold method"
1340 einfo "Creating hybrid ISO file with manifold method"
1341 # read only one but 2048-byte sized (scale: << 2) sector
1342 echo $bootoff $bootoff | \
1343 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1344 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1347 elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
1348 if ! which isohybrid >/dev/null 2>&1 ; then
1349 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1351 log "Creating hybrid ISO file with isohybrid method"
1352 einfo "Creating hybrid ISO file with isohybrid method"
1353 # Notes for consideration:
1354 # "-entry 4 -type 1c"
1355 # * using 4 as the partition number is supposed to help with BIOSes
1356 # that only support USB-Zip boot
1357 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1358 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1359 # to get the BIOS even look at the partition created by isohybrid
1360 if isohybrid --help | grep -q -- --uefi ; then
1361 if echo $CLASSES | grep -qw I386 ; then
1362 log "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring."
1363 einfo "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring."
1365 log "Detected uefi support for isohybrid, enabling"
1366 einfo "Detected uefi support for isohybrid, enabling"
1367 ISOHYBRID_OPTIONS=--uefi
1371 log "isohybrid $ISOHYBRID_OPTIONS ${ISO_OUTPUT}/${ISO_NAME}"
1372 isohybrid $ISOHYBRID_OPTIONS "${ISO_OUTPUT}/${ISO_NAME}"
1376 bailout 12 "Unknown HYBRID_METHOD [${HYBRID_METHOD}]. Supported values: disable, isohybrid, grub2, manifold"
1379 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1380 case $CLASSES in *RELEASE*)
1383 if cd $ISO_OUTPUT ; then
1384 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1385 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1386 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1387 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1396 if [ "$RC" = 0 ] ; then
1397 log "Finished execution of stage 'iso build' [$(date)]"
1398 einfo "Finished execution of stage 'iso build'" ; eend 0
1400 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1401 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1407 # netboot package {{{
1408 create_netbootpackage() {
1409 local OUTPUT_FILE="${NETBOOT}/grml_netboot_package_${GRML_NAME}_${VERSION}.tar.bz2"
1411 if [ -f "${OUTPUT_FILE}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1412 log "Skipping stage 'netboot' as $OUTPUT_FILE exists already."
1413 ewarn "Skipping stage 'netboot' as $OUTPUT_FILE exists already." ; eend 0
1415 elif [ -n "$SKIP_NETBOOT" ] ; then
1416 log "Skipping stage 'netboot' as requested via option -Q"
1417 ewarn "Skipping stage 'netboot' as requested via option -Q" ; eend 0
1423 if ! [ -r "${CHROOT}/usr/lib/syslinux/pxelinux.0" ] ; then
1424 ewarn "File /usr/lib/syslinux/pxelinux.0 not found in build chroot." ; eend 0
1426 einfo "Install syslinux[-common] package in chroot to get a netboot package."
1431 local OUTPUTDIR="${NETBOOT}/build_tmp"
1432 local WORKING_DIR="${OUTPUTDIR}/grml_netboot_package_${GRML_NAME}_${VERSION}/tftpboot/"
1434 mkdir -p "$WORKING_DIR"
1436 cp "${CHROOT_OUTPUT}"/boot/vmlinuz-* "$WORKING_DIR"/vmlinuz
1437 cp "${CHROOT_OUTPUT}"/boot/initrd.img-* "$WORKING_DIR"/initrd.img
1438 cp "${CHROOT_OUTPUT}"/usr/lib/syslinux/pxelinux.0 "${WORKING_DIR}/pxelinux.0"
1440 mkdir -p "${WORKING_DIR}/pxelinux.cfg"
1441 if [ -r "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" ] ; then
1442 cp "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" "${WORKING_DIR}/pxelinux.cfg/default"
1444 log "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found."
1445 ewarn "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found."
1447 log "Hint: Are you using custom templates which do not provide netboot.cfg?"
1448 ewarn "Hint: Are you using custom templates which do not provide netboot.cfg?" ; eend 0
1452 if tar -C "$OUTPUTDIR" -jcf "${OUTPUT_FILE}" "grml_netboot_package_${GRML_NAME}_${VERSION}" ; then
1454 cd $(dirname "${OUTPUT_FILE}")
1455 sha1sum $(basename "${OUTPUT_FILE}") > "${OUTPUT_FILE}.sha1"
1457 einfo "Generated netboot package ${OUTPUT_FILE}" ; eend 0
1458 rm -rf "${OUTPUTDIR}"
1460 rm -rf "${OUTPUTDIR}"
1461 eerror "Could not generate netboot package ${OUTPUT_FILE}" ; eend 1
1466 create_netbootpackage
1469 # log build information to database if grml-live-db is installed and enabled {{{
1471 if [ -d /usr/share/grml-live-db ] ; then
1474 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1475 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1476 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1477 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1479 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1480 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1481 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1485 # disable by default for now, not sure whether really everyone is using a local db file
1486 #if ! touch "$DPKG_DATABASE" ; then
1487 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1491 if ! [ -r "$DPKG_LIST" ] ; then
1492 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1493 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1495 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1496 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1497 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1500 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1516 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1517 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1519 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1521 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1525 ## END OF FILE #################################################################
1526 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=2