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
27 GRML_LIVE_VERSION='0.17.0'
30 ADDONS_LIST_FILE='/boot/isolinux/addons_list.cfg'
33 # usage information {{{
37 $PN - build process script for generating a (grml based) Linux Live-ISO
39 Usage: $PN [options, see as follows]
41 -a <architecture> architecture; available values: i386 and amd64
42 -A ensure clean build and pack artifacts
43 -b build the ISO without updating the chroot via FAI
44 -B build the ISO without touching the chroot (skips cleanup)
45 -c <classe[s]> classes to be used for building the ISO via FAI
46 -C <configfile> configuration file for grml-live
47 -d <date> use specified date instead of build time as date of release
48 -D <configdir> use specified configuration directory instead of /etc/grml/fai
49 -F force execution without prompting
50 -g <grml_name> set the grml flavour name
51 -h display short usage information and exit
52 -i <iso_name> name of ISO
53 -I <src_directory> directory which provides files that should become
54 part of the chroot/ISO
55 -n skip generation of ISO
56 -N bootstrap (build chroot) only, do not create files for ISO
57 -o <output_directory> main output directory of the build process
59 -Q skip netboot package build
60 -r <release_name> release name
61 -s <suite> Debian suite; values: etch, lenny, squeeze, sid
62 -t <template_directory> place of the templates
63 -T <tar_name> unpack chroot tar archive before starting
64 -u update existing chroot instead of rebuilding it from scratch
65 -U <username> arrange output to be owned by specified username
66 -v <version_number> specify version number of the release
67 -V increase verbosity in the build process
68 -z use ZLIB instead of LZMA/XZ compression
73 $PN -c GRMLBASE,GRML_FULL,AMD64 -o /dev/shm/grml
74 $PN -c GRMLBASE,GRML_FULL,AMD64 -i grml_0.0-1.iso -v 0.0-1
75 $PN -c GRMLBASE,GRML_FULL,AMD64 -s sid -V -r 'grml-live rocks'
77 More details: man grml-live + /usr/share/doc/grml-live/grml-live.html
78 http://grml.org/grml-live/
80 Please send your bug reports and feedback to the grml-team: http://grml.org/bugs/
84 # make sure it's possible to get usage information without being
85 # root or actually executing the script
86 if [ "$1" = '-h' -o "$1" = '--help' ] ; then
88 [ "$(id -u 2>/dev/null)" != 0 ] && echo "Please notice that this script requires root permissions."
93 # some runtime checks {{{
94 # we need root permissions for the build-process:
95 if [ "$(id -u 2>/dev/null)" != 0 ] ; then
96 echo "Error: please run this script with uid 0 (root)." >&2
100 if [ -r /var/run/fai/FAI_INSTALLATION_IN_PROGRESS ] ; then
101 echo "/usr/sbin/fai already running or was aborted before.">&2
102 echo "You may remove /var/run/fai/FAI_INSTALLATION_IN_PROGRESS and try again.">&2
107 if [ -r /var/run/fai/fai_softupdate_is_running ] ; then
108 echo "/usr/sbin/fai softupdate already running or was aborted before.">&2
109 echo "You may remove /var/run/fai/fai_softupdate_is_running and try again.">&2
114 # lsb-functions and configuration stuff {{{
115 # make sure they are not set by default
126 # don't use colors/escape sequences
127 if [ -r /lib/lsb/init-functions ] ; then
128 . /lib/lsb/init-functions
129 ! log_use_fancy_output && NOCOLORS=true
132 if [ -r /etc/grml/lsb-functions ] ; then
133 . /etc/grml/lsb-functions
135 einfo() { echo " [*] $*" ;}
136 eerror() { echo " [!] $*">&2 ;}
137 ewarn() { echo " [x] $*" ;}
139 eindent() { return 0 ;}
140 eoutdent() { return 0 ;}
143 # source main configuration file:
144 LIVE_CONF=/etc/grml/grml-live.conf
148 # umount all directories {{{
150 # make sure we don't leave any mounts - FAI doesn't remove them always
151 umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
152 umount $CHROOT_OUTPUT/sys 2>/dev/null || /bin/true
153 umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
154 umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
156 # certain FAI versions sadly leave a ramdisk behind, so better safe than sorry
157 if [ -x /usr/lib/fai/mkramdisk ] ; then
158 /usr/lib/fai/mkramdisk -u "$(readlink -f ${CHROOT_OUTPUT}/var/lib/dpkg)" >/dev/null 2>&1 || /bin/true
161 umount "${CHROOT_OUTPUT}/grml-live/sources/" 2>/dev/null || /bin/true
162 [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
168 rm -f /var/run/fai/fai_softupdate_is_running \
169 /var/run/fai/FAI_INSTALLATION_IN_PROGRESS
170 [ -n "$CONFIGDUMP" ] && rm -f "$CONFIGDUMP"
171 [ -n "$SQUASHFS_STDERR" ] && rm -rf "$SQUASHFS_STDERR"
173 [ -n "$1" ] && EXIT="$1" || EXIT="1"
174 [ -n "$2" ] && eerror "$2">&2
175 if [ -n "$PACK_ARTIFACTS" ]; then
178 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
179 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
182 if [ -n "$CHOWN_USER" ]; then
183 log "Setting ownership"
184 einfo "Setting ownership"
185 [ -n "${OUTPUT}" -a -d "${OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${OUTPUT}"
186 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${BUILD_OUTPUT}"
187 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${CHROOT_OUTPUT}"
188 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${ISO_OUTPUT}"
189 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${LOG_OUTPUT}"
190 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && chown -R "${CHOWN_USER}:" "${NETBOOT}"
191 [ -n "${CHROOT_ARCHIVE}" -a -f "${CHROOT_ARCHIVE}" ] && chown -R "${CHOWN_USER}:" "${CHROOT_ARCHIVE}"
194 log "------------------------------------------------------------------------------"
197 trap bailout 1 2 3 3 6 9 14 15
201 # some important functions {{{
204 # usage: log "string to log"
205 log() { [ -n "$LOGFILE" ] && echo "$*" >> $LOGFILE ; }
207 # cut string at character number int = $1
208 # usage: cut_string 5 "1234567890" will output "12345"
210 [ -n "$2" ] || return 1
211 echo "$2" | head -c "$1"; echo -ne "\n"
214 # prepend int = $1 spaces before string = $2
215 # usage: extend_string_begin 5 "123" will output " 123"
216 extend_string_begin() {
217 [ -n "$2" ] || return 1
218 local COUNT="$(echo $2 | wc -c)"
219 local FILL="$(expr $COUNT - $1)"
220 while [ "$FILL" -gt 1 ] ; do
222 local FILL=$(expr $FILL - 1)
224 while [ "$FILL" -lt 1 ] ; do
226 local FILL=$(expr $FILL + 1)
228 echo "$2" | head -c "$1"; echo -ne "\n"
231 # append int = $1 spaces to string = $2
232 # usage: extend_string_begin 5 "123" will output "123 "
233 extend_string_end() {
234 [ -n "$2" ] || return 1
235 echo -n "$2" | head -c "$1"
236 local COUNT="$(echo $2 | wc -c)"
237 local FILL="$(expr $COUNT - $1)"
238 while [ "$FILL" -gt 1 ] ; do
240 local FILL=$(expr $FILL - 1)
242 while [ "$FILL" -lt 1 ] ; do
244 local FILL=$(expr $FILL + 1)
249 # Copy addonfile $1 from either
250 # * the chroot (via $2, the system path),
251 # * or from TEMPLATE_DIRECTORY/compat (if exists),
252 # * or from the host system (again, using $2),
253 # or warn about the missing file.
256 # * We assume that the chroot always has a "good" version of
257 # the file. Also it makes sources handling easier.
258 # * On unstable, we Recommend the Debian packages containing
259 # these files. The user can override them by putting his
260 # "better" version into the chroot.
261 # * On stable, the Debian packages are probably not available,
262 # or outdated, so we look in TEMPLATE_DIRECTORY/compat first, where
263 # our grml-live-compat package installs current file versions.
265 DEST="${BUILD_OUTPUT}/boot/$3"
266 if [ ! -d "${DEST}/" ]; then
269 if [ -e "$CHROOT_OUTPUT/$2/$1" ]; then
270 log "Copying $1 from chroot"
271 cp "$CHROOT_OUTPUT/$2/$1" "${DEST}/"
274 if [ -e "${TEMPLATE_DIRECTORY}/compat/$3/$1" ]; then
275 log "Copying $1 from grml-live-compat"
276 cp "${TEMPLATE_DIRECTORY}/compat/$3/$1" "${DEST}/"
279 if [ -e "$2/$1" ]; then
280 log "Copying $1 from system"
281 cp "$2/$1" "${DEST}/"
285 msg="Missing addon file: \"$1\""
286 ewarn "$msg" ; eend 1
287 log "copy_addon_file: $msg"
291 # command line parsing {{{
292 while getopts "a:C:c:d:D:g:i:I:o:r:s:t:T:U:v:AbBFnNqQuVz" opt; do
295 A) PACK_ARTIFACTS=1 ;;
298 c) CLASSES="$OPTARG" ;;
299 C) LOCAL_CONFIG="$(readlink -f $OPTARG)" ;;
301 D) GRML_FAI_CONFIG="$(readlink -f $OPTARG)" ;;
302 g) GRML_NAME="$OPTARG" ;;
303 i) ISO_NAME="$OPTARG" ;;
304 I) CHROOT_INSTALL="$OPTARG" ;;
306 N) BOOTSTRAP_ONLY=1; SKIP_MKISOFS=1; SKIP_MKSQUASHFS=1 ;;
307 o) OUTPUT="$(readlink -f $OPTARG)" ;;
308 q) SKIP_MKSQUASHFS=1 ;;
310 r) RELEASENAME="$OPTARG" ;;
311 s) SUITE="$OPTARG" ;;
312 t) TEMPLATE_DIRECTORY="$OPTARG";;
313 T) UNPACK_CHROOT="$(readlink -f $OPTARG)" ;;
314 v) VERSION="$OPTARG" ;;
317 U) CHOWN_USER="$OPTARG" ;;
319 z) SQUASHFS_ZLIB=1 ;;
320 ?) echo "invalid option -$OPTARG" >&2; bailout 1 ;;
323 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
326 # read local (non-packaged) configuration {{{
327 if [ -z "$LOCAL_CONFIG" ]; then
328 if [ -r "/etc/grml/grml-live.local" ]; then
329 LOCAL_CONFIG="/etc/grml/grml-live.local"
332 if [ -n "$LOCAL_CONFIG" ]; then
333 if [ -r "$LOCAL_CONFIG" ]; then
336 eerror "Could not read specified local configuration file \"$LOCAL_CONFIG\"."
339 LOCAL_CONFIG=$(readlink -f "$LOCAL_CONFIG")
344 if [ -n "${GRML_LIVE_SOURCES:-}" ] ; then
345 eerror "Config variable \$GRML_LIVE_SOURCES is set. This variable has been deprecated."
346 ewarn "Please set up \${GRML_FAI_CONFIG}/config/files/etc/apt/sources.list.d/* instead."
351 # assume sane defaults (if not set already) {{{
352 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
353 [ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux'
354 [ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_FULL,$(echo ${ARCH} | tr 'a-z' 'A-Z')"
355 [ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)"
356 [ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators '
357 [ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml"
358 [ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png'
359 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
360 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai'
361 [ -n "$GRML_NAME" ] || GRML_NAME='grml'
362 [ -n "$HOSTNAME" ] || HOSTNAME='grml'
363 [ -n "$HYBRID_METHOD" ] || HYBRID_METHOD='manifold'
364 [ -n "$NFSROOT_CONF" ] || NFSROOT_CONF="${GRML_FAI_CONFIG}/make-fai-nfsroot.conf"
365 [ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks'
366 [ -n "$SQUASHFS_EXCLUDES_FILE" ] || SQUASHFS_EXCLUDES_FILE="${GRML_FAI_CONFIG}/config/grml/squashfs-excludes"
367 [ -n "$SUITE" ] || SUITE='squeeze'
368 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
369 [ -n "$USERNAME" ] || USERNAME='grml'
370 [ -n "$VERSION" ] || VERSION='0.0.1'
372 # output specific stuff, depends on $OUTPUT (iff not set):
373 [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live'
374 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
375 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
376 [ -n "$CHROOT_ARCHIVE" ] || CHROOT_ARCHIVE="$OUTPUT/$(basename $CHROOT_OUTPUT).tgz"
377 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
378 [ -n "$LOG_OUTPUT" ] || LOG_OUTPUT="$OUTPUT/grml_logs"
379 [ -n "$REPORTS" ] || REPORTS="${LOG_OUTPUT}/reports/"
380 [ -n "$NETBOOT" ] || NETBOOT="${OUTPUT}/netboot/"
383 # some misc checks before executing FAI {{{
384 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
385 specify it on the command line using the -c option."
386 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
387 specify it on the command line using the -o option."
389 # trim characters that are known to cause problems inside $GRML_NAME;
390 # for example isolinux does not like '-' inside the directory name
391 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
393 # export variables to have them available in fai scripts:
394 [ -n "$GRML_NAME" ] && export GRML_NAME="$GRML_NAME"
395 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
398 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
399 # this was default behaviour until grml-live 0.9.34:
400 if [ -n "$ZERO_LOGFILE" ] ; then
401 PRESERVE_LOGFILE='' # make sure it's cleaned then
402 ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
403 ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
408 # ask user whether the setup is ok {{{
409 if [ -z "$FORCE" ] ; then
411 echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
413 echo " FAI classes: $CLASSES"
414 [ -n "$LOCAL_CONFIG" ] && echo " Configuration: $LOCAL_CONFIG"
415 [ -n "$GRML_FAI_CONFIG" ] && echo " Config directory: $GRML_FAI_CONFIG"
416 echo " main directory: $OUTPUT"
417 [ -n "$UNPACK_CHROOT" ] && echo " Chroot from: $UNPACK_CHROOT"
418 [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT"
419 [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT"
420 [ -n "$ISO_OUTPUT" ] && echo " ISO target: $ISO_OUTPUT"
421 [ -n "$GRML_NAME" ] && echo " Grml name: $GRML_NAME"
422 [ -n "$RELEASENAME" ] && echo " Release name: $RELEASENAME"
423 [ -n "$DATE" ] && echo " Build date: $DATE"
424 [ -n "$VERSION" ] && echo " Grml version: $VERSION"
425 [ -n "$SUITE" ] && echo " Debian suite: $SUITE"
426 [ -n "$ARCH" ] && echo " Architecture: $ARCH"
427 [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD"
428 [ -n "$HYBRID_METHOD" ] && echo " Hybrid method: $HYBRID_METHOD"
429 [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY"
430 [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL"
431 [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID"
432 [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature."
433 [ -n "$CHOWN_USER" ] && echo " Output owner: $CHOWN_USER"
434 [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
435 [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS"
436 [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE"
437 [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA/XZ) compression."
438 [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
439 [ -n "$VERBOSE" ] && echo " Using VERBOSE mode."
440 [ -n "$PACK_ARTIFACTS" ] && echo " Will prepare packed artifacts and ensure clean build."
441 [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation."
442 if [ -n "$BOOTSTRAP_ONLY" ] ; then
443 echo " Bootstrapping only and not building (files for) ISO."
445 [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file."
446 [ -n "$SKIP_NETBOOT" ] && echo " Skipping creation of NETBOOT package."
447 [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file."
448 [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE."
449 [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched."
452 echo -n "Is this ok for you? [y/N] "
454 if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
455 bailout 1 "Exiting as requested."
461 # clean up before start {{{
462 if [ -n "${PACK_ARTIFACTS}" ]; then
463 echo "Wiping old artifacts"
464 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
465 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
466 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && rm -r "${ISO_OUTPUT}"
467 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && rm -r "${LOG_OUTPUT}"
468 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && rm -r "${NETBOOT}"
472 # create log file {{{
473 [ -n "$LOGFILE" ] || LOGFILE=${LOG_OUTPUT}/grml-live.log
474 mkdir -p $(dirname "${LOGFILE}")
476 chown root:adm $LOGFILE
480 # clean/zero/remove logfiles {{{
482 if [ -n "$PRESERVE_LOGFILE" ] ; then
483 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
485 # make sure it is empty (as it is e.g. appended to grml-live-db)
489 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
490 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
491 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
492 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
493 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
494 rm -f /var/log/fai/"$HOSTNAME"/last \
495 /var/log/fai/"$HOSTNAME"/last-dirinstall \
496 /var/log/fai/"$HOSTNAME"/last-softupdate
501 # source config and startup {{{
502 if [ -n "$CONFIG" ] ; then
503 if ! [ -f "$CONFIG" ] ; then
504 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
505 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
508 log "Sourcing $CONFIG"
513 start_seconds=$(cut -d . -f 1 /proc/uptime)
514 log "------------------------------------------------------------------------------"
515 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
516 log "Using local config file: $LOCAL_CONFIG"
517 log "Executed grml-live command line:"
520 einfo "Logging actions to logfile $LOGFILE"
523 # dump config variables into file, for script access {{{
526 '^(GRML_NAME|RELEASENAME|DATE|VERSION|SUITE|ARCH|DISTRI_NAME|USERNAME|HOSTNAME|APT_PROXY)=' \
531 if [ -n "${UNPACK_CHROOT}" ]; then
532 log "Unpacking chroot from ${UNPACK_CHROOT}"
533 einfo "Unpacking chroot from ${UNPACK_CHROOT}"
534 [ -d "$CHROOT_OUTPUT" ] || mkdir -p "${CHROOT_OUTPUT}"
535 tar -xf "${UNPACK_CHROOT}" -C "${CHROOT_OUTPUT}/" --strip-components 1 ; RC=$?
536 if [ "$RC" != 0 ] ; then
544 # cleanup CHROOT_ARCHIVE now {{{
545 if [ -n "${PACK_ARTIFACTS}" ]; then
546 # can't do this earlier, as UNPACK_CHROOT might point to CHROOT_ARCHIVE
547 [ -n "${CHROOT_ARCHIVE}" -a -f "${CHROOT_ARCHIVE}" ] && rm "${CHROOT_ARCHIVE}"
551 # on-the-fly configuration {{{
552 if [ -n "$FAI_DEBOOTSTRAP" ] ; then
553 sed "s#^FAI_DEBOOTSTRAP=.*#FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"#" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
556 # does this suck? YES!
557 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
559 unstable) SUITE='sid' ; CLASSES="DEBIAN_UNSTABLE,$CLASSES" ;;
560 *) CLASSES="DEBIAN_$(echo $SUITE | tr 'a-z' 'A-Z'),$CLASSES";;
562 export SUITE # make sure it's available in FAI scripts
564 for file in "$LIVE_CONF" "$LOCAL_CONFIG" "$NFSROOT_CONF" ; do
565 if [ -n "$file" ] ; then
566 sed "s|^FAI_DEBOOTSTRAP=\"[a-z]* |FAI_DEBOOTSTRAP=\"$SUITE |" "$file" | sponge "$file"
570 # validate whether the specified architecture class matches the
571 # architecture (option), otherwise installation of kernel will fail
572 if echo $CLASSES | grep -qi i386 ; then
573 if ! [[ "$ARCH" == "i386" ]] ; then
574 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
575 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
576 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
580 elif echo $CLASSES | grep -qi amd64 ; then
581 if ! [[ "$ARCH" == "amd64" ]] ; then
582 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
583 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
584 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
590 if grep -q -- 'FAI_DEBOOTSTRAP_OPTS.*--arch' "$NFSROOT_CONF" ; then
591 sed "s/--arch [a-z0-9]* /--arch $ARCH /" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
593 sed "s|^FAI_DEBOOTSTRAP_OPTS=\"\(.*\)|FAI_DEBOOTSTRAP_OPTS=\"--arch $ARCH \1|" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
597 # CHROOT_OUTPUT - execute FAI {{{
598 if [ -n "$BUILD_DIRTY" ]; then
599 log "Skipping stage 'fai' as requested via option -B"
600 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
602 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
604 # provide inform fai about the ISO we build
605 [ -d "$CHROOT_OUTPUT/etc/" ] || mkdir -p "$CHROOT_OUTPUT/etc/"
606 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
607 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
608 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
610 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
611 FAI_ACTION=softupdate
613 FAI_ACTION=dirinstall
616 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
617 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
618 log "Error: does not look like you have a working chroot. Updating/building not possible."
619 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
625 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
626 log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
627 ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
629 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
631 if [ -n "${MIRROR_DIRECTORY}" ] ; then
632 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
633 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
636 mkdir -p "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
637 mount --bind "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
639 # tell dpkg to use "unsafe io" during the build
640 [ -d "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d" ] || mkdir -p "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d"
641 echo force-unsafe-io > "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d/unsafe-io"
643 log "Executed FAI command line:"
644 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"
645 BUILD_ONLY="$BUILD_ONLY" BOOTSTRAP_ONLY="$BOOTSTRAP_ONLY" GRML_LIVE_CONFIG="$CONFIGDUMP" fai $VERBOSE \
646 -C "$GRML_FAI_CONFIG" -s "file:///$GRML_FAI_CONFIG/config" -c"$CLASSES" \
647 -u "$HOSTNAME" "$FAI_ACTION" "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
648 RC="$PIPESTATUS" # notice: bash-only
650 rm -f "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d/unsafe-io"
652 FORCE_ISO_REBUILD=true
654 if [ "$RC" != 0 ] ; then
655 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
656 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
660 # move fai logs into grml_logs directory
661 mkdir -p "$LOG_OUTPUT"/fai/
662 cp -r "$CHROOT_OUTPUT"/var/log/fai/"$HOSTNAME"/last/* "$LOG_OUTPUT"/fai/
663 rm -rf "$CHROOT_OUTPUT"/var/log/fai
664 # copy fai package list
665 cp "$CHROOT_OUTPUT"/var/log/install_packages.list "$LOG_OUTPUT"/fai/
667 chown root:adm "$LOG_OUTPUT"/fai/*
668 chmod 664 "$LOG_OUTPUT"/fai/*
672 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
674 CHECKLOG="$LOG_OUTPUT"/fai/
675 if [ -r "$CHECKLOG/software.log" ] ; then
676 # 1 errors during executing of commands
677 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
678 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
679 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
680 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
681 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
684 if [ -r "$CHECKLOG/shell.log" ] ; then
685 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
688 if [ -n "$ERROR" ] ; then
689 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
690 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
691 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
695 log "Finished execution of stage 'fai dirinstall' [$(date)]"
696 einfo "Finished execution of stage 'fai dirinstall'"
702 # package validator {{{
703 CHECKLOG=/var/log/fai/$HOSTNAME/last
704 if [ -r "$CHECKLOG/dpkg.selections" ] ; then
705 package_count=$(wc -l "$CHECKLOG/dpkg.selections" | awk '{print $1}')
707 package_count="unknown"
711 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
713 # check for missing packages
714 if ! [ -s "$CHECKLOG/package_errors.log" ] ; then
715 einfo "No missing packages found, generating empty junit report."
717 cat > "${REPORT_MISSING_PACKAGES}" << EOF
718 <?xml version="1.0" encoding="UTF-8"?>
719 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="0" errors="0" skipped="0" assertions="0">
720 <testcase name="test_missing_packages" time="0" assertions="0">
730 einfo "Missing packages found, generating junit report."
732 if [ -r "$CHECKLOG/package_errors.log" ] ; then
733 package_errors=$(wc -l "$CHECKLOG/package_errors.log" | awk '{print $1}')
735 package_errors="unknown"
739 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
741 cat > "${REPORT_MISSING_PACKAGES}" << EOF
742 <?xml version="1.0" encoding="UTF-8"?>
743 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="${package_errors}" errors="${package_errors}" skipped="0" assertions="0">
746 for package in $(awk '{print $5}' "${CHECKLOG}/package_errors.log" | sed 's/\.$//') ; do
747 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
748 <testcase name="test_missing_packages_${package}" time="0" assertions="0">
749 <failure type="RuntimeError" message="Package ${package} is missing">
750 Package $package is missing in chroot
756 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
765 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
766 eerror "The following packages were requested for installation but could not be processed:"
767 cat "$CHECKLOG/package_errors.log"
768 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
772 ewarn "The following packages were requested for installation but could not be processed:"
773 cat "$CHECKLOG/package_errors.log"
779 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
780 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
781 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
784 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
785 if [ -n "$BOOTSTRAP_ONLY" ] ; then
786 log "Skipping stage 'boot' as building with bootstrap only."
787 ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0
789 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
790 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
791 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
794 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
795 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
797 # if we don't have an initrd we a) can't boot and b) there was an error
798 # during build, so check for the file:
799 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
800 if [ -n "$INITRD" ] ; then
801 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.gz
802 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
804 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
805 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
809 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
810 if [ -n "$KERNEL_IMAGE" ] ; then
811 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/linux26
813 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
814 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
818 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
819 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
820 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
821 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
825 # copy _required_ isolinux files
826 for file in ifcpu64.c32 isolinux.bin vesamenu.c32; do
827 copy_addon_file "${file}" /usr/lib/syslinux isolinux
830 # *always* copy files to output directory so the variables
831 # get adjusted according to the build.
832 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
834 if [ -n "$NO_ADDONS" ] ; then
835 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
836 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
838 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
839 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
840 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
842 # copy addons from system packages or grml-live-compat
843 copy_addon_file ipxe.lkrn /usr/lib/ipxe addons
844 copy_addon_file pci.ids /usr/share/misc addons
845 copy_addon_file memtest86+.bin /boot addons
846 for file in memdisk chain.c32 hdt.c32 menu.c32; do
847 copy_addon_file "${file}" /usr/lib/syslinux addons
850 # make memtest filename FAT16/8.3 compatible
851 mv "${BUILD_OUTPUT}/boot/addons/memtest86+.bin" \
852 "${BUILD_OUTPUT}/boot/addons/memtest"
854 # copy only files so we can handle bsd4grml on its own
855 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
856 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
859 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
860 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
861 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
863 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
864 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
866 log "Missing addon file: bsd4grml"
867 ewarn "Missing addon file: bsd4grml" ; eend 0
871 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
874 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
875 mkdir -p "${BUILD_OUTPUT}/boot/grub"
877 cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
879 # copy grub files from target
880 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.mod "${BUILD_OUTPUT}"/boot/grub/
881 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.o "${BUILD_OUTPUT}"/boot/grub/
882 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.lst "${BUILD_OUTPUT}"/boot/grub/
883 cp -a "${CHROOT_OUTPUT}"/usr/share/grub/ascii.pf2 "${BUILD_OUTPUT}"/boot/grub/
884 cp -a "${CHROOT_OUTPUT}"/boot/grub/core.img "${BUILD_OUTPUT}"/boot/grub/
886 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
887 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
888 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
892 [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML
893 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/
895 # adjust boot splash information:
896 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
897 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
898 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
900 if [ -r "$BUILD_OUTPUT"/GRML/grml-version ] ; then
901 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version
902 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/grml-version
905 # make sure the squashfs filename is set accordingly:
906 SQUASHFS_NAME="$GRML_NAME.squashfs"
908 if [ -n "$NO_BOOTID" ] ; then
909 log 'Skipping bootid feature as requested via $NO_BOOTID.'
910 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
912 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
913 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
914 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
915 log "Generating /conf/bootid.txt with entry ${BOOTID}."
916 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
920 # adjust all variables in the templates with the according distribution information
921 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
922 "${BUILD_OUTPUT}"/boot/grub/* ; do
923 if [ -r "${file}" ] ; then
924 sed -i "s/%ARCH%/$ARCH/g" "${file}"
925 sed -i "s/%DATE%/$DATE/g" "${file}"
926 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
927 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
928 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
929 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
930 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
931 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
932 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
933 sed -i "s/%VERSION%/$VERSION/g" "${file}"
935 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s/ boot=live/ boot=live $DEFAULT_BOOTOPTIONS/" "${file}"
937 if [ -n "$NO_BOOTID" ] ; then
938 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
940 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
945 # adjust bootsplash accordingly but make sure the string has the according lenght
946 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
947 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
948 for file in f4 f5 ; do
949 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
950 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
951 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
955 # generate addon list
956 rm -f "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
957 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
958 include_name=$(basename "$name")
959 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
962 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
963 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
964 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
965 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
966 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
967 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
969 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
970 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
973 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
974 if [ ! -n "$NO_ADDONS" ] ; then
975 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
977 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
978 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
979 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
980 else # assume we are building a custom distribution:
981 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
982 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
983 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
984 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
986 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
990 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
991 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
992 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
996 # use old style console based isolinux method only if requested:
997 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
998 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
999 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1000 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1001 einfo "include for console.cfg already found, nothing to do."
1004 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1005 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1006 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1010 log 'Using graphical boot menu.'
1011 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
1012 log "include for vesamenu.cfg already found, nothing to do."
1014 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1015 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1019 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
1020 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
1023 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
1024 if ! [ -r "$DPKG_LIST" ] ; then
1025 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
1027 einfo "Storing package list information as /GRML/${GRML_NAME}-packages.txt on ISO."
1028 cp "$DPKG_LIST" "${BUILD_OUTPUT}/GRML/${GRML_NAME}-packages.txt"
1032 # autostart for Windows:
1033 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
1034 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
1037 FORCE_ISO_REBUILD=true
1038 einfo "Finished execution of stage 'boot'" ; eend 0
1042 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
1043 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
1047 # support installation of local files into the chroot/ISO
1048 if [ -n "$CHROOT_INSTALL" ] ; then
1049 if ! [ -d "$CHROOT_INSTALL" ] ; then
1050 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1051 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1053 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1054 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1055 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
1057 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
1058 FORCE_ISO_REBUILD=true
1062 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1063 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
1064 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
1065 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
1066 log "Skipping stage 'squashfs' as requested via option -q or -N"
1067 ewarn "Skipping stage 'squashfs' as requested via option -q or -N" ; eend 0
1069 [ -d "$BUILD_OUTPUT"/live ] || mkdir "$BUILD_OUTPUT"/live
1070 # make sure we don't leave (even an empty) base.tgz:
1071 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
1073 # if unconfigured default to squashfs-tools' mksquashfs binary
1074 if [ -z "$SQUASHFS_BINARY" ] ; then
1075 SQUASHFS_BINARY='mksquashfs'
1078 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
1079 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
1080 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
1082 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
1083 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
1087 # use sane defaults if $SQUASHFS_OPTIONS isn't set
1088 if [ -z "$SQUASHFS_OPTIONS" ] ; then
1089 # use blocksize 256k as this gives best result with regards to time + compression
1090 SQUASHFS_OPTIONS="-b 256k"
1092 # set lzma/xz compression by default, unless -z option has been specified on command line
1093 if [ -z "$SQUASHFS_ZLIB" ] ; then
1094 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
1096 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
1100 # support exclusion of files via exclude-file:
1101 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
1102 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE -wildcards"
1105 # get rid of unnecessary files when building grml-small for final release:
1106 if echo "$CLASSES" | grep -q GRML_SMALL ; then
1107 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
1111 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
1113 # informational stuff
1114 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1115 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1116 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1118 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1120 if $SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \
1121 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1122 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/filesystem.module
1123 log "Finished execution of stage 'squashfs' [$(date)]"
1124 einfo "Finished execution of stage 'squashfs'" ; eend 0
1126 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1127 log "$(cat $SQUASHFS_STDERR)"
1128 eerror "Error: there was a critical error executing stage 'squashfs':"
1129 cat "${SQUASHFS_STDERR}"
1134 FORCE_ISO_REBUILD=true
1137 # create md5sum file:
1138 if [ -z "$BOOTSTRAP_ONLY" ] ; then
1139 ( cd $BUILD_OUTPUT/GRML &&
1140 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1144 # ISO_OUTPUT - mkisofs {{{
1145 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1146 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1148 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1149 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1150 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1151 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1154 # Just until http://bts.grml.org/grml/issue945 has been resolved.
1155 # HYBRID_METHOD defaults to manifold, so make sure the default works OOTB.
1156 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1157 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1158 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1159 HYBRID_METHOD='grub2'
1163 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1164 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1165 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1166 elif [ -n "$SKIP_MKISOFS" ] ; then
1167 log "Skipping stage 'iso build' as requested via option -n or -N"
1168 ewarn "Skipping stage 'iso build' as requested via option -n or -N" ; eend 0
1170 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1172 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1173 log "Forcing rebuild of ISO because files on ISO have been modified."
1174 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1177 # support xorriso as well mkisofs and genisoimage
1178 if which xorriso >/dev/null 2>&1 ; then
1179 MKISOFS='xorriso -as mkisofs'
1180 elif which mkisofs >/dev/null 2>&1; then
1182 elif which genisoimage >/dev/null 2>&1; then
1183 MKISOFS='genisoimage'
1185 log "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO."
1186 eerror "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO." ; eend 1
1192 # using -eltorito-alt-boot is limited to xorriso for now
1195 einfo "Using xorriso for ISO generation." ; eend 0
1198 if ! dpkg --compare-versions $(dpkg-query -W -f='${Version}\n' xorriso 2>/dev/null) gt-nl 1.1.6-1 ; then
1199 log "Disabling (U)EFI boot support since xorriso version is not recent enough."
1200 ewarn "Disabling (U)EFI boot support since xorriso version is not recent enough." ; eend 0
1202 log "xorriso with -eltorito-alt-boot present, enabling (U)EFI boot support."
1203 einfo "xorriso with -eltorito-alt-boot present, enabling (U)EFI boot support." ; eend 0
1205 if [ -r "${CHROOT_OUTPUT}/var/lib/grml_live_efi.img" ] ; then
1206 einfo "Found /var/lib/grml_live_efi.img - moving to /boot/efi.img for ISO."
1207 log "Found /var/lib/grml_live_efi.img - moving to /boot/efi.img for ISO."
1208 mv "${CHROOT_OUTPUT}/var/lib/grml_live_efi.img" "${BUILD_OUTPUT}/boot/efi.img"
1212 if [ -r "${CHROOT_OUTPUT}/var/lib/grml_live_bootx64.efi" ] ; then
1213 einfo "Found /var/lib/grml_live_bootx64.efi - moving to /efi/boot/bootx64.efi for ISO"
1214 log "Found /var/lib/grml_live_bootx64.efi - moving to /efi/boot/bootx64.efi for ISO"
1215 mkdir -p "${BUILD_OUTPUT}/efi/boot/"
1216 mv "${CHROOT_OUTPUT}/var/lib/grml_live_bootx64.efi" "${BUILD_OUTPUT}/efi/boot/bootx64.efi"
1220 if [ -r "${BUILD_OUTPUT}"/boot/efi.img ] ; then
1221 einfo "/boot/efi.img found and amd64 architecture present, extending boot arguments."
1222 log "/boot/efi.img found and amd64 architecture present, extending boot arguments."
1223 BOOT_ARGS="$BOOT_ARGS -boot-info-table -eltorito-alt-boot -e boot/efi.img -no-emul-boot"
1235 if cd "$BUILD_OUTPUT" ; then
1236 if [ "$BOOT_METHOD" = "grub2" ]; then
1237 # make a 2048-byte bootsector for El Torito
1238 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1239 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1240 echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
1241 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1243 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1244 $MKISOFS -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1245 -l -r -J $BOOT_ARGS -no-pad \
1246 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1247 # both of these need core.img there, so it’s easier to write it here
1248 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1249 # must be <= 30720 bytes
1250 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1251 conv=notrunc bs=512 seek=4 2>/dev/null
1254 # pad the output ISO to multiples of 256 KiB for partition table support
1255 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1256 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1257 siz=$((cyls * 16 * 32 * 512)) # size after padding
1258 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1259 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1261 # support disabling hybrid ISO image
1262 if [ "$HYBRID_METHOD" = "disable" ] ; then\
1263 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1264 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1266 elif [ "$HYBRID_METHOD" = "manifold" ] ; then
1267 # isoinfo is part of both mkisofs and genisoimage so we're good
1268 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1269 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN[;1]* *$/s//\1/p')
1270 if ! [ -r boot/grub/core.img ] ; then
1271 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1272 elif [ "${bootoff:-0}" -lt 1 ] ; then
1273 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1275 log "Creating hybrid ISO file with manifold method"
1276 einfo "Creating hybrid ISO file with manifold method"
1277 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1278 # 512 bytes: MBR, partition table, load GRUB 2
1279 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1281 # read only one but 2048-byte sized (scale: << 2) sector
1282 echo $bootoff $bootoff | \
1283 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1284 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1287 # use isohybrid as default
1289 if ! which isohybrid >/dev/null 2>&1 ; then
1290 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1292 log "Creating hybrid ISO file with isohybrid method"
1293 einfo "Creating hybrid ISO file with isohybrid method"
1294 # Notes for consideration:
1295 # "-entry 4 -type 1c"
1296 # * using 4 as the partition number is supposed to help with BIOSes
1297 # that only support USB-Zip boot
1298 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1299 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1300 # to get the BIOS even look at the partition created by isohybrid
1301 if isohybrid --help | grep -q -- --uefi ; then
1302 einfo "Detected uefi support for isohybrid, enabling."
1303 ISOHYBRID_OPTIONS=--uefi
1306 log "isohybrid $ISOHYBRID_OPTIONS ${ISO_OUTPUT}/${ISO_NAME}"
1307 isohybrid $ISOHYBRID_OPTIONS "${ISO_OUTPUT}/${ISO_NAME}"
1312 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1313 case $CLASSES in *RELEASE*)
1316 if cd $ISO_OUTPUT ; then
1317 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1318 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1319 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1320 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1329 if [ "$RC" = 0 ] ; then
1330 log "Finished execution of stage 'iso build' [$(date)]"
1331 einfo "Finished execution of stage 'iso build'" ; eend 0
1333 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1334 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1340 # netboot package {{{
1341 create_netbootpackage() {
1342 local OUTPUT_FILE="${NETBOOT}/grml_netboot_package_${GRML_NAME}_${VERSION}.tar.bz2"
1344 if [ -f "${OUTPUT_FILE}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1345 log "Skipping stage 'netboot' as $OUTPUT_FILE exists already."
1346 ewarn "Skipping stage 'netboot' as $OUTPUT_FILE exists already." ; eend 0
1348 elif [ -n "$SKIP_NETBOOT" ] ; then
1349 log "Skipping stage 'netboot' as requested via option -Q"
1350 ewarn "Skipping stage 'netboot' as requested via option -Q" ; eend 0
1356 if ! [ -r "${CHROOT}/usr/lib/syslinux/pxelinux.0" ] ; then
1357 ewarn "File /usr/lib/syslinux/pxelinux.0 not found in build chroot." ; eend 0
1359 einfo "Install syslinux[-common] package in chroot to get a netboot package."
1364 local OUTPUTDIR="${NETBOOT}/build_tmp"
1365 local WORKING_DIR="${OUTPUTDIR}/grml_netboot_package_${GRML_NAME}_${VERSION}/tftpboot/"
1367 mkdir -p "$WORKING_DIR"
1369 cp "${CHROOT_OUTPUT}"/boot/vmlinuz-* "$WORKING_DIR"/linux26
1370 cp "${CHROOT_OUTPUT}"/boot/initrd.img-* "$WORKING_DIR"/initrd.img
1371 cp "${CHROOT_OUTPUT}"/usr/lib/syslinux/pxelinux.0 "${WORKING_DIR}/pxelinux.0"
1373 if [ -r "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" ] ; then
1374 mkdir -p "${WORKING_DIR}/pxelinux.cfg/default"
1375 cp "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" "${WORKING_DIR}/pxelinux.cfg/default"
1377 ewarn "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found." ; eend 0
1380 mkdir -p "${WORKING_DIR}/pxelinux.cfg"
1382 if tar -C "$OUTPUTDIR" -jcf "${OUTPUT_FILE}" "grml_netboot_package_${GRML_NAME}_${VERSION}" ; then
1383 sha1sum "${OUTPUT_FILE}" > "${OUTPUT_FILE}.sha1"
1384 einfo "Generated netboot package ${OUTPUT_FILE}" ; eend 0
1385 rm -rf "${OUTPUTDIR}"
1387 rm -rf "${OUTPUTDIR}"
1388 eerror "Could not generate netboot package ${OUTPUT_FILE}" ; eend 1
1393 create_netbootpackage
1396 # pack artifacts {{{
1397 if [ -n "$PACK_ARTIFACTS" ]; then
1398 log "Packing artifcats"
1399 einfo "Packing artifacts"
1400 [ -f "${CHROOT_ARCHIVE}" ] && rm -r "${CHROOT_ARCHIVE}"
1401 tar -c -a -f ${CHROOT_ARCHIVE} --preserve-permissions -C "$(dirname ${CHROOT_OUTPUT})" "$(basename ${CHROOT_OUTPUT})"
1406 # log build information to database if grml-live-db is installed and enabled {{{
1408 if [ -d /usr/share/grml-live-db ] ; then
1411 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1412 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1413 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1414 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1416 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1417 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1418 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1422 # disable by default for now, not sure whether really everyone is using a local db file
1423 #if ! touch "$DPKG_DATABASE" ; then
1424 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1428 if ! [ -r "$DPKG_LIST" ] ; then
1429 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1430 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1432 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1433 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1434 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1437 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1453 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1454 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1456 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1458 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1462 ## END OF FILE #################################################################
1463 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=2