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 echo "Exiting as requested."
474 # clean up before start {{{
475 if [ -n "${CLEAN_ARTIFACTS}" ]; then
476 echo "Wiping old artifacts"
477 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
478 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
479 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && rm -r "${ISO_OUTPUT}"
480 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && rm -r "${LOG_OUTPUT}"
481 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && rm -r "${NETBOOT}"
485 # create log file {{{
486 [ -n "$LOGFILE" ] || LOGFILE=${LOG_OUTPUT}/grml-live.log
487 mkdir -p $(dirname "${LOGFILE}")
489 chown root:adm $LOGFILE
493 # clean/zero/remove logfiles {{{
495 if [ -n "$PRESERVE_LOGFILE" ] ; then
496 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
498 # make sure it is empty (as it is e.g. appended to grml-live-db)
502 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
503 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
504 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
505 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
506 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
507 rm -f /var/log/fai/"$HOSTNAME"/last \
508 /var/log/fai/"$HOSTNAME"/last-dirinstall \
509 /var/log/fai/"$HOSTNAME"/last-softupdate
514 # source config and startup {{{
515 if [ -n "$CONFIG" ] ; then
516 if ! [ -f "$CONFIG" ] ; then
517 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
518 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
521 log "Sourcing $CONFIG"
526 start_seconds=$(cut -d . -f 1 /proc/uptime)
527 log "------------------------------------------------------------------------------"
528 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
529 log "Using local config file: $LOCAL_CONFIG"
530 log "Executed grml-live command line:"
533 einfo "Logging actions to logfile $LOGFILE"
536 # dump config variables into file, for script access {{{
539 '^(GRML_NAME|RELEASENAME|DATE|VERSION|SUITE|ARCH|DISTRI_NAME|USERNAME|HOSTNAME|APT_PROXY)=' \
543 # unpack iso/squashfs {{{
545 if [ -n "$EXTRACT_ISO_NAME" ]; then
546 log "Unpacking ISO from ${EXTRACT_ISO_NAME}"
547 einfo "Unpacking ISO from ${EXTRACT_ISO_NAME}"
548 local mountpoint=$(mktemp -d)
550 mount -o loop "${EXTRACT_ISO_NAME}" "$mountpoint" ; rc=$?
551 if [ "$rc" != 0 ]; then
554 eerror "mount failed"
559 if ls "${mountpoint}"/live/*/*.squashfs 2>/dev/null | grep -q . ; then # ISOs >=2011.12
560 log "Using ${mountpoint}/live/*/*.squashfs for unsquashfs"
561 unsquashfs -d "${CHROOT_OUTPUT}" "${mountpoint}"/live/*/*.squashfs ; rc=$?
562 elif ls "${mountpoint}"/live/*.squashfs 2>/dev/null | grep -q . ; then # ISOs before 2011.12
563 log "Using ${mountpoint}/live/*.squashfs for unsquashfs"
564 unsquashfs -d "${CHROOT_OUTPUT}" "${mountpoint}"/live/*.squashfs ; rc=$?
566 log "Error: Could not find any *.squashfs files on the ISO"
567 eerror "Error: Could not find any *.squashfs files on the ISO"
574 if [ "$rc" != 0 ]; then
575 log "unsquashfs failed"
576 eerror "unsquashfs failed"
585 # on-the-fly configuration {{{
587 # does this suck? YES!
588 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
590 unstable) SUITE='sid' ; CLASSES="DEBIAN_UNSTABLE,$CLASSES" ;;
591 *) CLASSES="DEBIAN_$(echo $SUITE | tr 'a-z' 'A-Z'),$CLASSES";;
593 export SUITE # make sure it's available in FAI scripts
595 # validate whether the specified architecture class matches the
596 # architecture (option), otherwise installation of kernel will fail
597 if echo $CLASSES | grep -qw I386 ; then
598 if ! [[ "$ARCH" == "i386" ]] ; then
599 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
600 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
601 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
605 elif echo $CLASSES | grep -qi amd64 ; then
606 if ! [[ "$ARCH" == "amd64" ]] ; then
607 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
608 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
609 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
615 # generate nfsroot configuration for FAI on the fly
616 if [ -z "$FAI_DEBOOTSTRAP" ] ; then
617 FAI_DEBOOTSTRAP="$SUITE http://cdn.debian.net/debian"
620 if [ -z "$FAI_DEBOOTSTRAP_OPTS" ] ; then
621 FAI_DEBOOTSTRAP_OPTS="--exclude=info,tasksel,tasksel-data --arch $ARCH"
624 # create backup of old (not yet automatically generated) config file
625 if [ -f "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" ] ; then
626 if ! grep -q 'This is an automatically generated file by grml-live' "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" ; then
627 ewarn "Found old ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf - moving to ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf.outdated"
628 mv "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf.outdated"
633 echo "# This is an automatically generated file by grml-live.
634 # Do NOT edit this file, your changes will be lost.
635 FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"
636 FAI_DEBOOTSTRAP_OPTS=\"$FAI_DEBOOTSTRAP_OPTS\"
637 # EOF " > "${GRML_FAI_CONFIG}/nfsroot.conf"
638 # support FAI <=3.4.8, versions >=4.0 use nfsroot.conf
639 ( cd ${GRML_FAI_CONFIG} && ln -sf nfsroot.conf make-fai-nfsroot.conf )
642 # CHROOT_OUTPUT - execute FAI {{{
643 if [ -n "$BUILD_DIRTY" ]; then
644 log "Skipping stage 'fai' as requested via option -B"
645 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
647 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
649 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
650 FAI_ACTION=softupdate
652 FAI_ACTION=dirinstall
655 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
656 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
657 log "Error: does not look like you have a working chroot. Updating/building not possible."
658 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
664 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
665 log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
666 ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
668 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
670 if [ -n "${MIRROR_DIRECTORY}" ] ; then
671 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
672 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
675 mkdir -p "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
676 mount --bind "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
678 log "Executed FAI command line:"
679 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"
680 BUILD_ONLY="$BUILD_ONLY" BOOTSTRAP_ONLY="$BOOTSTRAP_ONLY" GRML_LIVE_CONFIG="$CONFIGDUMP" fai $VERBOSE \
681 -C "$GRML_FAI_CONFIG" -s "file:///$GRML_FAI_CONFIG/config" -c"$CLASSES" \
682 -u "$HOSTNAME" "$FAI_ACTION" "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
683 RC="$PIPESTATUS" # notice: bash-only
685 # provide inform fai about the ISO we build, needs to be provided
686 # *after* FAI stage, otherwise FAI skips the debootstrap stage if
687 # there is not BASEFILE (as it checks for presence of /etc) :(
688 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
689 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
690 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
692 FORCE_ISO_REBUILD=true
694 if [ "$RC" != 0 ] ; then
695 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
696 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
700 # move fai logs into grml_logs directory
701 mkdir -p "$LOG_OUTPUT"/fai/
702 cp -r "$CHROOT_OUTPUT"/var/log/fai/"$HOSTNAME"/last/* "$LOG_OUTPUT"/fai/
703 rm -rf "$CHROOT_OUTPUT"/var/log/fai
705 # store copy of autogenerated configuration file
706 cp ${GRML_FAI_CONFIG}/nfsroot.conf "$LOG_OUTPUT"/fai/
708 # copy fai package list
709 cp "$CHROOT_OUTPUT"/var/log/install_packages.list "$LOG_OUTPUT"/fai/
711 chown root:adm "$LOG_OUTPUT"/fai/*
712 chmod 664 "$LOG_OUTPUT"/fai/*
716 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
718 CHECKLOG="$LOG_OUTPUT"/fai/
719 if [ -r "$CHECKLOG/software.log" ] ; then
720 # 1 errors during executing of commands
721 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
722 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
723 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
724 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
725 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
728 if [ -r "$CHECKLOG/shell.log" ] ; then
729 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
732 if [ -n "$ERROR" ] ; then
733 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
734 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
735 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
739 log "Finished execution of stage 'fai dirinstall' [$(date)]"
740 einfo "Finished execution of stage 'fai dirinstall'"
746 # package validator {{{
747 CHECKLOG=/var/log/fai/$HOSTNAME/last
748 if [ -r "$CHECKLOG/dpkg.selections" ] ; then
749 package_count=$(wc -l "$CHECKLOG/dpkg.selections" | awk '{print $1}')
751 package_count="unknown"
755 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
757 # check for missing packages
758 if ! [ -s "$CHECKLOG/package_errors.log" ] ; then
759 einfo "No missing packages found, generating empty junit report."
761 cat > "${REPORT_MISSING_PACKAGES}" << EOF
762 <?xml version="1.0" encoding="UTF-8"?>
763 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="0" errors="0" skipped="0" assertions="0">
764 <testcase name="test_missing_packages" time="0" assertions="0">
774 einfo "Missing packages found, generating junit report."
776 if [ -r "$CHECKLOG/package_errors.log" ] ; then
777 package_errors=$(wc -l "$CHECKLOG/package_errors.log" | awk '{print $1}')
779 package_errors="unknown"
783 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
785 cat > "${REPORT_MISSING_PACKAGES}" << EOF
786 <?xml version="1.0" encoding="UTF-8"?>
787 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="${package_errors}" errors="${package_errors}" skipped="0" assertions="0">
790 for package in $(awk '{print $1}' "${CHECKLOG}/package_errors.log") ; do
791 failure_reason="$(awk "/$package/ {print \$2}" "${CHECKLOG}/package_errors.log")"
792 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
793 <testcase name="test_missing_packages_${package}" time="0" assertions="0">
794 <failure type="${failure_reason}" message="Package ${package} is missing">
795 Package $package is missing in chroot (${failure_reason})
801 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
810 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
811 eerror "The following packages were requested for installation but could not be processed:"
812 cat "$CHECKLOG/package_errors.log"
813 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
817 ewarn "The following packages were requested for installation but could not be processed:"
818 cat "$CHECKLOG/package_errors.log"
824 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
825 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
826 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
829 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
830 if [ -n "$BOOTSTRAP_ONLY" ] ; then
831 log "Skipping stage 'boot' as building with bootstrap only."
832 ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0
834 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
835 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
836 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
839 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
840 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
842 # if we don't have an initrd we a) can't boot and b) there was an error
843 # during build, so check for the file:
844 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
845 if [ -n "$INITRD" ] ; then
846 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.img
847 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
849 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
850 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
854 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
855 if [ -n "$KERNEL_IMAGE" ] ; then
856 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/vmlinuz
858 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
859 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
864 if [ -r "${CHROOT_OUTPUT}/boot/efi.img" -a -r "${CHROOT_OUTPUT}/boot/bootx64.efi" ] ; then
865 einfo "Moving EFI boot files into ISO path."
866 log "Moving EFI boot files into ISO path."
868 mv "${CHROOT_OUTPUT}/boot/efi.img" "${BUILD_OUTPUT}/boot/" || RC=$?
869 mkdir -p "${BUILD_OUTPUT}/efi/boot/" || RC=$?
870 mv "${CHROOT_OUTPUT}/boot/bootx64.efi" "${BUILD_OUTPUT}/efi/boot/bootx64.efi" || RC=$?
874 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
875 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
876 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
877 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
881 # copy _required_ isolinux files
882 for file in ifcpu64.c32 isolinux.bin vesamenu.c32; do
883 copy_addon_file "${file}" /usr/lib/syslinux isolinux
886 # *always* copy files to output directory so the variables
887 # get adjusted according to the build.
888 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
890 if [ -n "$NO_ADDONS" ] ; then
891 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
892 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
894 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
895 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
896 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
898 # copy addons from system packages or grml-live-compat
899 copy_addon_file ipxe.lkrn /usr/lib/ipxe addons
900 copy_addon_file pci.ids /usr/share/misc addons
901 copy_addon_file memtest86+.bin /boot addons
902 for file in memdisk chain.c32 hdt.c32 mboot.c32 menu.c32; do
903 copy_addon_file "${file}" /usr/lib/syslinux addons
906 # make memtest filename FAT16/8.3 compatible
907 mv "${BUILD_OUTPUT}/boot/addons/memtest86+.bin" \
908 "${BUILD_OUTPUT}/boot/addons/memtest"
910 # copy only files so we can handle bsd4grml on its own
911 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
912 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
915 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
916 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
917 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
919 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
920 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
922 log "Missing addon file: bsd4grml"
923 ewarn "Missing addon file: bsd4grml" ; eend 0
927 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
930 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
931 mkdir -p "${BUILD_OUTPUT}/boot/grub"
933 cp -a ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
935 # generate loopback.cfg config file without depending on grub's regexp module
936 # which isn't available in Debian/squeeze
937 echo "## grub2 loopback configuration" > "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
938 echo "source /boot/grub/header.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
939 for config in "${BUILD_OUTPUT}"/boot/grub/*_default.cfg "${BUILD_OUTPUT}"/boot/grub/*_options.cfg ; do
940 [ -r "$config" ] || continue
941 echo "source ${config##$BUILD_OUTPUT}" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
943 echo "source /boot/grub/addons.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
944 echo "source /boot/grub/footer.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
946 # copy grub files from target
947 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.mod "${BUILD_OUTPUT}"/boot/grub/
948 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.o "${BUILD_OUTPUT}"/boot/grub/
949 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.lst "${BUILD_OUTPUT}"/boot/grub/
950 cp -a "${CHROOT_OUTPUT}"/usr/share/grub/ascii.pf2 "${BUILD_OUTPUT}"/boot/grub/
951 cp -a "${CHROOT_OUTPUT}"/boot/grub/core.img "${BUILD_OUTPUT}"/boot/grub/
952 cp -a "${CHROOT_OUTPUT}"/boot/grub/grub.img "${BUILD_OUTPUT}"/boot/grub/
954 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
955 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
956 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
960 mkdir -p "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
961 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
963 # adjust boot splash information:
964 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
965 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
966 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
968 if [ -r "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version ] ; then
969 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
970 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
973 # make sure the squashfs filename is set accordingly:
974 SQUASHFS_NAME="$GRML_NAME.squashfs"
976 if [ -n "$NO_BOOTID" ] ; then
977 log 'Skipping bootid feature as requested via $NO_BOOTID.'
978 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
980 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
981 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
982 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
983 log "Generating /conf/bootid.txt with entry ${BOOTID}."
984 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
988 # adjust all variables in the templates with the according distribution information
989 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
990 "${BUILD_OUTPUT}"/boot/grub/* ; do
991 if [ -r "${file}" ] && [ -f "${file}" ] ; then
992 sed -i "s/%ARCH%/$ARCH/g" "${file}"
993 sed -i "s/%DATE%/$DATE/g" "${file}"
994 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
995 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
996 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
997 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
998 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
999 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
1000 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
1001 sed -i "s/%VERSION%/$VERSION/g" "${file}"
1003 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s; boot=live; boot=live $DEFAULT_BOOTOPTIONS;" "${file}"
1005 if [ -n "$NO_BOOTID" ] ; then
1006 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
1008 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
1013 for param in ARCH DATE DISTRI_INFO DISTRI_NAME DISTRI_SPLASH GRML_NAME SQUASHFS_NAME \
1014 RELEASE_INFO SHORT_NAME VERSION ; do
1015 for file in $(find "${BUILD_OUTPUT}" -name "*%$param%*") ; do
1016 value="$(eval echo '$'"$param")"
1017 mv ${file} ${file/\%${param}\%/$value}
1021 # adjust bootsplash accordingly but make sure the string has the according lenght
1022 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
1023 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
1024 for file in f4 f5 ; do
1025 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
1026 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
1027 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
1031 # generate addon list
1032 rm -f "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
1033 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
1034 include_name=$(basename "$name")
1035 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
1038 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
1039 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1040 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1041 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1042 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1043 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1045 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
1046 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1049 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1050 if [ ! -n "$NO_ADDONS" ] ; then
1051 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1053 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1054 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1055 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1056 else # assume we are building a custom distribution:
1057 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
1058 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
1059 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1060 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1062 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1066 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1067 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1068 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1072 # use old style console based isolinux method only if requested:
1073 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
1074 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1075 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1076 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1077 einfo "include for console.cfg already found, nothing to do."
1080 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1081 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1082 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1086 log 'Using graphical boot menu.'
1087 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
1088 log "include for vesamenu.cfg already found, nothing to do."
1090 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1091 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1095 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
1096 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
1099 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
1100 if ! [ -r "$DPKG_LIST" ] ; then
1101 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
1103 einfo "Storing package list information as /GRML/${GRML_NAME}/packages.txt on ISO."
1104 cp "$DPKG_LIST" "${BUILD_OUTPUT}"/GRML/"${GRML_NAME}"/packages.txt
1108 # autostart for Windows:
1109 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
1110 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
1113 FORCE_ISO_REBUILD=true
1114 einfo "Finished execution of stage 'boot'" ; eend 0
1118 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
1119 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
1123 # support installation of local files into the chroot/ISO
1124 if [ -n "$CHROOT_INSTALL" ] ; then
1125 if ! [ -d "$CHROOT_INSTALL" ] ; then
1126 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1127 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1129 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1130 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1131 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
1133 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
1134 FORCE_ISO_REBUILD=true
1138 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1139 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
1140 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
1141 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
1142 log "Skipping stage 'squashfs' as requested via option -q or -N"
1143 ewarn "Skipping stage 'squashfs' as requested via option -q or -N" ; eend 0
1145 mkdir -p "$BUILD_OUTPUT"/live/"${GRML_NAME}"/
1146 # make sure we don't leave (even an empty) base.tgz:
1147 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
1149 # if unconfigured default to squashfs-tools' mksquashfs binary
1150 if [ -z "$SQUASHFS_BINARY" ] ; then
1151 SQUASHFS_BINARY='mksquashfs'
1154 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
1155 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
1156 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
1158 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
1159 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
1163 # use sane defaults if $SQUASHFS_OPTIONS isn't set
1164 if [ -z "$SQUASHFS_OPTIONS" ] ; then
1165 # use blocksize 256k as this gives best result with regards to time + compression
1166 SQUASHFS_OPTIONS="-b 256k"
1168 # set lzma/xz compression by default, unless -z option has been specified on command line
1169 if [ -z "$SQUASHFS_ZLIB" ] ; then
1170 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
1172 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
1176 # support exclusion of files via exclude-file:
1177 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
1178 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE -wildcards"
1181 # get rid of unnecessary files when building grml-small for final release:
1182 if echo "$CLASSES" | grep -q GRML_SMALL ; then
1183 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
1187 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
1189 # informational stuff
1190 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1191 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1192 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1194 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/${GRML_NAME}/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1196 if $SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/"${GRML_NAME}"/"${GRML_NAME}".squashfs \
1197 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1198 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/"${GRML_NAME}"/filesystem.module
1199 log "Finished execution of stage 'squashfs' [$(date)]"
1200 einfo "Finished execution of stage 'squashfs'" ; eend 0
1202 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1203 log "$(cat $SQUASHFS_STDERR)"
1204 eerror "Error: there was a critical error executing stage 'squashfs':"
1205 cat "${SQUASHFS_STDERR}"
1210 FORCE_ISO_REBUILD=true
1213 # create md5sum file:
1214 if [ -z "$BOOTSTRAP_ONLY" ] ; then
1215 ( cd $BUILD_OUTPUT/GRML/"${GRML_NAME}" &&
1216 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1220 # ISO_OUTPUT - mkisofs {{{
1221 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1222 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1224 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1225 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1226 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1227 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1230 # Work around http://bts.grml.org/grml/issue945
1231 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1232 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1233 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1234 HYBRID_METHOD='grub2'
1238 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1239 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1240 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1241 elif [ -n "$SKIP_MKISOFS" ] ; then
1242 log "Skipping stage 'iso build' as requested via option -n or -N"
1243 ewarn "Skipping stage 'iso build' as requested via option -n or -N" ; eend 0
1245 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1247 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1248 log "Forcing rebuild of ISO because files on ISO have been modified."
1249 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1252 # support xorriso as well mkisofs and genisoimage
1253 if which xorriso >/dev/null 2>&1 ; then
1254 MKISOFS='xorriso -as mkisofs'
1255 elif which mkisofs >/dev/null 2>&1; then
1257 elif which genisoimage >/dev/null 2>&1; then
1258 MKISOFS='genisoimage'
1260 log "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO."
1261 eerror "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO." ; eend 1
1265 einfo "Using ${MKISOFS} to build ISO." ; eend 0
1266 case "${ARCH}-${MKISOFS}" in
1267 # using -eltorito-alt-boot is limited to xorriso for now
1271 if ! dpkg --compare-versions $(dpkg-query -W -f='${Version}\n' xorriso 2>/dev/null) gt-nl 1.1.6-1 ; then
1272 log "Disabling (U)EFI boot support because xorriso version is too old."
1273 ewarn "Disabling (U)EFI boot support because xorriso version is too old." ; eend 0
1275 if [ -r "${BUILD_OUTPUT}"/boot/efi.img ] ; then
1276 einfo "Enabling (U)EFI boot."
1277 log "Enabling (U)EFI boot."
1278 BOOT_ARGS="$BOOT_ARGS -boot-info-table -eltorito-alt-boot -e boot/efi.img -no-emul-boot"
1281 log "Disabling (U)EFI boot support because /boot/efi.img is missing."
1282 ewarn "Disabling (U)EFI boot support because /boot/efi.img is missing." ; eend 0
1291 if cd "$BUILD_OUTPUT" ; then
1292 if [ "$BOOT_METHOD" = "grub2" ]; then
1293 # make a 2048-byte bootsector for El Torito
1294 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1295 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1296 echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
1297 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1299 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1300 $MKISOFS -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1301 -l -r -J $BOOT_ARGS -no-pad \
1302 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1303 # both of these need core.img there, so it’s easier to write it here
1304 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1305 # must be <= 30720 bytes
1306 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1307 conv=notrunc bs=512 seek=4 2>/dev/null
1310 # pad the output ISO to multiples of 256 KiB for partition table support
1311 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1312 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1313 siz=$((cyls * 16 * 32 * 512)) # size after padding
1314 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1315 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1317 # support disabling hybrid ISO image
1318 if [ "$HYBRID_METHOD" = "disable" ] ; then
1319 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1320 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1322 elif [ "$HYBRID_METHOD" = "manifold" ] || [ "$HYBRID_METHOD" = "grub2" ] ; then
1323 # isoinfo is part of both mkisofs and genisoimage so we're good
1324 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1325 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN[;1]* *$/s//\1/p')
1327 if ! [ -r boot/grub/core.img ] ; then
1328 log "boot/grub/core.img not found, not creating manifold boot ISO file"
1329 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1330 elif [ "${bootoff:-0}" -lt 1 ] ; then
1331 log "isolinux.bin not found on the ISO file, disabling manifold boot"
1332 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1334 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1335 log "Creating hybrid ISO file with manifold/grub2 method"
1336 einfo "Creating hybrid ISO file with manifold/grub2 method"
1337 # 512 bytes: MBR, partition table, load GRUB 2
1338 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1340 log "Creating hybrid ISO file with manifold method"
1341 einfo "Creating hybrid ISO file with manifold method"
1342 # read only one but 2048-byte sized (scale: << 2) sector
1343 echo $bootoff $bootoff | \
1344 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1345 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1348 elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
1349 if ! which isohybrid >/dev/null 2>&1 ; then
1350 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1352 log "Creating hybrid ISO file with isohybrid method"
1353 einfo "Creating hybrid ISO file with isohybrid method"
1354 # Notes for consideration:
1355 # "-entry 4 -type 1c"
1356 # * using 4 as the partition number is supposed to help with BIOSes
1357 # that only support USB-Zip boot
1358 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1359 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1360 # to get the BIOS even look at the partition created by isohybrid
1361 if isohybrid --help | grep -q -- --uefi ; then
1362 if echo $CLASSES | grep -qw I386 ; then
1363 log "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring."
1364 einfo "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring."
1366 log "Detected uefi support for isohybrid, enabling"
1367 einfo "Detected uefi support for isohybrid, enabling"
1368 ISOHYBRID_OPTIONS=--uefi
1372 log "isohybrid $ISOHYBRID_OPTIONS ${ISO_OUTPUT}/${ISO_NAME}"
1373 isohybrid $ISOHYBRID_OPTIONS "${ISO_OUTPUT}/${ISO_NAME}"
1377 bailout 12 "Unknown HYBRID_METHOD [${HYBRID_METHOD}]. Supported values: disable, isohybrid, grub2, manifold"
1380 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1381 case $CLASSES in *RELEASE*)
1384 if cd $ISO_OUTPUT ; then
1385 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1386 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1387 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1388 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1397 if [ "$RC" = 0 ] ; then
1398 log "Finished execution of stage 'iso build' [$(date)]"
1399 einfo "Finished execution of stage 'iso build'" ; eend 0
1401 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1402 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1408 # netboot package {{{
1409 create_netbootpackage() {
1410 local OUTPUT_FILE="${NETBOOT}/grml_netboot_package_${GRML_NAME}_${VERSION}.tar.bz2"
1412 if [ -f "${OUTPUT_FILE}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1413 log "Skipping stage 'netboot' as $OUTPUT_FILE exists already."
1414 ewarn "Skipping stage 'netboot' as $OUTPUT_FILE exists already." ; eend 0
1416 elif [ -n "$SKIP_NETBOOT" ] ; then
1417 log "Skipping stage 'netboot' as requested via option -Q"
1418 ewarn "Skipping stage 'netboot' as requested via option -Q" ; eend 0
1424 if ! [ -r "${CHROOT}/usr/lib/syslinux/pxelinux.0" ] ; then
1425 ewarn "File /usr/lib/syslinux/pxelinux.0 not found in build chroot." ; eend 0
1427 einfo "Install syslinux[-common] package in chroot to get a netboot package."
1432 local OUTPUTDIR="${NETBOOT}/build_tmp"
1433 local WORKING_DIR="${OUTPUTDIR}/grml_netboot_package_${GRML_NAME}_${VERSION}/tftpboot/"
1435 mkdir -p "$WORKING_DIR"
1437 cp "${CHROOT_OUTPUT}"/boot/vmlinuz-* "$WORKING_DIR"/vmlinuz
1438 cp "${CHROOT_OUTPUT}"/boot/initrd.img-* "$WORKING_DIR"/initrd.img
1439 cp "${CHROOT_OUTPUT}"/usr/lib/syslinux/pxelinux.0 "${WORKING_DIR}/pxelinux.0"
1441 mkdir -p "${WORKING_DIR}/pxelinux.cfg"
1442 if [ -r "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" ] ; then
1443 cp "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" "${WORKING_DIR}/pxelinux.cfg/default"
1445 log "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found."
1446 ewarn "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found."
1448 log "Hint: Are you using custom templates which do not provide netboot.cfg?"
1449 ewarn "Hint: Are you using custom templates which do not provide netboot.cfg?" ; eend 0
1453 if tar -C "$OUTPUTDIR" -jcf "${OUTPUT_FILE}" "grml_netboot_package_${GRML_NAME}_${VERSION}" ; then
1455 cd $(dirname "${OUTPUT_FILE}")
1456 sha1sum $(basename "${OUTPUT_FILE}") > "${OUTPUT_FILE}.sha1"
1458 einfo "Generated netboot package ${OUTPUT_FILE}" ; eend 0
1459 rm -rf "${OUTPUTDIR}"
1461 rm -rf "${OUTPUTDIR}"
1462 eerror "Could not generate netboot package ${OUTPUT_FILE}" ; eend 1
1467 create_netbootpackage
1470 # log build information to database if grml-live-db is installed and enabled {{{
1472 if [ -d /usr/share/grml-live-db ] ; then
1475 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1476 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1477 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1478 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1480 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1481 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1482 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1486 # disable by default for now, not sure whether really everyone is using a local db file
1487 #if ! touch "$DPKG_DATABASE" ; then
1488 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1492 if ! [ -r "$DPKG_LIST" ] ; then
1493 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1494 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1496 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1497 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1498 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1501 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1517 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1518 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1520 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1522 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1526 ## END OF FILE #################################################################
1527 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=2