-#!/bin/bash --norc
+#!/bin/bash -p
#
# Generator script for a dracut initramfs
# Tries to retain some degree of compatibility with the command line
# store for logging
+unset BASH_ENV
+
# Verify bash version, current minimum is 4
if (( BASH_VERSINFO[0] < 4 )); then
printf -- 'You need at least Bash 4 to use dracut, sorry.' >&2
--kernel-cmdline [PARAMETERS] Specify default kernel command line parameters
--strip Strip binaries in the initramfs
--nostrip Do not strip binaries in the initramfs
- --prelink Prelink binaries in the initramfs
- --noprelink Do not prelink binaries in the initramfs
--hardlink Hardlink files in the initramfs
--nohardlink Do not hardlink files in the initramfs
--prefix [DIR] Prefix initramfs files with [DIR]
-H, --hostonly Host-Only mode: Install only what is needed for
booting the local host instead of a generic host.
-N, --no-hostonly Disables Host-Only mode
+ --hostonly-mode <mode>
+ Specify the hostonly mode to use. <mode> could be
+ one of "sloppy" or "strict". "sloppy" mode is used
+ by default.
+ In "sloppy" hostonly mode, extra drivers and modules
+ will be installed, so minor hardware change won't make
+ the image unbootable (eg. changed keyboard), and the
+ image is still portable among similar hosts.
+ With "strict" mode enabled, anything not necessary
+ for booting the local host in its current state will
+ not be included, and modules may do some extra job
+ to save more space. Minor change of hardware or
+ environment could make the image unbootable.
+ DO NOT use "strict" mode unless you know what you
+ are doing.
--hostonly-cmdline Store kernel command line arguments needed
in the initramfs
--no-hostonly-cmdline Do not store kernel command line arguments needed
in the initramfs
+ --no-hostonly-default-device
+ Do not generate implicit host devices like root,
+ swap, fstab, etc. Use "--mount" or "--add-device"
+ to explicitly add devices as needed.
--hostonly-i18n Install only needed keyboard and font files according
to the host configuration (default).
--no-hostonly-i18n Install all keyboard and font files available.
--lz4 Compress the generated initramfs using lz4.
Make sure that your kernel has lz4 support compiled
in, otherwise you will not be able to boot.
+ --zstd Compress the generated initramfs using Zstandard.
+ Make sure that your kernel has zstd support compiled
+ in, otherwise you will not be able to boot.
--compress [COMPRESSION] Compress the generated initramfs with the
passed compression program. Make sure your kernel
knows how to decompress the generated initramfs,
rearrange_params()
{
# Workaround -i, --include taking 2 arguments
- set -- "${@/--include/++include}"
-
- # This prevents any long argument ending with "-i"
- # -i, like --opt-i but I think we can just prevent that
- set -- "${@/%-i/++include}"
+ newat=()
+ for i in "$@"; do
+ if [[ $i == "-i" ]] || [[ $i == "--include" ]]; then
+ newat+=("++include") # Replace --include by ++include
+ else
+ newat+=("$i")
+ fi
+ done
+ set -- "${newat[@]}" # Set new $@
TEMP=$(unset POSIXLY_CORRECT; getopt \
-o "a:m:o:d:I:k:c:L:fvqlHhMN" \
--long mount: \
--long device: \
--long add-device: \
- --long nofscks: \
+ --long nofscks \
--long ro-mnt \
--long kmoddir: \
--long conf: \
--long kernel-cmdline: \
--long strip \
--long nostrip \
- --long prelink \
- --long noprelink \
--long hardlink \
--long nohardlink \
--long noprefix \
--long host-only \
--long no-hostonly \
--long no-host-only \
+ --long hostonly-mode: \
--long hostonly-cmdline \
--long no-hostonly-cmdline \
+ --long no-hostonly-default-device \
--long persistent-policy: \
--long fstab \
--long help \
--long xz \
--long lzo \
--long lz4 \
+ --long zstd \
--long no-compress \
--long gzip \
--long list-modules \
eval set -- "$TEMP"
rearrange_params "$@"
fi
-
- # clean the temporarily used scratch-pad directory
- rm -rf $scratch_dir
fi
unset PARMS_TO_STORE
early_microcode_l="no";;
--strip) do_strip_l="yes";;
--nostrip) do_strip_l="no";;
- --prelink) do_prelink_l="yes";;
- --noprelink) do_prelink_l="no";;
--hardlink) do_hardlink_l="yes";;
--nohardlink) do_hardlink_l="no";;
--noprefix) prefix_l="/";;
hostonly_l="yes" ;;
-N|--no-hostonly|--no-host-only)
hostonly_l="no" ;;
+ --hostonly-mode)
+ hostonly_mode_l="$2"; PARMS_TO_STORE+=" '$2'"; shift;;
--hostonly-cmdline)
hostonly_cmdline_l="yes" ;;
--hostonly-i18n)
i18n_install_all_l="yes" ;;
--no-hostonly-cmdline)
hostonly_cmdline_l="no" ;;
+ --no-hostonly-default-device)
+ hostonly_default_device="no" ;;
--persistent-policy)
persistent_policy_l="$2"; PARMS_TO_STORE+=" '$2'"; shift;;
--fstab) use_fstab_l="yes" ;;
--xz) compress_l="xz";;
--lzo) compress_l="lzo";;
--lz4) compress_l="lz4";;
+ --zstd) compress_l="zstd";;
--no-compress) _no_compress_l="cat";;
--gzip) compress_l="gzip";;
--list-modules) do_list="yes";;
[[ $drivers_dir_l ]] && drivers_dir=$drivers_dir_l
[[ $do_strip_l ]] && do_strip=$do_strip_l
[[ $do_strip ]] || do_strip=yes
-[[ $do_prelink_l ]] && do_prelink=$do_prelink_l
-[[ $do_prelink ]] || do_prelink=yes
[[ $do_hardlink_l ]] && do_hardlink=$do_hardlink_l
[[ $do_hardlink ]] || do_hardlink=yes
[[ $prefix_l ]] && prefix=$prefix_l
[[ $prefix = "/" ]] && unset prefix
[[ $hostonly_l ]] && hostonly=$hostonly_l
[[ $hostonly_cmdline_l ]] && hostonly_cmdline=$hostonly_cmdline_l
+[[ $hostonly_mode_l ]] && hostonly_mode=$hostonly_mode_l
[[ "$hostonly" == "yes" ]] && ! [[ $hostonly_cmdline ]] && hostonly_cmdline="yes"
[[ $i18n_install_all_l ]] && i18n_install_all=$i18n_install_all_l
[[ $persistent_policy_l ]] && persistent_policy=$persistent_policy_l
[[ $nofscks_l ]] && nofscks="yes"
[[ $ro_mnt_l ]] && ro_mnt="yes"
[[ $early_microcode_l ]] && early_microcode=$early_microcode_l
-[[ $early_microcode ]] || early_microcode=no
+[[ $early_microcode ]] || early_microcode=yes
[[ $logfile_l ]] && logfile="$logfile_l"
[[ $reproducible_l ]] && reproducible="$reproducible_l"
[[ $loginstall_l ]] && loginstall="$loginstall_l"
mkdir -p "$efidir/Linux"
outfile="$efidir/Linux/linux-$kernel${MACHINE_ID:+-${MACHINE_ID}}${BUILD_ID:+-${BUILD_ID}}.efi"
else
- if [[ $MACHINE_ID ]] && ( [[ -d /boot/${MACHINE_ID} ]] || [[ -L /boot/${MACHINE_ID} ]] ); then
+ if [[ -e "/boot/vmlinuz-$kernel" ]]; then
+ outfile="/boot/initramfs-$kernel.img"
+ elif [[ $MACHINE_ID ]] && ( [[ -d /boot/${MACHINE_ID} ]] || [[ -L /boot/${MACHINE_ID} ]] ); then
outfile="/boot/${MACHINE_ID}/$kernel/initrd"
else
outfile="/boot/initramfs-$kernel.img"
if ! [[ $compress ]]; then
# check all known compressors, if none specified
- for i in pigz gzip lz4 lzop lzma xz lbzip2 bzip2 cat; do
+ for i in pigz gzip lz4 lzop zstd lzma xz lbzip2 bzip2 cat; do
command -v "$i" &>/dev/null || continue
compress="$i"
break
lz4)
compress="lz4 -l -9"
;;
+ zstd)
+ compress="zstd -15 -q -T0"
+ ;;
esac
[[ $hostonly = yes ]] && hostonly="-h"
[[ $hostonly != "-h" ]] && unset hostonly
+case $hostonly_mode in
+ '')
+ [[ $hostonly ]] && hostonly_mode="sloppy" ;;
+ sloppy|strict)
+ if [[ ! $hostonly ]]; then
+ unset hostonly_mode
+ fi
+ ;;
+ *)
+ printf "%s\n" "dracut: Invalid hostonly mode '$hostonly_mode'." >&2
+ exit 1
+esac
+
[[ $reproducible == yes ]] && DRACUT_REPRODUCIBLE=1
readonly TMPDIR="$(realpath -e "$tmpdir")"
push_host_devs "${add_device_l[@]}"
fi
-if [[ $hostonly ]]; then
+if [[ $hostonly ]] && [[ "$hostonly_default_device" != "no" ]]; then
# in hostonly mode, determine all devices, which have to be accessed
# and examine them for filesystem types
"/usr/lib64" \
"/boot" \
"/boot/efi" \
+ "/boot/zipl" \
;
do
mp=$(readlink -f "$mp")
push_host_devs "$_dev"
if [[ "$_t" == btrfs ]]; then
- for i in $(find_btrfs_devs "$_m"); do
+ for i in $(btrfs_devs "$_m"); do
push_host_devs "$i"
done
fi
[[ -d $udevdir ]] \
|| udevdir="$(pkg-config udev --variable=udevdir 2>/dev/null)"
if ! [[ -d "$udevdir" ]]; then
- [[ ! -h /lib ]] && [[ -d /lib/udev ]] && udevdir=/lib/udev
- [[ -d /usr/lib/udev ]] && udevdir=/usr/lib/udev
+ [[ -e /lib/udev/collect ]] && udevdir=/lib/udev
+ [[ -e /usr/lib/udev/collect ]] && udevdir=/usr/lib/udev
fi
[[ -d $systemdutildir ]] \
|| systemdutildir=$(pkg-config systemd --variable=systemdutildir 2>/dev/null)
if ! [[ -d "$systemdutildir" ]]; then
- [[ ! -h /lib ]] && [[ -d /lib/systemd ]] && systemdutildir=/lib/systemd
- [[ -d /usr/lib/systemd ]] && systemdutildir=/usr/lib/systemd
+ [[ -e /lib/systemd/systemd-udevd ]] && systemdutildir=/lib/systemd
+ [[ -e /usr/lib/systemd/systemd-udevd ]] && systemdutildir=/usr/lib/systemd
fi
[[ -d $systemdsystemunitdir ]] \
dracutmodules force_add_dracutmodules add_dracutmodules omit_dracutmodules \
mods_to_load \
fw_dir drivers_dir debug no_kernel kernel_only \
- omit_drivers mdadmconf lvmconf root_dev \
+ omit_drivers mdadmconf lvmconf root_devs \
use_fstab fstab_lines libdirs fscks nofscks ro_mnt \
stdloglvl sysloglvl fileloglvl kmsgloglvl logfile \
debug host_fs_types host_devs swap_devs sshkey add_fstab \
## final stuff that has to happen
if [[ $no_kernel != yes ]]; then
+ if [[ $hostonly ]]; then
+ echo "$(get_loaded_kernel_modules)" > $initdir/lib/dracut/loaded-kernel-modules.txt
+ fi
if [[ $drivers ]]; then
hostonly='' instmods $drivers
fi
- if [[ $add_drivers ]]; then
+ if [[ -n "${add_drivers// }" ]]; then
hostonly='' instmods -c $add_drivers
fi
if [[ $force_drivers ]]; then
dinfo "*** Resolving executable dependencies done***"
fi
+ # Now we are done with lazy resolving, always install dependencies
+ unset DRACUT_RESOLVE_LAZY
+ export DRACUT_RESOLVE_DEPS=1
+
# libpthread workaround: pthread_cancel wants to dlopen libgcc_s.so
for _dir in $libdirs; do
for _f in "$_dir/libpthread.so"*; do
fi
fi
-PRELINK_BIN="$(command -v prelink)"
-if [[ $EUID = 0 ]] && [[ $PRELINK_BIN ]]; then
- if [[ $DRACUT_FIPS_MODE ]]; then
- dinfo "*** Installing prelink files ***"
- inst_multiple -o prelink /etc/prelink.conf /etc/prelink.conf.d/*.conf /etc/prelink.cache
- elif [[ $do_prelink == yes ]]; then
- dinfo "*** Pre-linking files ***"
- inst_multiple -o prelink /etc/prelink.conf /etc/prelink.conf.d/*.conf
- chroot "$initdir" "$PRELINK_BIN" -a
- rm -f -- "$initdir/$PRELINK_BIN"
- rm -fr -- "$initdir"/etc/prelink.*
- dinfo "*** Pre-linking files done ***"
- fi
-fi
-
if [[ $do_hardlink = yes ]] && command -v hardlink >/dev/null; then
dinfo "*** Hardlinking files ***"
hardlink "$initdir" 2>&1
done
fi
+# cleanup empty ldconfig_paths directories
+for d in $(ldconfig_paths); do
+ rmdir -p --ignore-fail-on-non-empty "$initdir/$d" >/dev/null 2>&1
+done
+
if [[ $do_strip = yes ]] && ! [[ $DRACUT_FIPS_MODE ]]; then
dinfo "*** Stripping files ***"
find "$initdir" -type f \
exit 1
fi
-if (( maxloglvl >= 5 )); then
+if (( maxloglvl >= 5 )) && (( verbosity_mod_l >= 0 )); then
if [[ $allowlocal ]]; then
"$dracutbasedir/lsinitrd.sh" "${DRACUT_TMPDIR}/initramfs.img"| ddebug
else
command -v restorecon &>/dev/null && restorecon -- "$outfile"
-sync $outfile 2> /dev/null
-if [ $? -ne 0 ] ; then
- dinfo "dracut: sync operartion on newly created initramfs $outfile failed"
- exit 1
+# We sync/fsfreeze only if we're operating on a live booted system.
+# It's possible for e.g. `kernel` to be installed as an RPM BuildRequires or equivalent,
+# and there's no reason to sync, and *definitely* no reason to fsfreeze.
+# Another case where this happens is rpm-ostree, which performs its own sync/fsfreeze
+# globally. See e.g. https://github.com/ostreedev/ostree/commit/8642ef5ab3fec3ac8eb8f193054852f83a8bc4d0
+if test -d /run/systemd/system; then
+ if ! sync "$outfile" 2> /dev/null; then
+ dinfo "dracut: sync operation on newly created initramfs $outfile failed"
+ exit 1
+ fi
+
+ # use fsfreeze only if we're not writing to /
+ if [[ "$(stat -c %m -- "$outfile")" != "/" && "$(stat -f -c %T -- "$outfile")" != "msdos" ]]; then
+ if ! $(fsfreeze -f $(dirname "$outfile") 2>/dev/null && fsfreeze -u $(dirname "$outfile") 2>/dev/null); then
+ dinfo "dracut: warning: could not fsfreeze $(dirname "$outfile")"
+ fi
+ fi
fi
exit 0