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 -e <iso_name> extract ISO and squashfs contents from iso_name
50 -F force execution without prompting
51 -g <grml_name> set the grml flavour name
52 -h display short usage information and exit
53 -i <iso_name> name of ISO
54 -I <src_directory> directory which provides files that should become
55 part of the chroot/ISO
56 -n skip generation of ISO
57 -N bootstrap (build chroot) only, do not create files for ISO
58 -o <output_directory> main output directory of the build process
60 -Q skip netboot package build
61 -r <release_name> release name
62 -s <suite> Debian suite; values: etch, lenny, squeeze, sid
63 -t <template_directory> place of the templates
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:e:g:i:I:o:r:s: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 e) EXTRACT_ISO_NAME="$(readlink -f $OPTARG)" ;;
304 g) GRML_NAME="$OPTARG" ;;
305 i) ISO_NAME="$OPTARG" ;;
306 I) CHROOT_INSTALL="$OPTARG" ;;
308 N) BOOTSTRAP_ONLY=1; SKIP_MKISOFS=1; SKIP_MKSQUASHFS=1 ;;
309 o) OUTPUT="$(readlink -f $OPTARG)" ;;
310 q) SKIP_MKSQUASHFS=1 ;;
312 r) RELEASENAME="$OPTARG" ;;
313 s) SUITE="$OPTARG" ;;
314 t) TEMPLATE_DIRECTORY="$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 "$EXTRACT_ISO_NAME" ] && echo " Extract ISO: $EXTRACT_ISO_NAME"
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)=' \
531 # unpack iso/squashfs {{{
533 if [ -n "$EXTRACT_ISO_NAME" ]; then
534 log "Unpacking ISO from ${EXTRACT_ISO_NAME}"
535 einfo "Unpacking ISO from ${EXTRACT_ISO_NAME}"
536 local mountpoint=$(mktemp -d)
538 mount -o loop "${EXTRACT_ISO_NAME}" "$mountpoint" ; rc=$?
539 if [ "$rc" != 0 ]; then
542 eerror "mount failed"
546 unsquashfs -d "${CHROOT_OUTPUT}" "${mountpoint}"/live/*.squashfs ; rc=$?
549 if [ "$rc" != 0 ]; then
550 log "unsquashfs failed"
551 eerror "unsquashfs failed"
560 # cleanup CHROOT_ARCHIVE now {{{
561 if [ -n "${PACK_ARTIFACTS}" ]; then
562 [ -n "${CHROOT_ARCHIVE}" -a -f "${CHROOT_ARCHIVE}" ] && rm "${CHROOT_ARCHIVE}"
566 # on-the-fly configuration {{{
567 if [ -n "$FAI_DEBOOTSTRAP" ] ; then
568 sed "s#^FAI_DEBOOTSTRAP=.*#FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"#" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
571 # does this suck? YES!
572 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
574 unstable) SUITE='sid' ; CLASSES="DEBIAN_UNSTABLE,$CLASSES" ;;
575 *) CLASSES="DEBIAN_$(echo $SUITE | tr 'a-z' 'A-Z'),$CLASSES";;
577 export SUITE # make sure it's available in FAI scripts
579 for file in "$LIVE_CONF" "$LOCAL_CONFIG" "$NFSROOT_CONF" ; do
580 if [ -n "$file" ] ; then
581 sed "s|^FAI_DEBOOTSTRAP=\"[a-z]* |FAI_DEBOOTSTRAP=\"$SUITE |" "$file" | sponge "$file"
585 # validate whether the specified architecture class matches the
586 # architecture (option), otherwise installation of kernel will fail
587 if echo $CLASSES | grep -qi i386 ; then
588 if ! [[ "$ARCH" == "i386" ]] ; then
589 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
590 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
591 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
595 elif echo $CLASSES | grep -qi amd64 ; then
596 if ! [[ "$ARCH" == "amd64" ]] ; then
597 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
598 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
599 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
605 if grep -q -- 'FAI_DEBOOTSTRAP_OPTS.*--arch' "$NFSROOT_CONF" ; then
606 sed "s/--arch [a-z0-9]* /--arch $ARCH /" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
608 sed "s|^FAI_DEBOOTSTRAP_OPTS=\"\(.*\)|FAI_DEBOOTSTRAP_OPTS=\"--arch $ARCH \1|" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
612 # CHROOT_OUTPUT - execute FAI {{{
613 if [ -n "$BUILD_DIRTY" ]; then
614 log "Skipping stage 'fai' as requested via option -B"
615 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
617 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
619 # provide inform fai about the ISO we build
620 [ -d "$CHROOT_OUTPUT/etc/" ] || mkdir -p "$CHROOT_OUTPUT/etc/"
621 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
622 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
623 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
625 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
626 FAI_ACTION=softupdate
628 FAI_ACTION=dirinstall
631 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
632 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
633 log "Error: does not look like you have a working chroot. Updating/building not possible."
634 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
640 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
641 log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
642 ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
644 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
646 if [ -n "${MIRROR_DIRECTORY}" ] ; then
647 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
648 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
651 mkdir -p "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
652 mount --bind "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
654 # tell dpkg to use "unsafe io" during the build
655 [ -d "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d" ] || mkdir -p "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d"
656 echo force-unsafe-io > "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d/unsafe-io"
658 log "Executed FAI command line:"
659 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"
660 BUILD_ONLY="$BUILD_ONLY" BOOTSTRAP_ONLY="$BOOTSTRAP_ONLY" GRML_LIVE_CONFIG="$CONFIGDUMP" fai $VERBOSE \
661 -C "$GRML_FAI_CONFIG" -s "file:///$GRML_FAI_CONFIG/config" -c"$CLASSES" \
662 -u "$HOSTNAME" "$FAI_ACTION" "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
663 RC="$PIPESTATUS" # notice: bash-only
665 rm -f "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d/unsafe-io"
667 FORCE_ISO_REBUILD=true
669 if [ "$RC" != 0 ] ; then
670 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
671 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
675 # move fai logs into grml_logs directory
676 mkdir -p "$LOG_OUTPUT"/fai/
677 cp -r "$CHROOT_OUTPUT"/var/log/fai/"$HOSTNAME"/last/* "$LOG_OUTPUT"/fai/
678 rm -rf "$CHROOT_OUTPUT"/var/log/fai
679 # copy fai package list
680 cp "$CHROOT_OUTPUT"/var/log/install_packages.list "$LOG_OUTPUT"/fai/
682 chown root:adm "$LOG_OUTPUT"/fai/*
683 chmod 664 "$LOG_OUTPUT"/fai/*
687 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
689 CHECKLOG="$LOG_OUTPUT"/fai/
690 if [ -r "$CHECKLOG/software.log" ] ; then
691 # 1 errors during executing of commands
692 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
693 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
694 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
695 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
696 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
699 if [ -r "$CHECKLOG/shell.log" ] ; then
700 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
703 if [ -n "$ERROR" ] ; then
704 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
705 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
706 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
710 log "Finished execution of stage 'fai dirinstall' [$(date)]"
711 einfo "Finished execution of stage 'fai dirinstall'"
717 # package validator {{{
718 CHECKLOG=/var/log/fai/$HOSTNAME/last
719 if [ -r "$CHECKLOG/dpkg.selections" ] ; then
720 package_count=$(wc -l "$CHECKLOG/dpkg.selections" | awk '{print $1}')
722 package_count="unknown"
726 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
728 # check for missing packages
729 if ! [ -s "$CHECKLOG/package_errors.log" ] ; then
730 einfo "No missing packages found, generating empty junit report."
732 cat > "${REPORT_MISSING_PACKAGES}" << EOF
733 <?xml version="1.0" encoding="UTF-8"?>
734 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="0" errors="0" skipped="0" assertions="0">
735 <testcase name="test_missing_packages" time="0" assertions="0">
745 einfo "Missing packages found, generating junit report."
747 if [ -r "$CHECKLOG/package_errors.log" ] ; then
748 package_errors=$(wc -l "$CHECKLOG/package_errors.log" | awk '{print $1}')
750 package_errors="unknown"
754 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
756 cat > "${REPORT_MISSING_PACKAGES}" << EOF
757 <?xml version="1.0" encoding="UTF-8"?>
758 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="${package_errors}" errors="${package_errors}" skipped="0" assertions="0">
761 for package in $(awk '{print $5}' "${CHECKLOG}/package_errors.log" | sed 's/\.$//') ; do
762 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
763 <testcase name="test_missing_packages_${package}" time="0" assertions="0">
764 <failure type="RuntimeError" message="Package ${package} is missing">
765 Package $package is missing in chroot
771 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
780 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
781 eerror "The following packages were requested for installation but could not be processed:"
782 cat "$CHECKLOG/package_errors.log"
783 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
787 ewarn "The following packages were requested for installation but could not be processed:"
788 cat "$CHECKLOG/package_errors.log"
794 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
795 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
796 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
799 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
800 if [ -n "$BOOTSTRAP_ONLY" ] ; then
801 log "Skipping stage 'boot' as building with bootstrap only."
802 ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0
804 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
805 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
806 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
809 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
810 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
812 # if we don't have an initrd we a) can't boot and b) there was an error
813 # during build, so check for the file:
814 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
815 if [ -n "$INITRD" ] ; then
816 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.gz
817 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
819 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
820 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
824 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
825 if [ -n "$KERNEL_IMAGE" ] ; then
826 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/linux26
828 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
829 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
833 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
834 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
835 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
836 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
840 # copy _required_ isolinux files
841 for file in ifcpu64.c32 isolinux.bin vesamenu.c32; do
842 copy_addon_file "${file}" /usr/lib/syslinux isolinux
845 # *always* copy files to output directory so the variables
846 # get adjusted according to the build.
847 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
849 if [ -n "$NO_ADDONS" ] ; then
850 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
851 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
853 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
854 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
855 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
857 # copy addons from system packages or grml-live-compat
858 copy_addon_file ipxe.lkrn /usr/lib/ipxe addons
859 copy_addon_file pci.ids /usr/share/misc addons
860 copy_addon_file memtest86+.bin /boot addons
861 for file in memdisk chain.c32 hdt.c32 menu.c32; do
862 copy_addon_file "${file}" /usr/lib/syslinux addons
865 # make memtest filename FAT16/8.3 compatible
866 mv "${BUILD_OUTPUT}/boot/addons/memtest86+.bin" \
867 "${BUILD_OUTPUT}/boot/addons/memtest"
869 # copy only files so we can handle bsd4grml on its own
870 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
871 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
874 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
875 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
876 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
878 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
879 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
881 log "Missing addon file: bsd4grml"
882 ewarn "Missing addon file: bsd4grml" ; eend 0
886 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
889 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
890 mkdir -p "${BUILD_OUTPUT}/boot/grub"
892 cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
894 # copy grub files from target
895 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.mod "${BUILD_OUTPUT}"/boot/grub/
896 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.o "${BUILD_OUTPUT}"/boot/grub/
897 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.lst "${BUILD_OUTPUT}"/boot/grub/
898 cp -a "${CHROOT_OUTPUT}"/usr/share/grub/ascii.pf2 "${BUILD_OUTPUT}"/boot/grub/
899 cp -a "${CHROOT_OUTPUT}"/boot/grub/core.img "${BUILD_OUTPUT}"/boot/grub/
901 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
902 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
903 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
907 [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML
908 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/
910 # adjust boot splash information:
911 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
912 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
913 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
915 if [ -r "$BUILD_OUTPUT"/GRML/grml-version ] ; then
916 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version
917 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/grml-version
920 # make sure the squashfs filename is set accordingly:
921 SQUASHFS_NAME="$GRML_NAME.squashfs"
923 if [ -n "$NO_BOOTID" ] ; then
924 log 'Skipping bootid feature as requested via $NO_BOOTID.'
925 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
927 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
928 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
929 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
930 log "Generating /conf/bootid.txt with entry ${BOOTID}."
931 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
935 # adjust all variables in the templates with the according distribution information
936 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
937 "${BUILD_OUTPUT}"/boot/grub/* ; do
938 if [ -r "${file}" ] ; then
939 sed -i "s/%ARCH%/$ARCH/g" "${file}"
940 sed -i "s/%DATE%/$DATE/g" "${file}"
941 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
942 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
943 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
944 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
945 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
946 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
947 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
948 sed -i "s/%VERSION%/$VERSION/g" "${file}"
950 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s/ boot=live/ boot=live $DEFAULT_BOOTOPTIONS/" "${file}"
952 if [ -n "$NO_BOOTID" ] ; then
953 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
955 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
960 # adjust bootsplash accordingly but make sure the string has the according lenght
961 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
962 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
963 for file in f4 f5 ; do
964 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
965 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
966 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
970 # generate addon list
971 rm -f "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
972 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
973 include_name=$(basename "$name")
974 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
977 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
978 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
979 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
980 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
981 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
982 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
984 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
985 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
988 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
989 if [ ! -n "$NO_ADDONS" ] ; then
990 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
992 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
993 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
994 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
995 else # assume we are building a custom distribution:
996 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
997 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
998 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
999 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1001 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1005 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1006 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1007 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1011 # use old style console based isolinux method only if requested:
1012 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
1013 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1014 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1015 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1016 einfo "include for console.cfg already found, nothing to do."
1019 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1020 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1021 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1025 log 'Using graphical boot menu.'
1026 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
1027 log "include for vesamenu.cfg already found, nothing to do."
1029 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1030 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1034 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
1035 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
1038 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
1039 if ! [ -r "$DPKG_LIST" ] ; then
1040 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
1042 einfo "Storing package list information as /GRML/${GRML_NAME}-packages.txt on ISO."
1043 cp "$DPKG_LIST" "${BUILD_OUTPUT}/GRML/${GRML_NAME}-packages.txt"
1047 # autostart for Windows:
1048 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
1049 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
1052 FORCE_ISO_REBUILD=true
1053 einfo "Finished execution of stage 'boot'" ; eend 0
1057 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
1058 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
1062 # support installation of local files into the chroot/ISO
1063 if [ -n "$CHROOT_INSTALL" ] ; then
1064 if ! [ -d "$CHROOT_INSTALL" ] ; then
1065 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1066 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1068 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1069 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1070 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
1072 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
1073 FORCE_ISO_REBUILD=true
1077 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1078 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
1079 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
1080 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
1081 log "Skipping stage 'squashfs' as requested via option -q or -N"
1082 ewarn "Skipping stage 'squashfs' as requested via option -q or -N" ; eend 0
1084 [ -d "$BUILD_OUTPUT"/live ] || mkdir "$BUILD_OUTPUT"/live
1085 # make sure we don't leave (even an empty) base.tgz:
1086 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
1088 # if unconfigured default to squashfs-tools' mksquashfs binary
1089 if [ -z "$SQUASHFS_BINARY" ] ; then
1090 SQUASHFS_BINARY='mksquashfs'
1093 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
1094 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
1095 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
1097 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
1098 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
1102 # use sane defaults if $SQUASHFS_OPTIONS isn't set
1103 if [ -z "$SQUASHFS_OPTIONS" ] ; then
1104 # use blocksize 256k as this gives best result with regards to time + compression
1105 SQUASHFS_OPTIONS="-b 256k"
1107 # set lzma/xz compression by default, unless -z option has been specified on command line
1108 if [ -z "$SQUASHFS_ZLIB" ] ; then
1109 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
1111 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
1115 # support exclusion of files via exclude-file:
1116 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
1117 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE -wildcards"
1120 # get rid of unnecessary files when building grml-small for final release:
1121 if echo "$CLASSES" | grep -q GRML_SMALL ; then
1122 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
1126 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
1128 # informational stuff
1129 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1130 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1131 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1133 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1135 if $SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \
1136 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1137 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/filesystem.module
1138 log "Finished execution of stage 'squashfs' [$(date)]"
1139 einfo "Finished execution of stage 'squashfs'" ; eend 0
1141 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1142 log "$(cat $SQUASHFS_STDERR)"
1143 eerror "Error: there was a critical error executing stage 'squashfs':"
1144 cat "${SQUASHFS_STDERR}"
1149 FORCE_ISO_REBUILD=true
1152 # create md5sum file:
1153 if [ -z "$BOOTSTRAP_ONLY" ] ; then
1154 ( cd $BUILD_OUTPUT/GRML &&
1155 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1159 # ISO_OUTPUT - mkisofs {{{
1160 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1161 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1163 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1164 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1165 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1166 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1169 # Just until http://bts.grml.org/grml/issue945 has been resolved.
1170 # HYBRID_METHOD defaults to manifold, so make sure the default works OOTB.
1171 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1172 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1173 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1174 HYBRID_METHOD='grub2'
1178 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1179 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1180 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1181 elif [ -n "$SKIP_MKISOFS" ] ; then
1182 log "Skipping stage 'iso build' as requested via option -n or -N"
1183 ewarn "Skipping stage 'iso build' as requested via option -n or -N" ; eend 0
1185 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1187 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1188 log "Forcing rebuild of ISO because files on ISO have been modified."
1189 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1192 # support xorriso as well mkisofs and genisoimage
1193 if which xorriso >/dev/null 2>&1 ; then
1194 MKISOFS='xorriso -as mkisofs'
1195 elif which mkisofs >/dev/null 2>&1; then
1197 elif which genisoimage >/dev/null 2>&1; then
1198 MKISOFS='genisoimage'
1200 log "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO."
1201 eerror "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO." ; eend 1
1207 # using -eltorito-alt-boot is limited to xorriso for now
1210 einfo "Using xorriso for ISO generation." ; eend 0
1213 if ! dpkg --compare-versions $(dpkg-query -W -f='${Version}\n' xorriso 2>/dev/null) gt-nl 1.1.6-1 ; then
1214 log "Disabling (U)EFI boot support since xorriso version is not recent enough."
1215 ewarn "Disabling (U)EFI boot support since xorriso version is not recent enough." ; eend 0
1217 log "xorriso with -eltorito-alt-boot present, enabling (U)EFI boot support."
1218 einfo "xorriso with -eltorito-alt-boot present, enabling (U)EFI boot support." ; eend 0
1220 if [ -r "${CHROOT_OUTPUT}/var/lib/grml_live_efi.img" ] ; then
1221 einfo "Found /var/lib/grml_live_efi.img - moving to /boot/efi.img for ISO."
1222 log "Found /var/lib/grml_live_efi.img - moving to /boot/efi.img for ISO."
1223 mv "${CHROOT_OUTPUT}/var/lib/grml_live_efi.img" "${BUILD_OUTPUT}/boot/efi.img"
1227 if [ -r "${CHROOT_OUTPUT}/var/lib/grml_live_bootx64.efi" ] ; then
1228 einfo "Found /var/lib/grml_live_bootx64.efi - moving to /efi/boot/bootx64.efi for ISO"
1229 log "Found /var/lib/grml_live_bootx64.efi - moving to /efi/boot/bootx64.efi for ISO"
1230 mkdir -p "${BUILD_OUTPUT}/efi/boot/"
1231 mv "${CHROOT_OUTPUT}/var/lib/grml_live_bootx64.efi" "${BUILD_OUTPUT}/efi/boot/bootx64.efi"
1235 if [ -r "${BUILD_OUTPUT}"/boot/efi.img ] ; then
1236 einfo "/boot/efi.img found and amd64 architecture present, extending boot arguments."
1237 log "/boot/efi.img found and amd64 architecture present, extending boot arguments."
1238 BOOT_ARGS="$BOOT_ARGS -boot-info-table -eltorito-alt-boot -e boot/efi.img -no-emul-boot"
1250 if cd "$BUILD_OUTPUT" ; then
1251 if [ "$BOOT_METHOD" = "grub2" ]; then
1252 # make a 2048-byte bootsector for El Torito
1253 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1254 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1255 echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
1256 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1258 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1259 $MKISOFS -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1260 -l -r -J $BOOT_ARGS -no-pad \
1261 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1262 # both of these need core.img there, so it’s easier to write it here
1263 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1264 # must be <= 30720 bytes
1265 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1266 conv=notrunc bs=512 seek=4 2>/dev/null
1269 # pad the output ISO to multiples of 256 KiB for partition table support
1270 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1271 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1272 siz=$((cyls * 16 * 32 * 512)) # size after padding
1273 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1274 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1276 # support disabling hybrid ISO image
1277 if [ "$HYBRID_METHOD" = "disable" ] ; then\
1278 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1279 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1281 elif [ "$HYBRID_METHOD" = "manifold" ] ; then
1282 # isoinfo is part of both mkisofs and genisoimage so we're good
1283 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1284 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN[;1]* *$/s//\1/p')
1285 if ! [ -r boot/grub/core.img ] ; then
1286 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1287 elif [ "${bootoff:-0}" -lt 1 ] ; then
1288 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1290 log "Creating hybrid ISO file with manifold method"
1291 einfo "Creating hybrid ISO file with manifold method"
1292 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1293 # 512 bytes: MBR, partition table, load GRUB 2
1294 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1296 # read only one but 2048-byte sized (scale: << 2) sector
1297 echo $bootoff $bootoff | \
1298 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1299 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1302 # use isohybrid as default
1304 if ! which isohybrid >/dev/null 2>&1 ; then
1305 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1307 log "Creating hybrid ISO file with isohybrid method"
1308 einfo "Creating hybrid ISO file with isohybrid method"
1309 # Notes for consideration:
1310 # "-entry 4 -type 1c"
1311 # * using 4 as the partition number is supposed to help with BIOSes
1312 # that only support USB-Zip boot
1313 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1314 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1315 # to get the BIOS even look at the partition created by isohybrid
1316 if isohybrid --help | grep -q -- --uefi ; then
1317 einfo "Detected uefi support for isohybrid, enabling."
1318 ISOHYBRID_OPTIONS=--uefi
1321 log "isohybrid $ISOHYBRID_OPTIONS ${ISO_OUTPUT}/${ISO_NAME}"
1322 isohybrid $ISOHYBRID_OPTIONS "${ISO_OUTPUT}/${ISO_NAME}"
1327 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1328 case $CLASSES in *RELEASE*)
1331 if cd $ISO_OUTPUT ; then
1332 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1333 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1334 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1335 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1344 if [ "$RC" = 0 ] ; then
1345 log "Finished execution of stage 'iso build' [$(date)]"
1346 einfo "Finished execution of stage 'iso build'" ; eend 0
1348 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1349 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1355 # netboot package {{{
1356 create_netbootpackage() {
1357 local OUTPUT_FILE="${NETBOOT}/grml_netboot_package_${GRML_NAME}_${VERSION}.tar.bz2"
1359 if [ -f "${OUTPUT_FILE}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1360 log "Skipping stage 'netboot' as $OUTPUT_FILE exists already."
1361 ewarn "Skipping stage 'netboot' as $OUTPUT_FILE exists already." ; eend 0
1363 elif [ -n "$SKIP_NETBOOT" ] ; then
1364 log "Skipping stage 'netboot' as requested via option -Q"
1365 ewarn "Skipping stage 'netboot' as requested via option -Q" ; eend 0
1371 if ! [ -r "${CHROOT}/usr/lib/syslinux/pxelinux.0" ] ; then
1372 ewarn "File /usr/lib/syslinux/pxelinux.0 not found in build chroot." ; eend 0
1374 einfo "Install syslinux[-common] package in chroot to get a netboot package."
1379 local OUTPUTDIR="${NETBOOT}/build_tmp"
1380 local WORKING_DIR="${OUTPUTDIR}/grml_netboot_package_${GRML_NAME}_${VERSION}/tftpboot/"
1382 mkdir -p "$WORKING_DIR"
1384 cp "${CHROOT_OUTPUT}"/boot/vmlinuz-* "$WORKING_DIR"/linux26
1385 cp "${CHROOT_OUTPUT}"/boot/initrd.img-* "$WORKING_DIR"/initrd.img
1386 cp "${CHROOT_OUTPUT}"/usr/lib/syslinux/pxelinux.0 "${WORKING_DIR}/pxelinux.0"
1388 if [ -r "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" ] ; then
1389 mkdir -p "${WORKING_DIR}/pxelinux.cfg/default"
1390 cp "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" "${WORKING_DIR}/pxelinux.cfg/default"
1392 ewarn "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found." ; eend 0
1395 mkdir -p "${WORKING_DIR}/pxelinux.cfg"
1397 if tar -C "$OUTPUTDIR" -jcf "${OUTPUT_FILE}" "grml_netboot_package_${GRML_NAME}_${VERSION}" ; then
1398 sha1sum "${OUTPUT_FILE}" > "${OUTPUT_FILE}.sha1"
1399 einfo "Generated netboot package ${OUTPUT_FILE}" ; eend 0
1400 rm -rf "${OUTPUTDIR}"
1402 rm -rf "${OUTPUTDIR}"
1403 eerror "Could not generate netboot package ${OUTPUT_FILE}" ; eend 1
1408 create_netbootpackage
1411 # pack artifacts {{{
1412 if [ -n "$PACK_ARTIFACTS" ]; then
1413 log "Packing artifcats"
1414 einfo "Packing artifacts"
1415 [ -f "${CHROOT_ARCHIVE}" ] && rm -r "${CHROOT_ARCHIVE}"
1416 tar -c -a -f ${CHROOT_ARCHIVE} --preserve-permissions -C "$(dirname ${CHROOT_OUTPUT})" "$(basename ${CHROOT_OUTPUT})"
1421 # log build information to database if grml-live-db is installed and enabled {{{
1423 if [ -d /usr/share/grml-live-db ] ; then
1426 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1427 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1428 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1429 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1431 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1432 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1433 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1437 # disable by default for now, not sure whether really everyone is using a local db file
1438 #if ! touch "$DPKG_DATABASE" ; then
1439 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1443 if ! [ -r "$DPKG_LIST" ] ; then
1444 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1445 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1447 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1448 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1449 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1452 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1468 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1469 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1471 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1473 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1477 ## END OF FILE #################################################################
1478 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=2