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/sys/fs/binfmt_misc 2>/dev/null || /bin/true
152 umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
153 umount $CHROOT_OUTPUT/sys 2>/dev/null || /bin/true
154 umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
155 umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
157 # certain FAI versions sadly leave a ramdisk behind, so better safe than sorry
158 if [ -x /usr/lib/fai/mkramdisk ] ; then
159 /usr/lib/fai/mkramdisk -u "$(readlink -f ${CHROOT_OUTPUT}/var/lib/dpkg)" >/dev/null 2>&1 || /bin/true
162 umount "${CHROOT_OUTPUT}/grml-live/sources/" 2>/dev/null || /bin/true
163 [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
169 rm -f /var/run/fai/fai_softupdate_is_running \
170 /var/run/fai/FAI_INSTALLATION_IN_PROGRESS
171 [ -n "$CONFIGDUMP" ] && rm -f "$CONFIGDUMP"
172 [ -n "$SQUASHFS_STDERR" ] && rm -rf "$SQUASHFS_STDERR"
174 [ -n "$1" ] && EXIT="$1" || EXIT="1"
175 [ -n "$2" ] && eerror "$2">&2
176 if [ -n "$PACK_ARTIFACTS" ]; then
179 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
180 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
183 if [ -n "$CHOWN_USER" ]; then
184 log "Setting ownership"
185 einfo "Setting ownership"
186 [ -n "${OUTPUT}" -a -d "${OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${OUTPUT}"
187 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${BUILD_OUTPUT}"
188 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${CHROOT_OUTPUT}"
189 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${ISO_OUTPUT}"
190 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${LOG_OUTPUT}"
191 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && chown -R "${CHOWN_USER}:" "${NETBOOT}"
192 [ -n "${CHROOT_ARCHIVE}" -a -f "${CHROOT_ARCHIVE}" ] && chown -R "${CHOWN_USER}:" "${CHROOT_ARCHIVE}"
195 log "------------------------------------------------------------------------------"
198 trap bailout 1 2 3 3 6 9 14 15
202 # some important functions {{{
205 # usage: log "string to log"
206 log() { [ -n "$LOGFILE" ] && echo "$*" >> $LOGFILE ; }
208 # cut string at character number int = $1
209 # usage: cut_string 5 "1234567890" will output "12345"
211 [ -n "$2" ] || return 1
212 echo "$2" | head -c "$1"; echo -ne "\n"
215 # prepend int = $1 spaces before string = $2
216 # usage: extend_string_begin 5 "123" will output " 123"
217 extend_string_begin() {
218 [ -n "$2" ] || return 1
219 local COUNT="$(echo $2 | wc -c)"
220 local FILL="$(expr $COUNT - $1)"
221 while [ "$FILL" -gt 1 ] ; do
223 local FILL=$(expr $FILL - 1)
225 while [ "$FILL" -lt 1 ] ; do
227 local FILL=$(expr $FILL + 1)
229 echo "$2" | head -c "$1"; echo -ne "\n"
232 # append int = $1 spaces to string = $2
233 # usage: extend_string_begin 5 "123" will output "123 "
234 extend_string_end() {
235 [ -n "$2" ] || return 1
236 echo -n "$2" | head -c "$1"
237 local COUNT="$(echo $2 | wc -c)"
238 local FILL="$(expr $COUNT - $1)"
239 while [ "$FILL" -gt 1 ] ; do
241 local FILL=$(expr $FILL - 1)
243 while [ "$FILL" -lt 1 ] ; do
245 local FILL=$(expr $FILL + 1)
250 # Copy addonfile $1 from either
251 # * the chroot (via $2, the system path),
252 # * or from TEMPLATE_DIRECTORY/compat (if exists),
253 # * or from the host system (again, using $2),
254 # or warn about the missing file.
257 # * We assume that the chroot always has a "good" version of
258 # the file. Also it makes sources handling easier.
259 # * On unstable, we Recommend the Debian packages containing
260 # these files. The user can override them by putting his
261 # "better" version into the chroot.
262 # * On stable, the Debian packages are probably not available,
263 # or outdated, so we look in TEMPLATE_DIRECTORY/compat first, where
264 # our grml-live-compat package installs current file versions.
266 DEST="${BUILD_OUTPUT}/boot/$3"
267 if [ ! -d "${DEST}/" ]; then
270 if [ -e "$CHROOT_OUTPUT/$2/$1" ]; then
271 log "Copying $1 from chroot"
272 cp "$CHROOT_OUTPUT/$2/$1" "${DEST}/"
275 if [ -e "${TEMPLATE_DIRECTORY}/compat/$3/$1" ]; then
276 log "Copying $1 from grml-live-compat"
277 cp "${TEMPLATE_DIRECTORY}/compat/$3/$1" "${DEST}/"
280 if [ -e "$2/$1" ]; then
281 log "Copying $1 from system"
282 cp "$2/$1" "${DEST}/"
286 msg="Missing addon file: \"$1\""
287 ewarn "$msg" ; eend 1
288 log "copy_addon_file: $msg"
292 # command line parsing {{{
293 while getopts "a:C:c:d:D:g:i:I:o:r:s:t:T:U:v:AbBFnNqQuVz" opt; do
296 A) PACK_ARTIFACTS=1 ;;
299 c) CLASSES="$OPTARG" ;;
300 C) LOCAL_CONFIG="$(readlink -f $OPTARG)" ;;
302 D) GRML_FAI_CONFIG="$(readlink -f $OPTARG)" ;;
303 g) GRML_NAME="$OPTARG" ;;
304 i) ISO_NAME="$OPTARG" ;;
305 I) CHROOT_INSTALL="$OPTARG" ;;
307 N) BOOTSTRAP_ONLY=1; SKIP_MKISOFS=1; SKIP_MKSQUASHFS=1 ;;
308 o) OUTPUT="$(readlink -f $OPTARG)" ;;
309 q) SKIP_MKSQUASHFS=1 ;;
311 r) RELEASENAME="$OPTARG" ;;
312 s) SUITE="$OPTARG" ;;
313 t) TEMPLATE_DIRECTORY="$OPTARG";;
314 T) UNPACK_CHROOT="$(readlink -f $OPTARG)" ;;
315 v) VERSION="$OPTARG" ;;
318 U) CHOWN_USER="$OPTARG" ;;
320 z) SQUASHFS_ZLIB=1 ;;
321 ?) echo "invalid option -$OPTARG" >&2; bailout 1 ;;
324 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
327 # read local (non-packaged) configuration {{{
328 if [ -z "$LOCAL_CONFIG" ]; then
329 if [ -r "/etc/grml/grml-live.local" ]; then
330 LOCAL_CONFIG="/etc/grml/grml-live.local"
333 if [ -n "$LOCAL_CONFIG" ]; then
334 if [ -r "$LOCAL_CONFIG" ]; then
337 eerror "Could not read specified local configuration file \"$LOCAL_CONFIG\"."
340 LOCAL_CONFIG=$(readlink -f "$LOCAL_CONFIG")
345 if [ -n "${GRML_LIVE_SOURCES:-}" ] ; then
346 eerror "Config variable \$GRML_LIVE_SOURCES is set. This variable has been deprecated."
347 ewarn "Please set up \${GRML_FAI_CONFIG}/config/files/etc/apt/sources.list.d/* instead."
352 # assume sane defaults (if not set already) {{{
353 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
354 [ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux'
355 [ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_FULL,$(echo ${ARCH} | tr 'a-z' 'A-Z')"
356 [ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)"
357 [ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators '
358 [ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml"
359 [ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png'
360 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
361 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai'
362 [ -n "$GRML_NAME" ] || GRML_NAME='grml'
363 [ -n "$HOSTNAME" ] || HOSTNAME='grml'
364 [ -n "$HYBRID_METHOD" ] || HYBRID_METHOD='manifold'
365 [ -n "$NFSROOT_CONF" ] || NFSROOT_CONF="${GRML_FAI_CONFIG}/make-fai-nfsroot.conf"
366 [ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks'
367 [ -n "$SQUASHFS_EXCLUDES_FILE" ] || SQUASHFS_EXCLUDES_FILE="${GRML_FAI_CONFIG}/config/grml/squashfs-excludes"
368 [ -n "$SUITE" ] || SUITE='squeeze'
369 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
370 [ -n "$USERNAME" ] || USERNAME='grml'
371 [ -n "$VERSION" ] || VERSION='0.0.1'
373 # output specific stuff, depends on $OUTPUT (iff not set):
374 [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live'
375 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
376 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
377 [ -n "$CHROOT_ARCHIVE" ] || CHROOT_ARCHIVE="$OUTPUT/$(basename $CHROOT_OUTPUT).tgz"
378 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
379 [ -n "$LOG_OUTPUT" ] || LOG_OUTPUT="$OUTPUT/grml_logs"
380 [ -n "$REPORTS" ] || REPORTS="${LOG_OUTPUT}/reports/"
381 [ -n "$NETBOOT" ] || NETBOOT="${OUTPUT}/netboot/"
384 # some misc checks before executing FAI {{{
385 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
386 specify it on the command line using the -c option."
387 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
388 specify it on the command line using the -o option."
390 # trim characters that are known to cause problems inside $GRML_NAME;
391 # for example isolinux does not like '-' inside the directory name
392 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
394 # export variables to have them available in fai scripts:
395 [ -n "$GRML_NAME" ] && export GRML_NAME="$GRML_NAME"
396 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
399 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
400 # this was default behaviour until grml-live 0.9.34:
401 if [ -n "$ZERO_LOGFILE" ] ; then
402 PRESERVE_LOGFILE='' # make sure it's cleaned then
403 ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
404 ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
409 # ask user whether the setup is ok {{{
410 if [ -z "$FORCE" ] ; then
412 echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
414 echo " FAI classes: $CLASSES"
415 [ -n "$LOCAL_CONFIG" ] && echo " Configuration: $LOCAL_CONFIG"
416 [ -n "$GRML_FAI_CONFIG" ] && echo " Config directory: $GRML_FAI_CONFIG"
417 echo " main directory: $OUTPUT"
418 [ -n "$UNPACK_CHROOT" ] && echo " Chroot from: $UNPACK_CHROOT"
419 [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT"
420 [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT"
421 [ -n "$ISO_OUTPUT" ] && echo " ISO target: $ISO_OUTPUT"
422 [ -n "$GRML_NAME" ] && echo " Grml name: $GRML_NAME"
423 [ -n "$RELEASENAME" ] && echo " Release name: $RELEASENAME"
424 [ -n "$DATE" ] && echo " Build date: $DATE"
425 [ -n "$VERSION" ] && echo " Grml version: $VERSION"
426 [ -n "$SUITE" ] && echo " Debian suite: $SUITE"
427 [ -n "$ARCH" ] && echo " Architecture: $ARCH"
428 [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD"
429 [ -n "$HYBRID_METHOD" ] && echo " Hybrid method: $HYBRID_METHOD"
430 [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY"
431 [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL"
432 [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID"
433 [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature."
434 [ -n "$CHOWN_USER" ] && echo " Output owner: $CHOWN_USER"
435 [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
436 [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS"
437 [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE"
438 [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA/XZ) compression."
439 [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
440 [ -n "$VERBOSE" ] && echo " Using VERBOSE mode."
441 [ -n "$PACK_ARTIFACTS" ] && echo " Will prepare packed artifacts and ensure clean build."
442 [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation."
443 if [ -n "$BOOTSTRAP_ONLY" ] ; then
444 echo " Bootstrapping only and not building (files for) ISO."
446 [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file."
447 [ -n "$SKIP_NETBOOT" ] && echo " Skipping creation of NETBOOT package."
448 [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file."
449 [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE."
450 [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched."
453 echo -n "Is this ok for you? [y/N] "
455 if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
456 bailout 1 "Exiting as requested."
462 # clean up before start {{{
463 if [ -n "${PACK_ARTIFACTS}" ]; then
464 echo "Wiping old artifacts"
465 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
466 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
467 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && rm -r "${ISO_OUTPUT}"
468 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && rm -r "${LOG_OUTPUT}"
469 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && rm -r "${NETBOOT}"
473 # create log file {{{
474 [ -n "$LOGFILE" ] || LOGFILE=${LOG_OUTPUT}/grml-live.log
475 mkdir -p $(dirname "${LOGFILE}")
477 chown root:adm $LOGFILE
481 # clean/zero/remove logfiles {{{
483 if [ -n "$PRESERVE_LOGFILE" ] ; then
484 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
486 # make sure it is empty (as it is e.g. appended to grml-live-db)
490 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
491 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
492 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
493 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
494 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
495 rm -f /var/log/fai/"$HOSTNAME"/last \
496 /var/log/fai/"$HOSTNAME"/last-dirinstall \
497 /var/log/fai/"$HOSTNAME"/last-softupdate
502 # source config and startup {{{
503 if [ -n "$CONFIG" ] ; then
504 if ! [ -f "$CONFIG" ] ; then
505 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
506 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
509 log "Sourcing $CONFIG"
514 start_seconds=$(cut -d . -f 1 /proc/uptime)
515 log "------------------------------------------------------------------------------"
516 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
517 log "Using local config file: $LOCAL_CONFIG"
518 log "Executed grml-live command line:"
521 einfo "Logging actions to logfile $LOGFILE"
524 # dump config variables into file, for script access {{{
527 '^(GRML_NAME|RELEASENAME|DATE|VERSION|SUITE|ARCH|DISTRI_NAME|USERNAME|HOSTNAME|APT_PROXY)=' \
532 if [ -n "${UNPACK_CHROOT}" ]; then
533 log "Unpacking chroot from ${UNPACK_CHROOT}"
534 einfo "Unpacking chroot from ${UNPACK_CHROOT}"
535 [ -d "$CHROOT_OUTPUT" ] || mkdir -p "${CHROOT_OUTPUT}"
536 tar -xf "${UNPACK_CHROOT}" -C "${CHROOT_OUTPUT}/" --strip-components 1 ; RC=$?
537 if [ "$RC" != 0 ] ; then
545 # cleanup CHROOT_ARCHIVE now {{{
546 if [ -n "${PACK_ARTIFACTS}" ]; then
547 # can't do this earlier, as UNPACK_CHROOT might point to CHROOT_ARCHIVE
548 [ -n "${CHROOT_ARCHIVE}" -a -f "${CHROOT_ARCHIVE}" ] && rm "${CHROOT_ARCHIVE}"
552 # on-the-fly configuration {{{
553 if [ -n "$FAI_DEBOOTSTRAP" ] ; then
554 sed "s#^FAI_DEBOOTSTRAP=.*#FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"#" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
557 # does this suck? YES!
558 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
560 unstable) SUITE='sid' ; CLASSES="DEBIAN_UNSTABLE,$CLASSES" ;;
561 *) CLASSES="DEBIAN_$(echo $SUITE | tr 'a-z' 'A-Z'),$CLASSES";;
563 export SUITE # make sure it's available in FAI scripts
565 for file in "$LIVE_CONF" "$LOCAL_CONFIG" "$NFSROOT_CONF" ; do
566 if [ -n "$file" ] ; then
567 sed "s|^FAI_DEBOOTSTRAP=\"[a-z]* |FAI_DEBOOTSTRAP=\"$SUITE |" "$file" | sponge "$file"
571 # validate whether the specified architecture class matches the
572 # architecture (option), otherwise installation of kernel will fail
573 if echo $CLASSES | grep -qi i386 ; then
574 if ! [[ "$ARCH" == "i386" ]] ; then
575 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
576 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
577 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
581 elif echo $CLASSES | grep -qi amd64 ; then
582 if ! [[ "$ARCH" == "amd64" ]] ; then
583 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
584 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
585 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
591 if grep -q -- 'FAI_DEBOOTSTRAP_OPTS.*--arch' "$NFSROOT_CONF" ; then
592 sed "s/--arch [a-z0-9]* /--arch $ARCH /" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
594 sed "s|^FAI_DEBOOTSTRAP_OPTS=\"\(.*\)|FAI_DEBOOTSTRAP_OPTS=\"--arch $ARCH \1|" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
598 # CHROOT_OUTPUT - execute FAI {{{
599 if [ -n "$BUILD_DIRTY" ]; then
600 log "Skipping stage 'fai' as requested via option -B"
601 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
603 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
605 # provide inform fai about the ISO we build
606 [ -d "$CHROOT_OUTPUT/etc/" ] || mkdir -p "$CHROOT_OUTPUT/etc/"
607 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
608 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
609 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
611 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
612 FAI_ACTION=softupdate
614 FAI_ACTION=dirinstall
617 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
618 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
619 log "Error: does not look like you have a working chroot. Updating/building not possible."
620 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
626 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
627 log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
628 ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
630 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
632 if [ -n "${MIRROR_DIRECTORY}" ] ; then
633 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
634 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
637 mkdir -p "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
638 mount --bind "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
640 # tell dpkg to use "unsafe io" during the build
641 [ -d "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d" ] || mkdir -p "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d"
642 echo force-unsafe-io > "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d/unsafe-io"
644 log "Executed FAI command line:"
645 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"
646 BUILD_ONLY="$BUILD_ONLY" BOOTSTRAP_ONLY="$BOOTSTRAP_ONLY" GRML_LIVE_CONFIG="$CONFIGDUMP" fai $VERBOSE \
647 -C "$GRML_FAI_CONFIG" -s "file:///$GRML_FAI_CONFIG/config" -c"$CLASSES" \
648 -u "$HOSTNAME" "$FAI_ACTION" "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
649 RC="$PIPESTATUS" # notice: bash-only
651 rm -f "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d/unsafe-io"
653 FORCE_ISO_REBUILD=true
655 if [ "$RC" != 0 ] ; then
656 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
657 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
661 # move fai logs into grml_logs directory
662 mkdir -p "$LOG_OUTPUT"/fai/
663 cp -r "$CHROOT_OUTPUT"/var/log/fai/"$HOSTNAME"/last/* "$LOG_OUTPUT"/fai/
664 rm -rf "$CHROOT_OUTPUT"/var/log/fai
665 # copy fai package list
666 cp "$CHROOT_OUTPUT"/var/log/install_packages.list "$LOG_OUTPUT"/fai/
668 chown root:adm "$LOG_OUTPUT"/fai/*
669 chmod 664 "$LOG_OUTPUT"/fai/*
673 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
675 CHECKLOG="$LOG_OUTPUT"/fai/
676 if [ -r "$CHECKLOG/software.log" ] ; then
677 # 1 errors during executing of commands
678 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
679 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
680 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
681 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
682 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
685 if [ -r "$CHECKLOG/shell.log" ] ; then
686 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
689 if [ -n "$ERROR" ] ; then
690 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
691 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
692 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
696 log "Finished execution of stage 'fai dirinstall' [$(date)]"
697 einfo "Finished execution of stage 'fai dirinstall'"
703 # package validator {{{
704 CHECKLOG=/var/log/fai/$HOSTNAME/last
705 if [ -r "$CHECKLOG/dpkg.selections" ] ; then
706 package_count=$(wc -l "$CHECKLOG/dpkg.selections" | awk '{print $1}')
708 package_count="unknown"
712 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
714 # check for missing packages
715 if ! [ -s "$CHECKLOG/package_errors.log" ] ; then
716 einfo "No missing packages found, generating empty junit report."
718 cat > "${REPORT_MISSING_PACKAGES}" << EOF
719 <?xml version="1.0" encoding="UTF-8"?>
720 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="0" errors="0" skipped="0" assertions="0">
721 <testcase name="test_missing_packages" time="0" assertions="0">
731 einfo "Missing packages found, generating junit report."
733 if [ -r "$CHECKLOG/package_errors.log" ] ; then
734 package_errors=$(wc -l "$CHECKLOG/package_errors.log" | awk '{print $1}')
736 package_errors="unknown"
740 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
742 cat > "${REPORT_MISSING_PACKAGES}" << EOF
743 <?xml version="1.0" encoding="UTF-8"?>
744 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="${package_errors}" errors="${package_errors}" skipped="0" assertions="0">
747 for package in $(awk '{print $5}' "${CHECKLOG}/package_errors.log" | sed 's/\.$//') ; do
748 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
749 <testcase name="test_missing_packages_${package}" time="0" assertions="0">
750 <failure type="RuntimeError" message="Package ${package} is missing">
751 Package $package is missing in chroot
757 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
766 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
767 eerror "The following packages were requested for installation but could not be processed:"
768 cat "$CHECKLOG/package_errors.log"
769 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
773 ewarn "The following packages were requested for installation but could not be processed:"
774 cat "$CHECKLOG/package_errors.log"
780 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
781 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
782 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
785 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
786 if [ -n "$BOOTSTRAP_ONLY" ] ; then
787 log "Skipping stage 'boot' as building with bootstrap only."
788 ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0
790 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
791 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
792 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
795 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
796 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
798 # if we don't have an initrd we a) can't boot and b) there was an error
799 # during build, so check for the file:
800 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
801 if [ -n "$INITRD" ] ; then
802 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.gz
803 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
805 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
806 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
810 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
811 if [ -n "$KERNEL_IMAGE" ] ; then
812 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/linux26
814 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
815 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
819 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
820 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
821 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
822 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
826 # copy _required_ isolinux files
827 for file in ifcpu64.c32 isolinux.bin vesamenu.c32; do
828 copy_addon_file "${file}" /usr/lib/syslinux isolinux
831 # *always* copy files to output directory so the variables
832 # get adjusted according to the build.
833 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
835 if [ -n "$NO_ADDONS" ] ; then
836 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
837 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
839 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
840 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
841 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
843 # copy addons from system packages or grml-live-compat
844 copy_addon_file ipxe.lkrn /usr/lib/ipxe addons
845 copy_addon_file pci.ids /usr/share/misc addons
846 copy_addon_file memtest86+.bin /boot addons
847 for file in memdisk chain.c32 hdt.c32 menu.c32; do
848 copy_addon_file "${file}" /usr/lib/syslinux addons
851 # make memtest filename FAT16/8.3 compatible
852 mv "${BUILD_OUTPUT}/boot/addons/memtest86+.bin" \
853 "${BUILD_OUTPUT}/boot/addons/memtest"
855 # copy only files so we can handle bsd4grml on its own
856 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
857 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
860 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
861 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
862 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
864 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
865 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
867 log "Missing addon file: bsd4grml"
868 ewarn "Missing addon file: bsd4grml" ; eend 0
872 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
875 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
876 mkdir -p "${BUILD_OUTPUT}/boot/grub"
878 cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
880 # copy grub files from target
881 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.mod "${BUILD_OUTPUT}"/boot/grub/
882 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.o "${BUILD_OUTPUT}"/boot/grub/
883 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.lst "${BUILD_OUTPUT}"/boot/grub/
884 cp -a "${CHROOT_OUTPUT}"/usr/share/grub/ascii.pf2 "${BUILD_OUTPUT}"/boot/grub/
885 cp -a "${CHROOT_OUTPUT}"/boot/grub/core.img "${BUILD_OUTPUT}"/boot/grub/
887 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
888 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
889 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
893 [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML
894 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/
896 # adjust boot splash information:
897 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
898 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
899 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
901 if [ -r "$BUILD_OUTPUT"/GRML/grml-version ] ; then
902 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version
903 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/grml-version
906 # make sure the squashfs filename is set accordingly:
907 SQUASHFS_NAME="$GRML_NAME.squashfs"
909 if [ -n "$NO_BOOTID" ] ; then
910 log 'Skipping bootid feature as requested via $NO_BOOTID.'
911 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
913 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
914 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
915 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
916 log "Generating /conf/bootid.txt with entry ${BOOTID}."
917 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
921 # adjust all variables in the templates with the according distribution information
922 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
923 "${BUILD_OUTPUT}"/boot/grub/* ; do
924 if [ -r "${file}" ] ; then
925 sed -i "s/%ARCH%/$ARCH/g" "${file}"
926 sed -i "s/%DATE%/$DATE/g" "${file}"
927 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
928 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
929 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
930 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
931 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
932 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
933 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
934 sed -i "s/%VERSION%/$VERSION/g" "${file}"
936 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s/ boot=live/ boot=live $DEFAULT_BOOTOPTIONS/" "${file}"
938 if [ -n "$NO_BOOTID" ] ; then
939 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
941 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
946 # adjust bootsplash accordingly but make sure the string has the according lenght
947 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
948 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
949 for file in f4 f5 ; do
950 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
951 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
952 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
956 # generate addon list
957 rm -f "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
958 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
959 include_name=$(basename "$name")
960 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
963 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
964 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
965 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
966 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
967 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
968 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
970 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
971 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
974 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
975 if [ ! -n "$NO_ADDONS" ] ; then
976 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
978 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
979 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
980 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
981 else # assume we are building a custom distribution:
982 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
983 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
984 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
985 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
987 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
991 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
992 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
993 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
997 # use old style console based isolinux method only if requested:
998 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
999 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1000 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1001 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1002 einfo "include for console.cfg already found, nothing to do."
1005 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1006 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1007 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1011 log 'Using graphical boot menu.'
1012 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
1013 log "include for vesamenu.cfg already found, nothing to do."
1015 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1016 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1020 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
1021 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
1024 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
1025 if ! [ -r "$DPKG_LIST" ] ; then
1026 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
1028 einfo "Storing package list information as /GRML/${GRML_NAME}-packages.txt on ISO."
1029 cp "$DPKG_LIST" "${BUILD_OUTPUT}/GRML/${GRML_NAME}-packages.txt"
1033 # autostart for Windows:
1034 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
1035 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
1038 FORCE_ISO_REBUILD=true
1039 einfo "Finished execution of stage 'boot'" ; eend 0
1043 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
1044 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
1048 # support installation of local files into the chroot/ISO
1049 if [ -n "$CHROOT_INSTALL" ] ; then
1050 if ! [ -d "$CHROOT_INSTALL" ] ; then
1051 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1052 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1054 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1055 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1056 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
1058 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
1059 FORCE_ISO_REBUILD=true
1063 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1064 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
1065 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
1066 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
1067 log "Skipping stage 'squashfs' as requested via option -q or -N"
1068 ewarn "Skipping stage 'squashfs' as requested via option -q or -N" ; eend 0
1070 [ -d "$BUILD_OUTPUT"/live ] || mkdir "$BUILD_OUTPUT"/live
1071 # make sure we don't leave (even an empty) base.tgz:
1072 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
1074 # if unconfigured default to squashfs-tools' mksquashfs binary
1075 if [ -z "$SQUASHFS_BINARY" ] ; then
1076 SQUASHFS_BINARY='mksquashfs'
1079 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
1080 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
1081 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
1083 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
1084 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
1088 # use sane defaults if $SQUASHFS_OPTIONS isn't set
1089 if [ -z "$SQUASHFS_OPTIONS" ] ; then
1090 # use blocksize 256k as this gives best result with regards to time + compression
1091 SQUASHFS_OPTIONS="-b 256k"
1093 # set lzma/xz compression by default, unless -z option has been specified on command line
1094 if [ -z "$SQUASHFS_ZLIB" ] ; then
1095 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
1097 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
1101 # support exclusion of files via exclude-file:
1102 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
1103 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE -wildcards"
1106 # get rid of unnecessary files when building grml-small for final release:
1107 if echo "$CLASSES" | grep -q GRML_SMALL ; then
1108 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
1112 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
1114 # informational stuff
1115 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1116 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1117 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1119 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1121 if $SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \
1122 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1123 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/filesystem.module
1124 log "Finished execution of stage 'squashfs' [$(date)]"
1125 einfo "Finished execution of stage 'squashfs'" ; eend 0
1127 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1128 log "$(cat $SQUASHFS_STDERR)"
1129 eerror "Error: there was a critical error executing stage 'squashfs':"
1130 cat "${SQUASHFS_STDERR}"
1135 FORCE_ISO_REBUILD=true
1138 # create md5sum file:
1139 if [ -z "$BOOTSTRAP_ONLY" ] ; then
1140 ( cd $BUILD_OUTPUT/GRML &&
1141 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1145 # ISO_OUTPUT - mkisofs {{{
1146 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1147 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1149 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1150 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1151 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1152 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1155 # Just until http://bts.grml.org/grml/issue945 has been resolved.
1156 # HYBRID_METHOD defaults to manifold, so make sure the default works OOTB.
1157 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1158 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1159 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1160 HYBRID_METHOD='grub2'
1164 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1165 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1166 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1167 elif [ -n "$SKIP_MKISOFS" ] ; then
1168 log "Skipping stage 'iso build' as requested via option -n or -N"
1169 ewarn "Skipping stage 'iso build' as requested via option -n or -N" ; eend 0
1171 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1173 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1174 log "Forcing rebuild of ISO because files on ISO have been modified."
1175 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1178 # support xorriso as well mkisofs and genisoimage
1179 if which xorriso >/dev/null 2>&1 ; then
1180 MKISOFS='xorriso -as mkisofs'
1181 elif which mkisofs >/dev/null 2>&1; then
1183 elif which genisoimage >/dev/null 2>&1; then
1184 MKISOFS='genisoimage'
1186 log "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO."
1187 eerror "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO." ; eend 1
1193 # using -eltorito-alt-boot is limited to xorriso for now
1196 einfo "Using xorriso for ISO generation." ; eend 0
1199 if ! dpkg --compare-versions $(dpkg-query -W -f='${Version}\n' xorriso 2>/dev/null) gt-nl 1.1.6-1 ; then
1200 log "Disabling (U)EFI boot support since xorriso version is not recent enough."
1201 ewarn "Disabling (U)EFI boot support since xorriso version is not recent enough." ; eend 0
1203 log "xorriso with -eltorito-alt-boot present, enabling (U)EFI boot support."
1204 einfo "xorriso with -eltorito-alt-boot present, enabling (U)EFI boot support." ; eend 0
1206 if [ -r "${CHROOT_OUTPUT}/var/lib/grml_live_efi.img" ] ; then
1207 einfo "Found /var/lib/grml_live_efi.img - moving to /boot/efi.img for ISO."
1208 log "Found /var/lib/grml_live_efi.img - moving to /boot/efi.img for ISO."
1209 mv "${CHROOT_OUTPUT}/var/lib/grml_live_efi.img" "${BUILD_OUTPUT}/boot/efi.img"
1213 if [ -r "${CHROOT_OUTPUT}/var/lib/grml_live_bootx64.efi" ] ; then
1214 einfo "Found /var/lib/grml_live_bootx64.efi - moving to /efi/boot/bootx64.efi for ISO"
1215 log "Found /var/lib/grml_live_bootx64.efi - moving to /efi/boot/bootx64.efi for ISO"
1216 mkdir -p "${BUILD_OUTPUT}/efi/boot/"
1217 mv "${CHROOT_OUTPUT}/var/lib/grml_live_bootx64.efi" "${BUILD_OUTPUT}/efi/boot/bootx64.efi"
1221 if [ -r "${BUILD_OUTPUT}"/boot/efi.img ] ; then
1222 einfo "/boot/efi.img found and amd64 architecture present, extending boot arguments."
1223 log "/boot/efi.img found and amd64 architecture present, extending boot arguments."
1224 BOOT_ARGS="$BOOT_ARGS -boot-info-table -eltorito-alt-boot -e boot/efi.img -no-emul-boot"
1236 if cd "$BUILD_OUTPUT" ; then
1237 if [ "$BOOT_METHOD" = "grub2" ]; then
1238 # make a 2048-byte bootsector for El Torito
1239 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1240 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1241 echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
1242 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1244 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1245 $MKISOFS -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1246 -l -r -J $BOOT_ARGS -no-pad \
1247 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1248 # both of these need core.img there, so it’s easier to write it here
1249 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1250 # must be <= 30720 bytes
1251 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1252 conv=notrunc bs=512 seek=4 2>/dev/null
1255 # pad the output ISO to multiples of 256 KiB for partition table support
1256 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1257 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1258 siz=$((cyls * 16 * 32 * 512)) # size after padding
1259 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1260 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1262 # support disabling hybrid ISO image
1263 if [ "$HYBRID_METHOD" = "disable" ] ; then\
1264 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1265 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1267 elif [ "$HYBRID_METHOD" = "manifold" ] ; then
1268 # isoinfo is part of both mkisofs and genisoimage so we're good
1269 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1270 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN[;1]* *$/s//\1/p')
1271 if ! [ -r boot/grub/core.img ] ; then
1272 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1273 elif [ "${bootoff:-0}" -lt 1 ] ; then
1274 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1276 log "Creating hybrid ISO file with manifold method"
1277 einfo "Creating hybrid ISO file with manifold method"
1278 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1279 # 512 bytes: MBR, partition table, load GRUB 2
1280 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1282 # read only one but 2048-byte sized (scale: << 2) sector
1283 echo $bootoff $bootoff | \
1284 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1285 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1288 # use isohybrid as default
1290 if ! which isohybrid >/dev/null 2>&1 ; then
1291 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1293 log "Creating hybrid ISO file with isohybrid method"
1294 einfo "Creating hybrid ISO file with isohybrid method"
1295 # Notes for consideration:
1296 # "-entry 4 -type 1c"
1297 # * using 4 as the partition number is supposed to help with BIOSes
1298 # that only support USB-Zip boot
1299 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1300 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1301 # to get the BIOS even look at the partition created by isohybrid
1302 if isohybrid --help | grep -q -- --uefi ; then
1303 einfo "Detected uefi support for isohybrid, enabling."
1304 ISOHYBRID_OPTIONS=--uefi
1307 log "isohybrid $ISOHYBRID_OPTIONS ${ISO_OUTPUT}/${ISO_NAME}"
1308 isohybrid $ISOHYBRID_OPTIONS "${ISO_OUTPUT}/${ISO_NAME}"
1313 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1314 case $CLASSES in *RELEASE*)
1317 if cd $ISO_OUTPUT ; then
1318 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1319 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1320 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1321 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1330 if [ "$RC" = 0 ] ; then
1331 log "Finished execution of stage 'iso build' [$(date)]"
1332 einfo "Finished execution of stage 'iso build'" ; eend 0
1334 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1335 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1341 # netboot package {{{
1342 create_netbootpackage() {
1343 local OUTPUT_FILE="${NETBOOT}/grml_netboot_package_${GRML_NAME}_${VERSION}.tar.bz2"
1345 if [ -f "${OUTPUT_FILE}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1346 log "Skipping stage 'netboot' as $OUTPUT_FILE exists already."
1347 ewarn "Skipping stage 'netboot' as $OUTPUT_FILE exists already." ; eend 0
1349 elif [ -n "$SKIP_NETBOOT" ] ; then
1350 log "Skipping stage 'netboot' as requested via option -Q"
1351 ewarn "Skipping stage 'netboot' as requested via option -Q" ; eend 0
1357 if ! [ -r "${CHROOT}/usr/lib/syslinux/pxelinux.0" ] ; then
1358 ewarn "File /usr/lib/syslinux/pxelinux.0 not found in build chroot." ; eend 0
1360 einfo "Install syslinux[-common] package in chroot to get a netboot package."
1365 local OUTPUTDIR="${NETBOOT}/build_tmp"
1366 local WORKING_DIR="${OUTPUTDIR}/grml_netboot_package_${GRML_NAME}_${VERSION}/tftpboot/"
1368 mkdir -p "$WORKING_DIR"
1370 cp "${CHROOT_OUTPUT}"/boot/vmlinuz-* "$WORKING_DIR"/linux26
1371 cp "${CHROOT_OUTPUT}"/boot/initrd.img-* "$WORKING_DIR"/initrd.img
1372 cp "${CHROOT_OUTPUT}"/usr/lib/syslinux/pxelinux.0 "${WORKING_DIR}/pxelinux.0"
1374 if [ -r "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" ] ; then
1375 mkdir -p "${WORKING_DIR}/pxelinux.cfg/default"
1376 cp "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" "${WORKING_DIR}/pxelinux.cfg/default"
1378 ewarn "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found." ; eend 0
1381 mkdir -p "${WORKING_DIR}/pxelinux.cfg"
1383 if tar -C "$OUTPUTDIR" -jcf "${OUTPUT_FILE}" "grml_netboot_package_${GRML_NAME}_${VERSION}" ; then
1384 sha1sum "${OUTPUT_FILE}" > "${OUTPUT_FILE}.sha1"
1385 einfo "Generated netboot package ${OUTPUT_FILE}" ; eend 0
1386 rm -rf "${OUTPUTDIR}"
1388 rm -rf "${OUTPUTDIR}"
1389 eerror "Could not generate netboot package ${OUTPUT_FILE}" ; eend 1
1394 create_netbootpackage
1397 # pack artifacts {{{
1398 if [ -n "$PACK_ARTIFACTS" ]; then
1399 log "Packing artifcats"
1400 einfo "Packing artifacts"
1401 [ -f "${CHROOT_ARCHIVE}" ] && rm -r "${CHROOT_ARCHIVE}"
1402 tar -c -a -f ${CHROOT_ARCHIVE} --preserve-permissions -C "$(dirname ${CHROOT_OUTPUT})" "$(basename ${CHROOT_OUTPUT})"
1407 # log build information to database if grml-live-db is installed and enabled {{{
1409 if [ -d /usr/share/grml-live-db ] ; then
1412 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1413 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1414 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1415 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1417 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1418 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1419 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1423 # disable by default for now, not sure whether really everyone is using a local db file
1424 #if ! touch "$DPKG_DATABASE" ; then
1425 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1429 if ! [ -r "$DPKG_LIST" ] ; then
1430 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1431 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1433 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1434 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1435 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1438 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1454 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1455 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1457 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1459 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1463 ## END OF FILE #################################################################
1464 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=2