3 # Purpose: build process script for generating a (grml based) Linux Live-ISO
4 # Authors: grml-team (grml.org),
5 # (c) Michael Prokop <mika@grml.org>,
6 # (c) Thorsten Glaser <tg@mirbsd.org>
7 # Bug-Reports: see http://grml.org/bugs/
8 # License: This file is licensed under the GPL v2 or any later version.
9 ################################################################################
11 # some misc and global stuff {{{
15 # define function getfilesize before "set -e"
16 if stat --help >/dev/null 2>&1; then
17 getfilesize='stat -c %s' # GNU stat
19 getfilesize='stat -f %z' # BSD stat
23 # disable for now since it seems to cause some problems
26 # The line following this line is patched by debian/rules.
27 GRML_LIVE_VERSION='***UNRELEASED***'
32 ADDONS_LIST_FILE='/boot/isolinux/addons_list.cfg'
35 # usage information {{{
39 $PN - build process script for generating a (grml based) Linux Live-ISO
41 Usage: $PN [options, see as follows]
43 -a <architecture> architecture; available values: i386 and amd64
44 -A clean build directories before and after running
45 -b build the ISO without updating the chroot via FAI
46 -B build the ISO without touching the chroot (skips cleanup)
47 -c <classe[s]> classes to be used for building the ISO via FAI
48 -C <configfile> configuration file for grml-live
49 -d <date> use specified date instead of build time as date of release
50 -D <configdir> use specified configuration directory instead of /etc/grml/fai
51 -e <iso_name> extract ISO and squashfs contents from iso_name
52 -F force execution without prompting
53 -g <grml_name> set the grml flavour name
54 -h display short usage information and exit
55 -i <iso_name> name of ISO
56 -I <src_directory> directory which provides files that should become
57 part of the chroot/ISO
58 -n skip generation of ISO
59 -N bootstrap (build chroot) only, do not create files for ISO
60 -o <output_directory> main output directory of the build process
62 -Q skip netboot package build
63 -r <release_name> release name
64 -s <suite> Debian suite; values: etch, lenny, squeeze, sid
65 -t <template_directory> place of the templates
66 -u update existing chroot instead of rebuilding it from scratch
67 -U <username> arrange output to be owned by specified username
68 -v <version_number> specify version number of the release
69 -V increase verbosity in the build process
70 -z use ZLIB instead of LZMA/XZ compression
75 $PN -c GRMLBASE,GRML_FULL,AMD64 -o /dev/shm/grml
76 $PN -c GRMLBASE,GRML_FULL,AMD64 -i grml_0.0-1.iso -v 0.0-1
77 $PN -c GRMLBASE,GRML_FULL,AMD64 -s sid -V -r 'grml-live rocks'
79 More details: man grml-live + /usr/share/doc/grml-live/grml-live.html
80 http://grml.org/grml-live/
82 Please send your bug reports and feedback to the grml-team: http://grml.org/bugs/
84 [ "$(id -u 2>/dev/null)" != 0 ] && echo "Please notice that this script requires root permissions."
87 # make sure it's possible to get usage information without being
88 # root or actually executing the script
89 if [ "$1" = '-h' -o "$1" = '--help' ] ; then
95 # some runtime checks {{{
96 # we need root permissions for the build-process:
97 if [ "$(id -u 2>/dev/null)" != 0 ] ; then
98 echo "Error: please run this script with uid 0 (root)." >&2
102 if [ -r /var/run/fai/FAI_INSTALLATION_IN_PROGRESS ] ; then
103 echo "/usr/sbin/fai already running or was aborted before.">&2
104 echo "You may remove /var/run/fai/FAI_INSTALLATION_IN_PROGRESS and try again.">&2
109 if [ -r /var/run/fai/fai_softupdate_is_running ] ; then
110 echo "/usr/sbin/fai softupdate already running or was aborted before.">&2
111 echo "You may remove /var/run/fai/fai_softupdate_is_running and try again.">&2
116 # lsb-functions and configuration stuff {{{
117 # make sure they are not set by default
128 # don't use colors/escape sequences
129 if [ -r /lib/lsb/init-functions ] ; then
130 . /lib/lsb/init-functions
131 ! log_use_fancy_output && NOCOLORS=true
134 if [ -r /etc/grml/lsb-functions ] ; then
135 . /etc/grml/lsb-functions
137 einfo() { echo " [*] $*" ;}
138 eerror() { echo " [!] $*">&2 ;}
139 ewarn() { echo " [x] $*" ;}
141 eindent() { return 0 ;}
142 eoutdent() { return 0 ;}
145 # source main configuration file:
146 LIVE_CONF=/etc/grml/grml-live.conf
150 # umount all directories {{{
152 # make sure we don't leave any mounts - FAI doesn't remove them always
153 umount $CHROOT_OUTPUT/proc/sys/fs/binfmt_misc 2>/dev/null || /bin/true
154 umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
155 umount $CHROOT_OUTPUT/run 2>/dev/null || /bin/true
156 umount $CHROOT_OUTPUT/sys 2>/dev/null || /bin/true
157 umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
158 umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
160 # certain FAI versions sadly leave a ramdisk behind, so better safe than sorry
161 if [ -x /usr/lib/fai/mkramdisk ] ; then
162 /usr/lib/fai/mkramdisk -u "$(readlink -f ${CHROOT_OUTPUT}/var/lib/dpkg)" >/dev/null 2>&1 || /bin/true
165 umount "${CHROOT_OUTPUT}/grml-live/sources/" 2>/dev/null || /bin/true
166 [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
172 rm -f /var/run/fai/fai_softupdate_is_running \
173 /var/run/fai/FAI_INSTALLATION_IN_PROGRESS
174 [ -n "$CONFIGDUMP" ] && rm -f "$CONFIGDUMP"
175 [ -n "$SQUASHFS_STDERR" ] && rm -rf "$SQUASHFS_STDERR"
177 [ -n "$1" ] && EXIT="$1" || EXIT="1"
178 [ -n "$2" ] && eerror "$2">&2
179 if [ -n "$CLEAN_ARTIFACTS" ]; then
182 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
183 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
186 if [ -n "$CHOWN_USER" ]; then
187 log "Setting ownership"
188 einfo "Setting ownership"
189 [ -n "${OUTPUT}" -a -d "${OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${OUTPUT}"
190 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${BUILD_OUTPUT}"
191 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${CHROOT_OUTPUT}"
192 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${ISO_OUTPUT}"
193 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${LOG_OUTPUT}"
194 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && chown -R "${CHOWN_USER}:" "${NETBOOT}"
197 log "------------------------------------------------------------------------------"
200 trap bailout 1 2 3 3 6 9 14 15
204 # some important functions {{{
207 # usage: log "string to log"
208 log() { [ -n "$LOGFILE" ] && echo "$*" >> $LOGFILE ; }
210 # cut string at character number int = $1
211 # usage: cut_string 5 "1234567890" will output "12345"
213 [ -n "$2" ] || return 1
214 echo "$2" | head -c "$1"; echo -ne "\n"
217 # prepend int = $1 spaces before string = $2
218 # usage: extend_string_begin 5 "123" will output " 123"
219 extend_string_begin() {
220 [ -n "$2" ] || return 1
221 local COUNT="$(echo $2 | wc -c)"
222 local FILL="$(expr $COUNT - $1)"
223 while [ "$FILL" -gt 1 ] ; do
225 local FILL=$(expr $FILL - 1)
227 while [ "$FILL" -lt 1 ] ; do
229 local FILL=$(expr $FILL + 1)
231 echo "$2" | head -c "$1"; echo -ne "\n"
234 # append int = $1 spaces to string = $2
235 # usage: extend_string_begin 5 "123" will output "123 "
236 extend_string_end() {
237 [ -n "$2" ] || return 1
238 echo -n "$2" | head -c "$1"
239 local COUNT="$(echo $2 | wc -c)"
240 local FILL="$(expr $COUNT - $1)"
241 while [ "$FILL" -gt 1 ] ; do
243 local FILL=$(expr $FILL - 1)
245 while [ "$FILL" -lt 1 ] ; do
247 local FILL=$(expr $FILL + 1)
252 # Copy addonfile $1 from either
253 # * the chroot (via $2, the system path),
254 # * or from TEMPLATE_DIRECTORY/compat (if exists),
255 # * or from the host system (again, using $2),
256 # or warn about the missing file.
259 # * We assume that the chroot always has a "good" version of
260 # the file. Also it makes sources handling easier.
261 # * On unstable, we Recommend the Debian packages containing
262 # these files. The user can override them by putting his
263 # "better" version into the chroot.
264 # * On stable, the Debian packages are probably not available,
265 # or outdated, so we look in TEMPLATE_DIRECTORY/compat first, where
266 # our grml-live-compat package installs current file versions.
268 DEST="${BUILD_OUTPUT}/boot/$3"
269 if [ ! -d "${DEST}/" ]; then
272 if [ -e "$CHROOT_OUTPUT/$2/$1" ]; then
273 log "Copying $1 from chroot"
274 cp "$CHROOT_OUTPUT/$2/$1" "${DEST}/"
277 if [ -e "${TEMPLATE_DIRECTORY}/compat/$3/$1" ]; then
278 log "Copying $1 from grml-live-compat"
279 cp "${TEMPLATE_DIRECTORY}/compat/$3/$1" "${DEST}/"
282 if [ -e "$2/$1" ]; then
283 log "Copying $1 from system"
284 cp "$2/$1" "${DEST}/"
288 msg="Missing addon file: \"$1\""
289 ewarn "$msg" ; eend 1
290 log "copy_addon_file: $msg"
294 # command line parsing {{{
295 while getopts "a:C:c:d:D:e:g:i:I:o:r:s:t:U:v:AbBFhnNqQuVz" opt; do
298 A) CLEAN_ARTIFACTS=1 ;;
301 c) CLASSES="$OPTARG" ;;
302 C) LOCAL_CONFIG="$(readlink -f $OPTARG)" ;;
304 D) GRML_FAI_CONFIG="$(readlink -f $OPTARG)" ;;
305 e) EXTRACT_ISO_NAME="$(readlink -f $OPTARG)" ;;
306 g) GRML_NAME="$OPTARG" ;;
307 h) usage ; bailout 0 ;;
308 i) ISO_NAME="$OPTARG" ;;
309 I) CHROOT_INSTALL="$OPTARG" ;;
311 N) BOOTSTRAP_ONLY=1; SKIP_MKISOFS=1; SKIP_MKSQUASHFS=1 ;;
312 o) OUTPUT="$(readlink -f $OPTARG)" ;;
313 q) SKIP_MKSQUASHFS=1 ;;
315 r) RELEASENAME="$OPTARG" ;;
316 s) SUITE="$OPTARG" ;;
317 t) TEMPLATE_DIRECTORY="$OPTARG";;
318 v) VERSION="$OPTARG" ;;
321 U) CHOWN_USER="$OPTARG" ;;
323 z) SQUASHFS_ZLIB=1 ;;
324 ?) echo "invalid option -$OPTARG" >&2; bailout 1 ;;
327 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
330 # read local (non-packaged) configuration {{{
331 if [ -z "$LOCAL_CONFIG" ]; then
332 if [ -r "/etc/grml/grml-live.local" ]; then
333 LOCAL_CONFIG="/etc/grml/grml-live.local"
336 if [ -n "$LOCAL_CONFIG" ]; then
337 if [ -r "$LOCAL_CONFIG" ]; then
340 eerror "Could not read specified local configuration file \"$LOCAL_CONFIG\"."
343 LOCAL_CONFIG=$(readlink -f "$LOCAL_CONFIG")
348 if [ -n "${GRML_LIVE_SOURCES:-}" ] ; then
349 eerror "Config variable \$GRML_LIVE_SOURCES is set. This variable has been deprecated."
350 ewarn "Please set up \${GRML_FAI_CONFIG}/config/files/etc/apt/sources.list.d/* instead."
355 # assume sane defaults (if not set already) {{{
356 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
357 [ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux'
358 [ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_FULL,$(echo ${ARCH} | tr 'a-z' 'A-Z')"
359 [ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)"
360 [ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators'
361 [ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml"
362 [ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png'
363 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
364 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai'
365 [ -n "$GRML_NAME" ] || GRML_NAME='grml'
366 [ -n "$HOSTNAME" ] || HOSTNAME='grml'
367 [ -n "$HYBRID_METHOD" ] || HYBRID_METHOD='manifold'
368 [ -n "$NFSROOT_CONF" ] || NFSROOT_CONF="${GRML_FAI_CONFIG}/make-fai-nfsroot.conf"
369 [ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks'
370 [ -n "$SQUASHFS_EXCLUDES_FILE" ] || SQUASHFS_EXCLUDES_FILE="${GRML_FAI_CONFIG}/config/grml/squashfs-excludes"
371 [ -n "$SUITE" ] || SUITE='testing'
372 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
373 [ -n "$USERNAME" ] || USERNAME='grml'
374 [ -n "$VERSION" ] || VERSION='0.0.1'
376 # output specific stuff, depends on $OUTPUT (iff not set):
377 [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live'
378 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
379 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
380 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
381 [ -n "$LOG_OUTPUT" ] || LOG_OUTPUT="$OUTPUT/grml_logs"
382 [ -n "$REPORTS" ] || REPORTS="${LOG_OUTPUT}/reports/"
383 [ -n "$NETBOOT" ] || NETBOOT="${OUTPUT}/netboot/"
386 # some misc checks before executing FAI {{{
387 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
388 specify it on the command line using the -c option."
389 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
390 specify it on the command line using the -o option."
392 # trim characters that are known to cause problems inside $GRML_NAME;
393 # for example isolinux does not like '-' inside the directory name
394 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
396 # export variables to have them available in fai scripts:
397 [ -n "$GRML_NAME" ] && export GRML_NAME="$GRML_NAME"
398 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
401 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
402 # this was default behaviour until grml-live 0.9.34:
403 if [ -n "$ZERO_LOGFILE" ] ; then
404 PRESERVE_LOGFILE='' # make sure it's cleaned then
405 ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
406 ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
411 # ask user whether the setup is ok {{{
412 if [ -z "$FORCE" ] ; then
414 echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
416 echo " FAI classes: $CLASSES"
417 [ -n "$LOCAL_CONFIG" ] && echo " Configuration: $LOCAL_CONFIG"
418 [ -n "$GRML_FAI_CONFIG" ] && echo " Config directory: $GRML_FAI_CONFIG"
419 echo " main directory: $OUTPUT"
420 [ -n "$EXTRACT_ISO_NAME" ] && echo " Extract ISO: $EXTRACT_ISO_NAME"
421 [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT"
422 [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT"
423 [ -n "$ISO_OUTPUT" ] && echo " ISO target: $ISO_OUTPUT"
424 [ -n "$GRML_NAME" ] && echo " Grml name: $GRML_NAME"
425 [ -n "$RELEASENAME" ] && echo " Release name: $RELEASENAME"
426 [ -n "$DATE" ] && echo " Build date: $DATE"
427 [ -n "$VERSION" ] && echo " Grml version: $VERSION"
428 [ -n "$SUITE" ] && echo " Debian suite: $SUITE"
429 [ -n "$ARCH" ] && echo " Architecture: $ARCH"
430 [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD"
431 [ -n "$HYBRID_METHOD" ] && echo " Hybrid method: $HYBRID_METHOD"
432 [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY"
433 [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL"
434 [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID"
435 [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature."
436 [ -n "$CHOWN_USER" ] && echo " Output owner: $CHOWN_USER"
437 [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
438 [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS"
439 [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE"
440 [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA/XZ) compression."
441 [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
442 [ -n "$VERBOSE" ] && echo " Using VERBOSE mode."
443 [ -n "$CLEAN_ARTIFACTS" ] && echo " Will clean output before and after running."
444 [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation."
445 if [ -n "$BOOTSTRAP_ONLY" ] ; then
446 echo " Bootstrapping only and not building (files for) ISO."
448 [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file."
449 [ -n "$SKIP_NETBOOT" ] && echo " Skipping creation of NETBOOT package."
450 [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file."
451 [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE."
452 [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched."
455 echo -n "Is this ok for you? [y/N] "
457 if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
458 bailout 1 "Exiting as requested."
464 # clean up before start {{{
465 if [ -n "${CLEAN_ARTIFACTS}" ]; then
466 echo "Wiping old artifacts"
467 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
468 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
469 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && rm -r "${ISO_OUTPUT}"
470 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && rm -r "${LOG_OUTPUT}"
471 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && rm -r "${NETBOOT}"
475 # create log file {{{
476 [ -n "$LOGFILE" ] || LOGFILE=${LOG_OUTPUT}/grml-live.log
477 mkdir -p $(dirname "${LOGFILE}")
479 chown root:adm $LOGFILE
483 # clean/zero/remove logfiles {{{
485 if [ -n "$PRESERVE_LOGFILE" ] ; then
486 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
488 # make sure it is empty (as it is e.g. appended to grml-live-db)
492 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
493 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
494 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
495 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
496 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
497 rm -f /var/log/fai/"$HOSTNAME"/last \
498 /var/log/fai/"$HOSTNAME"/last-dirinstall \
499 /var/log/fai/"$HOSTNAME"/last-softupdate
504 # source config and startup {{{
505 if [ -n "$CONFIG" ] ; then
506 if ! [ -f "$CONFIG" ] ; then
507 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
508 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
511 log "Sourcing $CONFIG"
516 start_seconds=$(cut -d . -f 1 /proc/uptime)
517 log "------------------------------------------------------------------------------"
518 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
519 log "Using local config file: $LOCAL_CONFIG"
520 log "Executed grml-live command line:"
523 einfo "Logging actions to logfile $LOGFILE"
526 # dump config variables into file, for script access {{{
529 '^(GRML_NAME|RELEASENAME|DATE|VERSION|SUITE|ARCH|DISTRI_NAME|USERNAME|HOSTNAME|APT_PROXY)=' \
533 # unpack iso/squashfs {{{
535 if [ -n "$EXTRACT_ISO_NAME" ]; then
536 log "Unpacking ISO from ${EXTRACT_ISO_NAME}"
537 einfo "Unpacking ISO from ${EXTRACT_ISO_NAME}"
538 local mountpoint=$(mktemp -d)
540 mount -o loop "${EXTRACT_ISO_NAME}" "$mountpoint" ; rc=$?
541 if [ "$rc" != 0 ]; then
544 eerror "mount failed"
548 unsquashfs -d "${CHROOT_OUTPUT}" "${mountpoint}"/live/*/*.squashfs ; rc=$?
551 if [ "$rc" != 0 ]; then
552 log "unsquashfs failed"
553 eerror "unsquashfs failed"
562 # on-the-fly configuration {{{
563 if [ -n "$FAI_DEBOOTSTRAP" ] ; then
564 sed "s#^FAI_DEBOOTSTRAP=.*#FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"#" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
567 # does this suck? YES!
568 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
570 unstable) SUITE='sid' ; CLASSES="DEBIAN_UNSTABLE,$CLASSES" ;;
571 *) CLASSES="DEBIAN_$(echo $SUITE | tr 'a-z' 'A-Z'),$CLASSES";;
573 export SUITE # make sure it's available in FAI scripts
575 for file in "$LIVE_CONF" "$LOCAL_CONFIG" "$NFSROOT_CONF" ; do
576 if [ -n "$file" ] ; then
577 sed "s|^FAI_DEBOOTSTRAP=\"[a-z]* |FAI_DEBOOTSTRAP=\"$SUITE |" "$file" | sponge "$file"
581 # validate whether the specified architecture class matches the
582 # architecture (option), otherwise installation of kernel will fail
583 if echo $CLASSES | grep -qi i386 ; then
584 if ! [[ "$ARCH" == "i386" ]] ; then
585 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
586 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
587 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
591 elif echo $CLASSES | grep -qi amd64 ; then
592 if ! [[ "$ARCH" == "amd64" ]] ; then
593 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
594 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
595 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
601 if grep -q -- 'FAI_DEBOOTSTRAP_OPTS.*--arch' "$NFSROOT_CONF" ; then
602 sed "s/--arch [a-z0-9]* /--arch $ARCH /" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
604 sed "s|^FAI_DEBOOTSTRAP_OPTS=\"\(.*\)|FAI_DEBOOTSTRAP_OPTS=\"--arch $ARCH \1|" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
608 # CHROOT_OUTPUT - execute FAI {{{
609 if [ -n "$BUILD_DIRTY" ]; then
610 log "Skipping stage 'fai' as requested via option -B"
611 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
613 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
615 # provide inform fai about the ISO we build
616 [ -d "$CHROOT_OUTPUT/etc/" ] || mkdir -p "$CHROOT_OUTPUT/etc/"
617 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
618 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
619 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
621 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
622 FAI_ACTION=softupdate
624 FAI_ACTION=dirinstall
627 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
628 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
629 log "Error: does not look like you have a working chroot. Updating/building not possible."
630 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
636 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
637 log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
638 ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
640 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
642 if [ -n "${MIRROR_DIRECTORY}" ] ; then
643 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
644 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
647 mkdir -p "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
648 mount --bind "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
650 # tell dpkg to use "unsafe io" during the build
651 [ -d "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d" ] || mkdir -p "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d"
652 echo force-unsafe-io > "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d/unsafe-io"
654 log "Executed FAI command line:"
655 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"
656 BUILD_ONLY="$BUILD_ONLY" BOOTSTRAP_ONLY="$BOOTSTRAP_ONLY" GRML_LIVE_CONFIG="$CONFIGDUMP" fai $VERBOSE \
657 -C "$GRML_FAI_CONFIG" -s "file:///$GRML_FAI_CONFIG/config" -c"$CLASSES" \
658 -u "$HOSTNAME" "$FAI_ACTION" "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
659 RC="$PIPESTATUS" # notice: bash-only
661 rm -f "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d/unsafe-io"
663 FORCE_ISO_REBUILD=true
665 if [ "$RC" != 0 ] ; then
666 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
667 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
671 # move fai logs into grml_logs directory
672 mkdir -p "$LOG_OUTPUT"/fai/
673 cp -r "$CHROOT_OUTPUT"/var/log/fai/"$HOSTNAME"/last/* "$LOG_OUTPUT"/fai/
674 rm -rf "$CHROOT_OUTPUT"/var/log/fai
675 # copy fai package list
676 cp "$CHROOT_OUTPUT"/var/log/install_packages.list "$LOG_OUTPUT"/fai/
678 chown root:adm "$LOG_OUTPUT"/fai/*
679 chmod 664 "$LOG_OUTPUT"/fai/*
683 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
685 CHECKLOG="$LOG_OUTPUT"/fai/
686 if [ -r "$CHECKLOG/software.log" ] ; then
687 # 1 errors during executing of commands
688 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
689 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
690 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
691 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
692 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
695 if [ -r "$CHECKLOG/shell.log" ] ; then
696 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
699 if [ -n "$ERROR" ] ; then
700 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
701 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
702 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
706 log "Finished execution of stage 'fai dirinstall' [$(date)]"
707 einfo "Finished execution of stage 'fai dirinstall'"
713 # package validator {{{
714 CHECKLOG=/var/log/fai/$HOSTNAME/last
715 if [ -r "$CHECKLOG/dpkg.selections" ] ; then
716 package_count=$(wc -l "$CHECKLOG/dpkg.selections" | awk '{print $1}')
718 package_count="unknown"
722 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
724 # check for missing packages
725 if ! [ -s "$CHECKLOG/package_errors.log" ] ; then
726 einfo "No missing packages found, generating empty junit report."
728 cat > "${REPORT_MISSING_PACKAGES}" << EOF
729 <?xml version="1.0" encoding="UTF-8"?>
730 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="0" errors="0" skipped="0" assertions="0">
731 <testcase name="test_missing_packages" time="0" assertions="0">
741 einfo "Missing packages found, generating junit report."
743 if [ -r "$CHECKLOG/package_errors.log" ] ; then
744 package_errors=$(wc -l "$CHECKLOG/package_errors.log" | awk '{print $1}')
746 package_errors="unknown"
750 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
752 cat > "${REPORT_MISSING_PACKAGES}" << EOF
753 <?xml version="1.0" encoding="UTF-8"?>
754 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="${package_errors}" errors="${package_errors}" skipped="0" assertions="0">
757 for package in $(awk '{print $5}' "${CHECKLOG}/package_errors.log" | sed 's/\.$//') ; do
758 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
759 <testcase name="test_missing_packages_${package}" time="0" assertions="0">
760 <failure type="RuntimeError" message="Package ${package} is missing">
761 Package $package is missing in chroot
767 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
776 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
777 eerror "The following packages were requested for installation but could not be processed:"
778 cat "$CHECKLOG/package_errors.log"
779 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
783 ewarn "The following packages were requested for installation but could not be processed:"
784 cat "$CHECKLOG/package_errors.log"
790 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
791 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
792 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
795 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
796 if [ -n "$BOOTSTRAP_ONLY" ] ; then
797 log "Skipping stage 'boot' as building with bootstrap only."
798 ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0
800 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
801 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
802 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
805 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
806 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
808 # if we don't have an initrd we a) can't boot and b) there was an error
809 # during build, so check for the file:
810 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
811 if [ -n "$INITRD" ] ; then
812 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.img
813 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
815 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
816 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
820 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
821 if [ -n "$KERNEL_IMAGE" ] ; then
822 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/vmlinuz
824 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
825 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
830 if [ -r "${CHROOT_OUTPUT}/boot/efi.img" -a -r "${CHROOT_OUTPUT}/boot/bootx64.efi" ] ; then
831 einfo "Moving EFI boot files into ISO path."
832 log "Moving EFI boot files into ISO path."
834 mv "${CHROOT_OUTPUT}/boot/efi.img" "${BUILD_OUTPUT}/boot/" || RC=$?
835 mkdir -p "${BUILD_OUTPUT}/efi/boot/" || RC=$?
836 mv "${CHROOT_OUTPUT}/boot/bootx64.efi" "${BUILD_OUTPUT}/efi/boot/bootx64.efi" || RC=$?
840 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
841 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
842 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
843 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
847 # copy _required_ isolinux files
848 for file in ifcpu64.c32 isolinux.bin vesamenu.c32; do
849 copy_addon_file "${file}" /usr/lib/syslinux isolinux
852 # *always* copy files to output directory so the variables
853 # get adjusted according to the build.
854 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
856 if [ -n "$NO_ADDONS" ] ; then
857 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
858 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
860 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
861 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
862 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
864 # copy addons from system packages or grml-live-compat
865 copy_addon_file ipxe.lkrn /usr/lib/ipxe addons
866 copy_addon_file pci.ids /usr/share/misc addons
867 copy_addon_file memtest86+.bin /boot addons
868 for file in memdisk chain.c32 hdt.c32 menu.c32; do
869 copy_addon_file "${file}" /usr/lib/syslinux addons
872 # make memtest filename FAT16/8.3 compatible
873 mv "${BUILD_OUTPUT}/boot/addons/memtest86+.bin" \
874 "${BUILD_OUTPUT}/boot/addons/memtest"
876 # copy only files so we can handle bsd4grml on its own
877 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
878 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
881 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
882 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
883 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
885 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
886 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
888 log "Missing addon file: bsd4grml"
889 ewarn "Missing addon file: bsd4grml" ; eend 0
893 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
896 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
897 mkdir -p "${BUILD_OUTPUT}/boot/grub"
899 cp -a ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
901 # copy grub files from target
902 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.mod "${BUILD_OUTPUT}"/boot/grub/
903 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.o "${BUILD_OUTPUT}"/boot/grub/
904 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.lst "${BUILD_OUTPUT}"/boot/grub/
905 cp -a "${CHROOT_OUTPUT}"/usr/share/grub/ascii.pf2 "${BUILD_OUTPUT}"/boot/grub/
906 cp -a "${CHROOT_OUTPUT}"/boot/grub/core.img "${BUILD_OUTPUT}"/boot/grub/
907 cp -a "${CHROOT_OUTPUT}"/boot/grub/grub.img "${BUILD_OUTPUT}"/boot/grub/
909 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
910 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
911 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
915 mkdir -p "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
916 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
918 # adjust boot splash information:
919 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
920 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
921 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
923 if [ -r "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version ] ; then
924 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
925 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
928 # make sure the squashfs filename is set accordingly:
929 SQUASHFS_NAME="$GRML_NAME.squashfs"
931 if [ -n "$NO_BOOTID" ] ; then
932 log 'Skipping bootid feature as requested via $NO_BOOTID.'
933 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
935 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
936 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
937 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
938 log "Generating /conf/bootid.txt with entry ${BOOTID}."
939 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
943 # adjust all variables in the templates with the according distribution information
944 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
945 "${BUILD_OUTPUT}"/boot/grub/* ; do
946 if [ -r "${file}" ] && [ -f "${file}" ] ; then
947 sed -i "s/%ARCH%/$ARCH/g" "${file}"
948 sed -i "s/%DATE%/$DATE/g" "${file}"
949 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
950 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
951 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
952 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
953 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
954 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
955 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
956 sed -i "s/%VERSION%/$VERSION/g" "${file}"
958 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s/ boot=live/ boot=live $DEFAULT_BOOTOPTIONS/" "${file}"
960 if [ -n "$NO_BOOTID" ] ; then
961 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
963 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
968 for param in ARCH DATE DISTRI_INFO DISTRI_NAME DISTRI_SPLASH GRML_NAME SQUASHFS_NAME \
969 RELEASE_INFO SHORT_NAME VERSION ; do
970 for file in $(find "${BUILD_OUTPUT}" -name "*%$param%*") ; do
971 value="$(eval echo '$'"$param")"
972 mv ${file} ${file/\%${param}\%/$value}
976 # adjust bootsplash accordingly but make sure the string has the according lenght
977 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
978 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
979 for file in f4 f5 ; do
980 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
981 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
982 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
986 # generate addon list
987 rm -f "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
988 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
989 include_name=$(basename "$name")
990 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
993 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
994 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
995 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
996 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
997 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
998 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1000 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
1001 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1004 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1005 if [ ! -n "$NO_ADDONS" ] ; then
1006 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1008 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1009 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1010 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1011 else # assume we are building a custom distribution:
1012 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
1013 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
1014 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1015 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1017 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1021 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1022 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1023 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1027 # use old style console based isolinux method only if requested:
1028 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
1029 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1030 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1031 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1032 einfo "include for console.cfg already found, nothing to do."
1035 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1036 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1037 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1041 log 'Using graphical boot menu.'
1042 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
1043 log "include for vesamenu.cfg already found, nothing to do."
1045 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1046 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1050 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
1051 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
1054 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
1055 if ! [ -r "$DPKG_LIST" ] ; then
1056 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
1058 einfo "Storing package list information as /GRML/${GRML_NAME}/packages.txt on ISO."
1059 cp "$DPKG_LIST" "${BUILD_OUTPUT}"/GRML/"${GRML_NAME}"/packages.txt
1063 # autostart for Windows:
1064 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
1065 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
1068 FORCE_ISO_REBUILD=true
1069 einfo "Finished execution of stage 'boot'" ; eend 0
1073 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
1074 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
1078 # support installation of local files into the chroot/ISO
1079 if [ -n "$CHROOT_INSTALL" ] ; then
1080 if ! [ -d "$CHROOT_INSTALL" ] ; then
1081 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1082 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1084 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1085 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1086 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
1088 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
1089 FORCE_ISO_REBUILD=true
1093 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1094 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
1095 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
1096 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
1097 log "Skipping stage 'squashfs' as requested via option -q or -N"
1098 ewarn "Skipping stage 'squashfs' as requested via option -q or -N" ; eend 0
1100 mkdir -p "$BUILD_OUTPUT"/live/"${GRML_NAME}"/
1101 # make sure we don't leave (even an empty) base.tgz:
1102 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
1104 # if unconfigured default to squashfs-tools' mksquashfs binary
1105 if [ -z "$SQUASHFS_BINARY" ] ; then
1106 SQUASHFS_BINARY='mksquashfs'
1109 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
1110 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
1111 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
1113 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
1114 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
1118 # use sane defaults if $SQUASHFS_OPTIONS isn't set
1119 if [ -z "$SQUASHFS_OPTIONS" ] ; then
1120 # use blocksize 256k as this gives best result with regards to time + compression
1121 SQUASHFS_OPTIONS="-b 256k"
1123 # set lzma/xz compression by default, unless -z option has been specified on command line
1124 if [ -z "$SQUASHFS_ZLIB" ] ; then
1125 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
1127 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
1131 # support exclusion of files via exclude-file:
1132 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
1133 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE -wildcards"
1136 # get rid of unnecessary files when building grml-small for final release:
1137 if echo "$CLASSES" | grep -q GRML_SMALL ; then
1138 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
1142 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
1144 # informational stuff
1145 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1146 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1147 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1149 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/${GRML_NAME}/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1151 if $SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/"${GRML_NAME}"/"${GRML_NAME}".squashfs \
1152 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1153 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/"${GRML_NAME}"/filesystem.module
1154 log "Finished execution of stage 'squashfs' [$(date)]"
1155 einfo "Finished execution of stage 'squashfs'" ; eend 0
1157 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1158 log "$(cat $SQUASHFS_STDERR)"
1159 eerror "Error: there was a critical error executing stage 'squashfs':"
1160 cat "${SQUASHFS_STDERR}"
1165 FORCE_ISO_REBUILD=true
1168 # create md5sum file:
1169 if [ -z "$BOOTSTRAP_ONLY" ] ; then
1170 ( cd $BUILD_OUTPUT/GRML/"${GRML_NAME}" &&
1171 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1175 # ISO_OUTPUT - mkisofs {{{
1176 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1177 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1179 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1180 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1181 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1182 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1185 # Just until http://bts.grml.org/grml/issue945 has been resolved.
1186 # HYBRID_METHOD defaults to manifold, so make sure the default works OOTB.
1187 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1188 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1189 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1190 HYBRID_METHOD='grub2'
1194 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1195 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1196 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1197 elif [ -n "$SKIP_MKISOFS" ] ; then
1198 log "Skipping stage 'iso build' as requested via option -n or -N"
1199 ewarn "Skipping stage 'iso build' as requested via option -n or -N" ; eend 0
1201 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1203 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1204 log "Forcing rebuild of ISO because files on ISO have been modified."
1205 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1208 # support xorriso as well mkisofs and genisoimage
1209 if which xorriso >/dev/null 2>&1 ; then
1210 MKISOFS='xorriso -as mkisofs'
1211 elif which mkisofs >/dev/null 2>&1; then
1213 elif which genisoimage >/dev/null 2>&1; then
1214 MKISOFS='genisoimage'
1216 log "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO."
1217 eerror "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO." ; eend 1
1221 einfo "Using ${MKISOFS} to build ISO." ; eend 0
1222 case "${ARCH}-${MKISOFS}" in
1223 # using -eltorito-alt-boot is limited to xorriso for now
1227 if ! dpkg --compare-versions $(dpkg-query -W -f='${Version}\n' xorriso 2>/dev/null) gt-nl 1.1.6-1 ; then
1228 log "Disabling (U)EFI boot support because xorriso version is too old."
1229 ewarn "Disabling (U)EFI boot support because xorriso version is too old." ; eend 0
1231 if [ -r "${BUILD_OUTPUT}"/boot/efi.img ] ; then
1232 einfo "Enabling (U)EFI boot."
1233 log "Enabling (U)EFI boot."
1234 BOOT_ARGS="$BOOT_ARGS -boot-info-table -eltorito-alt-boot -e boot/efi.img -no-emul-boot"
1237 log "Disabling (U)EFI boot support because /boot/efi.img is missing."
1238 ewarn "Disabling (U)EFI boot support because /boot/efi.img is missing." ; eend 0
1247 if cd "$BUILD_OUTPUT" ; then
1248 if [ "$BOOT_METHOD" = "grub2" ]; then
1249 # make a 2048-byte bootsector for El Torito
1250 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1251 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1252 echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
1253 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1255 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1256 $MKISOFS -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1257 -l -r -J $BOOT_ARGS -no-pad \
1258 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1259 # both of these need core.img there, so it’s easier to write it here
1260 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1261 # must be <= 30720 bytes
1262 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1263 conv=notrunc bs=512 seek=4 2>/dev/null
1266 # pad the output ISO to multiples of 256 KiB for partition table support
1267 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1268 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1269 siz=$((cyls * 16 * 32 * 512)) # size after padding
1270 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1271 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1273 # support disabling hybrid ISO image
1274 if [ "$HYBRID_METHOD" = "disable" ] ; then\
1275 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1276 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1278 elif [ "$HYBRID_METHOD" = "manifold" ] ; then
1279 # isoinfo is part of both mkisofs and genisoimage so we're good
1280 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1281 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN[;1]* *$/s//\1/p')
1282 if ! [ -r boot/grub/core.img ] ; then
1283 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1284 elif [ "${bootoff:-0}" -lt 1 ] ; then
1285 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1287 log "Creating hybrid ISO file with manifold method"
1288 einfo "Creating hybrid ISO file with manifold method"
1289 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1290 # 512 bytes: MBR, partition table, load GRUB 2
1291 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1293 # read only one but 2048-byte sized (scale: << 2) sector
1294 echo $bootoff $bootoff | \
1295 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1296 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1299 # use isohybrid as default
1301 if ! which isohybrid >/dev/null 2>&1 ; then
1302 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1304 log "Creating hybrid ISO file with isohybrid method"
1305 einfo "Creating hybrid ISO file with isohybrid method"
1306 # Notes for consideration:
1307 # "-entry 4 -type 1c"
1308 # * using 4 as the partition number is supposed to help with BIOSes
1309 # that only support USB-Zip boot
1310 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1311 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1312 # to get the BIOS even look at the partition created by isohybrid
1313 if isohybrid --help | grep -q -- --uefi ; then
1314 einfo "Detected uefi support for isohybrid, enabling."
1315 ISOHYBRID_OPTIONS=--uefi
1318 log "isohybrid $ISOHYBRID_OPTIONS ${ISO_OUTPUT}/${ISO_NAME}"
1319 isohybrid $ISOHYBRID_OPTIONS "${ISO_OUTPUT}/${ISO_NAME}"
1324 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1325 case $CLASSES in *RELEASE*)
1328 if cd $ISO_OUTPUT ; then
1329 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1330 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1331 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1332 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1341 if [ "$RC" = 0 ] ; then
1342 log "Finished execution of stage 'iso build' [$(date)]"
1343 einfo "Finished execution of stage 'iso build'" ; eend 0
1345 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1346 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1352 # netboot package {{{
1353 create_netbootpackage() {
1354 local OUTPUT_FILE="${NETBOOT}/grml_netboot_package_${GRML_NAME}_${VERSION}.tar.bz2"
1356 if [ -f "${OUTPUT_FILE}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1357 log "Skipping stage 'netboot' as $OUTPUT_FILE exists already."
1358 ewarn "Skipping stage 'netboot' as $OUTPUT_FILE exists already." ; eend 0
1360 elif [ -n "$SKIP_NETBOOT" ] ; then
1361 log "Skipping stage 'netboot' as requested via option -Q"
1362 ewarn "Skipping stage 'netboot' as requested via option -Q" ; eend 0
1368 if ! [ -r "${CHROOT}/usr/lib/syslinux/pxelinux.0" ] ; then
1369 ewarn "File /usr/lib/syslinux/pxelinux.0 not found in build chroot." ; eend 0
1371 einfo "Install syslinux[-common] package in chroot to get a netboot package."
1376 local OUTPUTDIR="${NETBOOT}/build_tmp"
1377 local WORKING_DIR="${OUTPUTDIR}/grml_netboot_package_${GRML_NAME}_${VERSION}/tftpboot/"
1379 mkdir -p "$WORKING_DIR"
1381 cp "${CHROOT_OUTPUT}"/boot/vmlinuz-* "$WORKING_DIR"/vmlinuz
1382 cp "${CHROOT_OUTPUT}"/boot/initrd.img-* "$WORKING_DIR"/initrd.img
1383 cp "${CHROOT_OUTPUT}"/usr/lib/syslinux/pxelinux.0 "${WORKING_DIR}/pxelinux.0"
1385 mkdir -p "${WORKING_DIR}/pxelinux.cfg"
1386 if [ -r "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" ] ; then
1387 cp "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" "${WORKING_DIR}/pxelinux.cfg/default"
1389 ewarn "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found." ; eend 0
1392 if tar -C "$OUTPUTDIR" -jcf "${OUTPUT_FILE}" "grml_netboot_package_${GRML_NAME}_${VERSION}" ; then
1394 cd $(dirname "${OUTPUT_FILE}")
1395 sha1sum $(basename "${OUTPUT_FILE}") > "${OUTPUT_FILE}.sha1"
1397 einfo "Generated netboot package ${OUTPUT_FILE}" ; eend 0
1398 rm -rf "${OUTPUTDIR}"
1400 rm -rf "${OUTPUTDIR}"
1401 eerror "Could not generate netboot package ${OUTPUT_FILE}" ; eend 1
1406 create_netbootpackage
1409 # log build information to database if grml-live-db is installed and enabled {{{
1411 if [ -d /usr/share/grml-live-db ] ; then
1414 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1415 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1416 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1417 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1419 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1420 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1421 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1425 # disable by default for now, not sure whether really everyone is using a local db file
1426 #if ! touch "$DPKG_DATABASE" ; then
1427 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1431 if ! [ -r "$DPKG_LIST" ] ; then
1432 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1433 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1435 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1436 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1437 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1440 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1456 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1457 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1459 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1461 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1465 ## END OF FILE #################################################################
1466 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=2