Fedora 12 (Constantine) contains a new infrastructure for populating and building an initramfs image called Dracut. Dracut is a replacement for both the mkinitrd build script and the nash script interpreter. The project was started by Jeremy Katz when he worked at Redhat as a result of discussions at a Linux Summit a couple of years ago and some community prodding by David Jones. Currently Harald Hoyer, who works for Redhat, is the owner of the project. In this post I examine Dracut in detail and show the major differences between the existing and new infrastructures.
I assume that if you are reading this post you are somewhat familiar with how Linux (and Fedora in particular) is booted, the purpose of initrd, initramfs and mkinitrd. Dracut continues to use the initramfs architecture but replaces the /sbin/mkinitrd shell script with its own shell script /sbin/dracut, the nash script interpreter with dash (Debian Almquist shell) if available otherwise bash, and a totally new init script.
First let us look at the changes that are or may be visible when you boot your system. If you look at your grub configuration file you will see a number of changes. Here is one stanza from my current configuration file.
title Fedora (2.6.31.6-166.fc12.x86_64) root (hd0,1) kernel /vmlinuz-2.6.31.6-166.fc12.x86_64 ro root=UUID=434794ee-a7ff-4156-aabf-53a79c3d319b LANG=en_US.UTF-8 SYSFONT=latarcyrheb-sun16 KEYBOARDTYPE=pc KEYTABLE=us rhgb quiet initrd /initramfs-2.6.31.6-166.fc12.x86_64.img
The number of arguments on the kernel command line has increased. Now a console language (locale), a console font and keyboard type and table are specified. Console fonts are used to display text (glyphs) on a Linux console. Numerous console fonts are available; they are kept in /lib/kbd/consolefonts. The Unicode console font latarcyrheb-sun16 covers Latin, Cyrillic, Hebrew and Arabic. This is the default Fedora console font. Where specified on the kernel command line, I18N-related parameters will be written to the appropriate file in the initramfs. For example, KEYTABLE=us will be written to the initramfs’s /etc/sysconfig/keyboard, SYSFONT=latarcyrheb-sun16 will be written to the initramfs’s /etc/sysconfig/i18n, and so on.
Numerous other kernel command line options are also supported. These are all documented in the dracut(8) man page. Support for debugging initramfs problems has been significantly improved. Here is a list of the documented debugging options:
- rdinfo – print informational output though “quiet” is set
- rdshell – allow dropping to a shell, if root mounting fails
- rdinitdebug – set -x for the dracut shell and logs to dmesg, console and /init.log
- rdbreak – drop to a shell at the end
- rdbreak={cmdline|pre-udev|pre-trigger|initqueue|pre-mount|mount|pre-pivot} – drop to a shell on defined breakpoint
- rdudevinfo – set udev to loglevel info
- rdudevdebug – set udev to loglevel debug
- rdnetdebug – debug network scripts in dracut. Output is written to /tmp/
The one that I particularly like is the ability to drop into a shell on a defined breakpoint.
Here is the Dracut-related content in /var/log/dmesg when I boot my system with no debugging options set.
dracut: dracut-003-13.4.git8f397a9b.fc12 udev: starting version 145 [drm] Initialized drm 1.1.0 20060810 nouveau 0000:01:00.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16 nouveau 0000:01:00.0: setting latency timer to 64 [drm] nouveau 0000:01:00.0: Detected an NV50 generation card (0x096000c1) [drm] nouveau 0000:01:00.0: Attempting to load BIOS image from PRAMIN [drm] nouveau 0000:01:00.0: ... appears to be valid [drm] nouveau 0000:01:00.0: BIT BIOS found [drm] nouveau 0000:01:00.0: Bios version 62.94.29.00 [drm] nouveau 0000:01:00.0: TMDS table revision 2.0 not currently supported [drm] nouveau 0000:01:00.0: Found Display Configuration Block version 4.0 [drm] nouveau 0000:01:00.0: DCB connector table: VHER 0x40 5 16 4 [drm] nouveau 0000:01:00.0: 0: 0x00001030: type 0x30 idx 0 tag 0x07 [drm] nouveau 0000:01:00.0: 1: 0x00002130: type 0x30 idx 1 tag 0x08 [drm] nouveau 0000:01:00.0: 2: 0x00000210: type 0x10 idx 2 tag 0xff [drm] nouveau 0000:01:00.0: 3: 0x00000211: type 0x11 idx 2 tag 0xff [drm] nouveau 0000:01:00.0: 4: 0x00000213: type 0x13 idx 2 tag 0xff [drm] nouveau 0000:01:00.0: Raw DCB entry 0: 02000300 00000028 [drm] nouveau 0000:01:00.0: Raw DCB entry 1: 01000302 00020030 [drm] nouveau 0000:01:00.0: Raw DCB entry 2: 04011310 00000028 [drm] nouveau 0000:01:00.0: Raw DCB entry 3: 02011312 00020030 [drm] nouveau 0000:01:00.0: Raw DCB entry 4: 010223f1 00c0c080 [drm] nouveau 0000:01:00.0: Parsing VBIOS init table 0 at offset 0xD0BE [drm] nouveau 0000:01:00.0: Parsing VBIOS init table 1 at offset 0xD4D3 [drm] nouveau 0000:01:00.0: Parsing VBIOS init table 2 at offset 0xE4C4 [drm] nouveau 0000:01:00.0: Parsing VBIOS init table 3 at offset 0xE60D [drm] nouveau 0000:01:00.0: Parsing VBIOS init table 4 at offset 0xE849 [drm] nouveau 0000:01:00.0: Parsing VBIOS init table at offset 0xE8AE [drm] nouveau 0000:01:00.0: 0xE8AE: Condition still not met after 20ms, skipping following opcodes [drm] nouveau 0000:01:00.0: 0xC090: parsing output script 0 SELinux: initialized (dev debugfs, type debugfs), uses genfs_contexts SELinux: initialized (dev sockfs, type sockfs), uses task SIDs SELinux: initialized (dev proc, type proc), uses genfs_contexts SELinux: initialized (dev bdev, type bdev), uses genfs_contexts SELinux: initialized (dev rootfs, type rootfs), uses genfs_contexts SELinux: initialized (dev sysfs, type sysfs), uses genfs_contexts type=1403 audit(1260498140.014:3): policy loaded auid=4294967295 ses=4294967295 dracut: Switching root
Here is what is outputted to the console (and to /var/log/boot.log) when the rdinfo option is added to the kernel command line.
WARNING: Deprecated config file /etc/modprobe.conf, all config files belong into /etc/modprobe.d/. dracut: Scanning devices sda3 for LVM volume groups dracut: Reading all physical volumes. This may take a while... dracut: Found volume group "vg_ultra" using metadata type lvm2 dracut: 2 logical volume(s) in volume group "vg_ultra" now active dracut: Mounted root filesystem /dev/dm-0 dracut: Loading SELinux policy dracut: Switching root
Here is what is outputted when rdinitdebug is added to the kernel command line instead of rdinfo:
dracut: + /bin/plymouth --show-splash+ dracut: vinfo dracut: + read line dracut: + [ -e /pre-trigger/30parse-dm.sh ] dracut: + . /pre-trigger/30parse-dm.sh dracut: + getarg rd_NO_DM dracut: + set +x dracut: + return 1 dracut: + getarg nodmraid dracut: + set +x dracut: + return 1 dracut: + [ -e /pre-trigger/30parse-md.sh ] dracut: + . /pre-trigger/30parse-md.sh dracut: + getarg rd_NO_MD dracut: + set +x dracut: + return 1 dracut: + getargs rd_MD_UUID= dracut: + set +x dracut: + return 1 dracut: + MD_UUID= dracut: + [ -n ] dracut: + [ -e /etc/mdadm.conf ] dracut: + getarg rd_NO_MDIMSM dracut: + set +x dracut: + return 1 dracut: + getarg noiswmd dracut: + set +x dracut: + return 1 dracut: + getarg nodmraid dracut: + set +x dracut: + return 1 dracut: + udevadm trigger dracut: + getarg rdbreak=initqueue dracut: + set +x dracut: + return 1 dracut: + i=0 dracut: + : dracut: + check_finished dracut: + local f dracut: + [ -e /initqueue-finished/block.sh ] dracut: + . /initqueue-finished/block.sh dracut: + [ -e /dev/root ] dracut: + return 1 dracut: + udevsettle dracut: + [ -z 145 ] dracut: + [ 145 -ge 143 ] dracut: + udevadm settle --exit-if-exists=/initqueue/work dracut: + check_finished dracut: + local f dracut: + [ -e /initqueue-finished/block.sh ] dracut: + . /initqueue-finished/block.sh dracut: + [ -e /dev/root ] dracut: + return 1 dracut: + [ -f /initqueue/work ] dracut: + [ -e /initqueue/*.sh ] dracut: + break dracut: + udevadm settle --timeout=0 dracut: + modprobe scsi_wait_scan dracut: WARNING: Deprecated config file /etc/modprobe.conf, all config files belong into /etc/modprobe.d/. dracut: + rmmod scsi_wait_scan dracut: + udevadm settle --timeout=0 dracut: + [ -e /initqueue-settled/blocksymlink.sh ] dracut: + job=/initqueue-settled/blocksymlink.sh . /initqueue-settled/blocksymlink.sh dracut: + [ -e /dev/disk/by-uuid/434794ee-a7ff-4156-aabf-53a79c3d319b ] dracut: + check_finished dracut: + local f dracut: + [ -e /initqueue-finished/block.sh ] dracut: + . /initqueue-finished/block.sh dracut: + [ -e /dev/root ] dracut: + return 1 dracut: + [ -e /initqueue-settled/lvm_scan.sh ] dracut: + job=/initqueue-settled/lvm_scan.sh . /initqueue-settled/lvm_scan.sh dracut: + [ -e /initqueue-settled/lvm_scan.sh ] dracut: + rm /initqueue-settled/lvm_scan.sh dracut: + /sbin/lvm_scan dracut: + getargs rd_LVM_VG= dracut: + set +x dracut: + return 1 dracut: + VGS= dracut: + [ -d /etc/lvm ] dracut: + [ -e /tmp/.lvm_scan-sda3 ] dracut: + echo -n sda3 dracut: + lvmdevs=sda3 dracut: + [ ! -e /etc/lvm/lvm.conf ] dracut: + info Scanning devices sda3 for LVM volume groups dracut: + [ -z ] dracut: + DRACUT_QUIET=no dracut: + getarg quiet dracut: + set +x dracut: + return 1 dracut: + echo <6>dracut: Scanning devices sda3 for LVM volume groups dracut: + [ yes != yes ] dracut: + lvm vgscan dracut: + vinfo dracut: + read line dracut: + info Reading all physical volumes. This may take a while... dracut: + [ -z yes ] dracut: + echo <6>dracut: Reading all physical volumes. This may take a while... dracut: + [ yes != yes ] dracut: + read line dracut: + info Found volume group "vg_ultra" using metadata type lvm2 dracut: + [ -z yes ] dracut: + echo <6>dracut: Found volume group "vg_ultra" using metadata type lvm2 dracut: + [ yes != yes ] dracut: + read line dracut: + lvm vgchange+ -ay dracut: vinfo dracut: + read line dracut: + info 2 logical volume(s) in volume group "vg_ultra" now active dracut: + [ -z yes ] dracut: + echo <6>dracut: 2 logical volume(s) in volume group "vg_ultra" now active dracut: + [ yes != yes ] dracut: + read line dracut: + [ ] dracut: + unset lvmwritten dracut: + check_finished dracut: + local f dracut: + [ -e /initqueue-finished/block.sh ] dracut: + . /initqueue-finished/block.sh dracut: + [ -e /dev/root ] dracut: + return 1 dracut: + udevadm settle --timeout=0 dracut: + continue dracut: + : dracut: + check_finished dracut: + local f dracut: + [ -e /initqueue-finished/block.sh ] dracut: + . /initqueue-finished/block.sh dracut: + [ -e /dev/root ] dracut: + return 1 dracut: + udevsettle dracut: + [ -z 145 ] dracut: + [ 145 -ge 143 ] dracut: + udevadm settle --exit-if-exists=/initqueue/work dracut: + check_finished dracut: + local f dracut: + [ -e /initqueue-finished/block.sh ] dracut: + . /initqueue-finished/block.sh dracut: + [ -e /dev/root ] dracut: + return 0 dracut: + break dracut: + unset job dracut: + unset queuetriggered dracut: + getarg rdbreak=pre-mount dracut: + set +x dracut: + return 1 dracut: + source_all pre-mount dracut: + local f dracut: + [ pre-mount ] dracut: + [ -d /pre-mount ] dracut: + return dracut: + getarg rdbreak=mount dracut: + set +x dracut: + return 1 dracut: + i=0 dracut: + : dracut: + [ -d /sysroot/proc ] dracut: + [ -f /mount/10resume.sh ] dracut: + . /mount/10resume.sh dracut: + [ -s /.resume -a -b ] dracut: + [ -d /sysroot/proc ] dracut: + [ -f /mount/99mount-root.sh ] dracut: + . /mount/99mount-root.sh dracut: + [ -n block:/dev/disk/by-uuid/434794ee-a7ff-4156-aabf-53a79c3d319b -a -z ] dracut: + mount -t auto -o ro /dev/disk/by-uuid/434794ee-a7ff-4156-aabf-53a79c3d319b /sysroot dracut: + ROOTFS_MOUNTED=yes dracut: + [ -d /sysroot/proc ] dracut: + break dracut: + i=1 dracut: + [ 1 -gt 20 ] dracut: + : dracut: + [ -d /sysroot/proc ] dracut: + break dracut: + echo -n Mounted root filesystem dracut: + vinfo dracut: + read line dracut: + read dev mp rest dracut: + [ / = /sysroot ] dracut: + read dev mp rest dracut: + [ /proc = /sysroot ] dracut: + read dev mp rest dracut: + [ /sys = /sysroot ] dracut: + read dev mp rest dracut: + [ /dev = /sysroot ] dracut: + read dev mp rest dracut: + [ /dev/pts = /sysroot ] dracut: + read dev mp rest dracut: + [ /dev/shm = /sysroot ] dracut: + read dev mp rest dracut: + [ /sysroot = /sysroot ] dracut: + echo /dev/dm-0 dracut: + info Mounted root filesystem /dev/dm-0 dracut: + [ -z yes ] dracut: + echo <6>dracut: Mounted root filesystem /dev/dm-0 dracut: + [ yes != yes ] dracut: + read line dracut: + read dev mp rest dracut: + getarg rdbreak=pre-pivot dracut: + set +x dracut: + return 1 dracut: + source_all pre-pivot dracut: + local f dracut: + [ pre-pivot ] dracut: + [ -d /pre-pivot ] dracut: + [ -e /pre-pivot/30crypt-cleanup.sh ] dracut: + . /pre-pivot/30crypt-cleanup.sh dracut: + cryptsetup luksClose /dev/mapper/luks-* dracut: + [ -e /pre-pivot/31crypt-cleanup.sh ] dracut: + . /pre-pivot/31crypt-cleanup.sh dracut: + cryptsetup luksClose /dev/mapper/luks-* dracut: + [ -e /pre-pivot/50selinux-loadpolicy.sh ] dracut: + . /pre-pivot/50selinux-loadpolicy.sh dracut: + rd_load_policy dracut: + SELINUX=enforcing dracut: + [ -e /sysroot/etc/selinux/config ] dracut: + . /sysroot/etc/selinux/config dracut: + SELINUX=enforcing dracut: + SELINUXTYPE=targeted dracut: + getarg selinux=0 dracut: + set +x dracut: + return 1 dracut: + [ 1 -eq 0 -o enforcing = disabled ] dracut: + permissive=0 dracut: + getarg enforcing=0 dracut: + set +x dracut: + return 1 dracut: + [ 1 -eq 0 -o enforcing = permissive ] dracut: + [ -x /sysroot/usr/sbin/load_policy -o -x /sysroot/sbin/load_policy ] dracut: + ret=0 dracut: + info Loading SELinux policy dracut: + [ -z yes ] dracut: + echo <6>dracut: Loading SELinux policy dracut: + [ yes != yes ] dracut: + vinfo dracut: + read line dracut: + info + [ -x /sysroot/sbin/load_policy ] dracut: + [ -z yes ] dracut: + echo <6>dracut: + [ -x /sysroot/sbin/load_policy ] dracut: + [ yes != yes ] dracut: + read line dracut: + info + chroot /sysroot /sbin/load_policy -i dracut: + [ -z yes ] dracut: + echo <6>dracut: + chroot /sysroot /sbin/load_policy -i dracut: + [ yes != yes ] dracut: + read line dracut: + info + ret=0 dracut: + [ -z yes ] dracut: + echo <6>dracut: + ret=0 dracut: + [ yes != yes ] dracut: + read line dracut: + [ 0 -eq 0 -o 0 -eq 2 ] dracut: + return 0 dracut: + [ -e /pre-pivot/90plymouth-newroot.sh ] dracut: + . /pre-pivot/90plymouth-newroot.sh dracut: + [ -x /bin/plymouth ] dracut: + /bin/plymouth --newroot=/sysroot dracut: + getarg init= dracut: + set +x dracut: + return 1 dracut: + [ -f /sysroot -a -x /sysroot ] dracut: + [ -f /sysroot/sbin/init -a -x /sysroot/sbin/init ] dracut: + INIT=/sbin/init dracut: + break dracut: + [ /sbin/init ] dracut: + getarg rdbreak dracut: + set +x dracut: + return 1 dracut: + udevadm control --stop-exec-queue dracut: + HARD= dracut: + pidof udevd dracut: + pidof udevd dracut: + kill 187 dracut: + kill 186 dracut: + kill 185 dracut: + kill 184 dracut: + kill 183 dracut: + kill 182 dracut: + kill 180 dracut: + kill 179 dracut: + kill 177 dracut: + kill 175 dracut: + kill 169 dracut: + kill 166 dracut: + kill 136 dracut: + kill 134 dracut: + kill 133 dracut: + kill 132 dracut: + kill 131 dracut: + kill 130 dracut: + kill 129 dracut: + kill 126 dracut: + kill 124 dracut: + HARD=-9 dracut: + pidof udevd dracut: + pidof udevd dracut: + kill -9 124 dracut: + HARD=-9 dracut: + pidof udevd dracut: + pidof udevd dracut: + kill -9 124 dracut: + HARD=-9 dracut: + pidof udevd dracut: + export -p dracut: + i=export dracut: + i= dracut: + i= dracut: + [ = root -o = PATH -o = HOME -o = TERM ] dracut: + unset dracut: + i=HOME='/' dracut: + i=HOME='/' dracut: + i=HOME dracut: + [ HOME = root -o HOME = PATH -o HOME = HOME -o HOME = TERM ] dracut: + i=export dracut: + i= dracut: + i= dracut: + [ = root -o = PATH -o = HOME -o = TERM ] dracut: + unset dracut: + i=KEYBOARDTYPE='pc' dracut: + i=KEYBOARDTYPE='pc' dracut: + i=KEYBOARDTYPE dracut: + [ KEYBOARDTYPE = root -o KEYBOARDTYPE = PATH -o KEYBOARDTYPE = HOME -o KEYBOARDTYPE = TERM ] dracut: + unset KEYBOARDTYPE dracut: + i=export dracut: + i= dracut: + i= dracut: + [ = root -o = PATH -o = HOME -o = TERM ] dracut: + unset dracut: + i=KEYTABLE='us' dracut: + i=KEYTABLE='us' dracut: + i=KEYTABLE dracut: + [ KEYTABLE = root -o KEYTABLE = PATH -o KEYTABLE = HOME -o KEYTABLE = TERM ] dracut: + unset KEYTABLE dracut: + i=export dracut: + i= dracut: + i= dracut: + [ = root -o = PATH -o = HOME -o = TERM ] dracut: + unset dracut: + i=LANG='en_US.UTF-8' dracut: + i=LANG='en_US.UTF-8' dracut: + i=LANG dracut: + [ LANG = root -o LANG = PATH -o LANG = HOME -o LANG = TERM ] dracut: + unset LANG dracut: + i=export dracut: + i= dracut: + i= dracut: + [ = root -o = PATH -o = HOME -o = TERM ] dracut: + unset dracut: + i=PATH='/sbin:/bin:/usr/sbin:/usr/bin' dracut: + i=PATH='/sbin:/bin:/usr/sbin:/usr/bin' dracut: + i=PATH dracut: + [ PATH = root -o PATH = PATH -o PATH = HOME -o PATH = TERM ] dracut: + i=export dracut: + i= dracut: + i= dracut: + [ = root -o = PATH -o = HOME -o = TERM ] dracut: + unset dracut: + i=PWD='/' dracut: + i=PWD='/' dracut: + i=PWD dracut: + [ PWD = root -o PWD = PATH -o PWD = HOME -o PWD = TERM ] dracut: + unset PWD dracut: + i=export dracut: + i= dracut: + i= dracut: + [ = root -o = PATH -o = HOME -o = TERM ] dracut: + unset dracut: + i=SYSFONT='latarcyrheb-sun16' dracut: + i=SYSFONT='latarcyrheb-sun16' dracut: + i=SYSFONT dracut: + [ SYSFONT = root -o SYSFONT = PATH -o SYSFONT = HOME -o SYSFONT = TERM ] dracut: + unset SYSFONT dracut: + i=export dracut: + i= dracut: + i= dracut: + [ = root -o = PATH -o = HOME -o = TERM ] dracut: + unset dracut: + i=TERM='linux' dracut: + i=TERM='linux' dracut: + i=TERM dracut: + [ TERM = root -o TERM = PATH -o TERM = HOME -o TERM = TERM ] dracut: + i=export dracut: + i= dracut: + i= dracut: + [ = root -o = PATH -o = HOME -o = TERM ] dracut: + unset dracut: + i=ip='eth0:dhcp' dracut: + i=ip='eth0:dhcp' dracut: + i=ip dracut: + [ ip = root -o ip = PATH -o ip = HOME -o ip = TERM ] dracut: + unset ip dracut: + initargs= dracut: + getarg init= dracut: + set +x dracut: + return 1 dracut: + [ -e /tmp/net.ifaces ] dracut: + getarg rdcopystate dracut: + set +x dracut: + return 1 dracut: + info Switching root dracut: + [ -z yes ] dracut: + echo <6>dracut: Switching root dracut: + [ yes != yes ] dracut: + wait_for_loginit dracut: + getarg rdinitdebug dracut: + set +x + exec switch_root /sysroot /sbin/init
The first thing you will notice is that the init script immediately invokes Plymouth (which I discussed recently in another post. If you do not want Plymouth to be started by Dracut, add rd_NO_PLYMOUTH (can anybody explain why part of this option in uppercase?) to the kernel command line. Note that, according to the man page, this will not work with encrypted partitions.
Turning now to the question of how to build a new initramfs file using Dracut. If you want to build a generic initramfs file using Dracut, which should be able to boot any bootable configuration given the appropriate boot flags (root device, network configuration information, etc.) the following packages must be installed on your system:
- cryptsetup-luks
- device-mapper
- iscsi-initiator-utils
- lvm2
- mdadm
- nbd
- net-tools iproute
- rpcbind nfs-utils
Note that a generic initramfs file is huge. The following three files show the difference in size between a 2.6.30.96 initrd made using /sbin/mkinitrd, the same one made using Dracut and a generic one made using Dracut:
-rw-------. 1 root root 3774369 2009-11-11 13:18 /boot/initrd-2.6.30.9-96.fc11.x86_64.img -rw-r--r--. 1 root root 4163575 2009-11-13 17:19 /boot/initrd-dracut-2.6.30.9-96.fc11.x86_64.img -rw-r--r--. 1 root root 14971825 2009-11-13 16:09 /boot/initrd-dracut-generic-2.6.30.9-96.fc11.x86_64.img
Most of the functionality that Dracut implements is actually implemented by individual Dracut (generator) modules that are sourced by the main Dracut script to install specific functionality into the initramfs directory structure using additional functionality provided by /usr/share/dracut/dracut-functions. Dracut modules live in subdirectories under /usr/share/dracut/modules.d/. Each module name is prefixed by a two-digit numeric sort code in the range of 00 to 99, e.g. 50plymouth. Modules with lower numbers are installed first in the initramfs directory structure. Each module takes 2 standard arguments – install and check. Install is used to install the module functionality onto the initramfs directory structure in a controlled manner. Mainly this consists of copying files into the initramfs directory structure. The check option is used by Dracut to check that all the files that the modules needs to install into the initramfs from the host system are present. Check can take a number of options. For example the -h option is used to check if the functionality implemented by the module is actually being used by the host system. The -d option outputs a list of other dracut modules that a module has dependencies on.
The following modules are part of the initial release of Dracut: i18n, network, plymouth, crypt, dmraid, lvm, mdraid, dmsquash-live, fcoe, iscsi, nbd, nfs, resume, rootfs-block and s390. Let us example one module, i.e. plymouth, in more detail. This module consists of a total of 8 shell scripts. (Interestingly, the file utility reports a mix of Bourne shell and POSIX shell scripts!)
# pwd /usr/share/dracut/modules.d/50plymouth # ls -l total 32 -rwxr-xr-x. 1 root root 128 2009-09-29 12:29 check -rwxr-xr-x. 1 root root 815 2009-09-29 12:29 cryptroot-ask.sh -rwxr-xr-x. 1 root root 641 2009-09-29 12:29 install -rwxr-xr-x. 1 root root 191 2009-09-29 12:29 installkernel -rw-r--r--. 1 root root 52 2009-09-29 12:29 plymouth-emergency.sh -rwxr-xr-x. 1 root root 79 2009-09-29 12:29 plymouth-newroot.sh -rwxr-xr-x. 1 root root 1633 2009-09-29 12:29 plymouth-populate-initrd -rwxr-xr-x. 1 root root 756 2009-09-29 12:29 plymouth-pretrigger.sh # file * check: Bourne-Again shell script text executable cryptroot-ask.sh: POSIX shell script text executable install: Bourne-Again shell script text executable installkernel: Bourne-Again shell script text executable plymouth-emergency.sh: ASCII text plymouth-newroot.sh: POSIX shell script text executable plymouth-populate-initrd: Bourne-Again shell script text executable plymouth-pretrigger.sh: POSIX shell script text executable
Here is the install script:
#!/bin/bash if grep -q nash /usr/libexec/plymouth/plymouth-populate-initrd \ || ! grep -q PLYMOUTH_POPULATE_SOURCE_FUNCTIONS /usr/libexec/plymouth/plymouth-populate-initrd \ || [ ! -x /usr/libexec/plymouth/plymouth-populate-initrd ]; then . "$moddir"/plymouth-populate-initrd else PLYMOUTH_POPULATE_SOURCE_FUNCTIONS="$dracutfunctions" \ /usr/libexec/plymouth/plymouth-populate-initrd -t $initdir fi inst_hook pre-pivot 90 "$moddir"/plymouth-newroot.sh inst_hook pre-trigger 10 "$moddir"/plymouth-pretrigger.sh inst_hook emergency 50 "$moddir"/plymouth-emergency.sh inst "$moddir"/cryptroot-ask.sh /sbin/cryptroot-ask
and here is what is in the check script
#!/bin/bash [[ $1 = -d ]] && echo crypt [[ -x /sbin/plymouthd && -x /bin/plymouth && -x /usr/sbin/plymouth-set-default-theme ]]
Dracut can have a number of configuration files. The main configuration file is /etc/dracut.conf. Here is what comes out-of-the-box with Fedora 12.
# Sample dracut config file # Specific list of dracut modules to use #dracutmodules="" # Dracut modules to omit #omit_dracutmodules="" # additional kernel modules to the default #add_drivers="" # build initrd only to boot current hardware #hostonly="-h" # install local /etc/mdadm.conf mdadmconf="yes" # install local /etc/lvm/lvm.conf lvmconf="yes"
Unfortunately no details of what options can be placed in the configuration file are detailed in the Dracut man page or elsewhere.
Traditionally on Fedora /sbin/mkinitrd was used to build a new initramfs. Here is the contents of an initramfs file which was build for a Fedora 11 system using mkinitrd:
init sbin etc etc/ld.so.conf.d etc/ld.so.conf.d/mysql-x86_64.conf etc/ld.so.conf.d/kernel-2.6.29.6-217.2.16.fc11.x86_64.conf etc/ld.so.conf.d/kernel-2.6.30.9-96.fc11.x86_64.conf etc/ld.so.conf.d/nvidia-lib64.conf etc/ld.so.conf.d/atlas-x86_64.conf etc/ld.so.conf.d/kernel-2.6.29.6-217.2.8.fc11.x86_64.conf etc/ld.so.conf.d/xulrunner-64.conf etc/ld.so.conf.d/qt-x86_64.conf etc/ld.so.conf.d/kernel-2.6.30.5-43.fc11.x86_64.conf etc/ld.so.cache etc/sysconfig etc/sysconfig/i18n etc/sysconfig/keyboard etc/lvm etc/lvm/lvm.conf etc/fedora-release etc/system-release etc/ld.so.conf usr usr/lib64 usr/lib64/plymouth usr/lib64/plymouth/details.so usr/lib64/plymouth/text.so usr/lib64/plymouth/space-flares.so usr/lib64/libpng12.so.0.37.0 usr/lib64/libnl.so.1 usr/lib64/libelf.so.1 usr/lib64/libnl.so.1.1 usr/lib64/libbdevid.so.6.0.87 usr/lib64/libnash.so.6.0.87 usr/lib64/libpng12.so.0 usr/lib64/libplybootsplash.so.2.0.0 usr/lib64/libplybootsplash.so.2 usr/lib64/libelf-0.142.so usr/share usr/share/plymouth usr/share/plymouth/bizcom.png usr/share/plymouth/themes usr/share/plymouth/themes/details usr/share/plymouth/themes/details/details.plymouth usr/share/plymouth/themes/text usr/share/plymouth/themes/text/text.plymouth usr/share/plymouth/themes/default.plymouth usr/share/plymouth/themes/solar usr/share/plymouth/themes/solar/progress_bar.png usr/share/plymouth/themes/solar/star.png usr/share/plymouth/themes/solar/lock.png usr/share/plymouth/themes/solar/solar.plymouth usr/share/plymouth/themes/solar/bullet.png usr/share/plymouth/themes/solar/box.png usr/share/plymouth/themes/solar/entry.png sys lib64 lib64/libpopt.so.0.0.0 lib64/libparted-1.8.so.8 lib64/libgcc_s.so.1 lib64/libz.so.1 lib64/libpthread.so.0 lib64/libc.so.6 lib64/libpthread-2.10.1.so lib64/libuuid.so.1 lib64/libpopt.so.0 lib64/libz.so.1.2.3 lib64/libtinfo.so.5.7 lib64/libgcc_s-4.4.1-20090729.so.1 lib64/librt.so.1 lib64/libreadline.so.5 lib64/libdl-2.10.1.so lib64/libparted-1.8.so.8.0.0 lib64/libglib-2.0.so.0 lib64/libreadline.so.5.2 lib64/libm.so.6 lib64/librt-2.10.1.so lib64/libtinfo.so.5 lib64/libuuid.so.1.2 lib64/libglib-2.0.so.0.2000.5 lib64/libply.so.2.0.0 lib64/libselinux.so.1 lib64/libply.so.2 lib64/libblkid.so.1.0 lib64/libresolv.so.2 lib64/libblkid.so.1 lib64/libsepol.so.1 lib64/libc-2.10.1.so lib64/libm-2.10.1.so lib64/libdl.so.2 lib64/ld-linux-x86-64.so.2 lib64/ld-2.10.1.so lib64/libdevmapper.so.1.02 lib64/libresolv-2.10.1.so bin bin/nash bin/setfont bin/loadkeys bin/plymouth bin/plymouthd bin/modprobe bin/rmmod bin/lvm lib lib/kbd lib/kbd/consolefonts lib/kbd/consolefonts/latarcyrheb-sun16.psfu lib/kbd/keymaps lib/kbd/keymaps/i386 lib/kbd/keymaps/i386/include lib/kbd/keymaps/i386/include/linux-with-alt-and-altgr.inc lib/kbd/keymaps/i386/include/linux-keys-bare.inc lib/kbd/keymaps/i386/include/euro1.map lib/kbd/keymaps/i386/include/compose.inc lib/kbd/keymaps/i386/include/qwerty-layout.inc lib/kbd/keymaps/i386/qwerty lib/kbd/keymaps/i386/qwerty/us.map lib/kbd/keymaps/include lib/kbd/keymaps/include/compose.latin4 lib/kbd/keymaps/include/compose.8859_8 lib/kbd/keymaps/include/compose.latin1 lib/kbd/keymaps/include/compose.latin3 lib/kbd/keymaps/include/compose.8859_7 lib/kbd/keymaps/include/compose.latin2 lib/kbd/keymaps/include/compose.latin lib/modules lib/modules/2.6.30.9-96.fc11.x86_64 lib/modules/2.6.30.9-96.fc11.x86_64/scsi_wait_scan.ko lib/modules/2.6.30.9-96.fc11.x86_64/modules.symbols lib/modules/2.6.30.9-96.fc11.x86_64/modules.alias.bin lib/modules/2.6.30.9-96.fc11.x86_64/modules.alias lib/modules/2.6.30.9-96.fc11.x86_64/modules.symbols.bin lib/modules/2.6.30.9-96.fc11.x86_64/modules.ofmap lib/modules/2.6.30.9-96.fc11.x86_64/modules.pcimap lib/modules/2.6.30.9-96.fc11.x86_64/modules.dep lib/modules/2.6.30.9-96.fc11.x86_64/modules.isapnpmap lib/modules/2.6.30.9-96.fc11.x86_64/modules.dep.bin lib/modules/2.6.30.9-96.fc11.x86_64/modules.usbmap lib/modules/2.6.30.9-96.fc11.x86_64/modules.ccwmap lib/modules/2.6.30.9-96.fc11.x86_64/modules.seriomap lib/modules/2.6.30.9-96.fc11.x86_64/modules.inputmap lib/modules/2.6.30.9-96.fc11.x86_64/modules.ieee1394map lib/firmware lib/udev lib/udev/console_init sysroot dev dev/ttyS1 dev/tty6 dev/tty12 dev/tty9 dev/ptmx dev/tty2 dev/tty dev/ttyS0 dev/mapper dev/ttyS2 dev/tty1 dev/tty3 dev/tty0 dev/console dev/tty4 dev/ttyS3 dev/ram0 dev/tty5 dev/null dev/zero dev/systty dev/ram1 dev/tty10 dev/tty11 dev/ram dev/tty8 dev/tty7 proc 16476 blocks
As you can see the script interpreter is nash.
Here is the init script which nash uses to start the boot process.
#!/bin/nash mount -t proc /proc /proc setquiet echo Mounting proc filesystem echo Mounting sysfs filesystem mount -t sysfs /sys /sys echo Creating /dev mount -o mode=0755 -t tmpfs /dev /dev mkdir /dev/pts mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts mkdir /dev/shm mkdir /dev/mapper echo Creating initial device nodes mknod /dev/null c 1 3 mknod /dev/zero c 1 5 mknod /dev/systty c 4 0 mknod /dev/tty c 5 0 mknod /dev/console c 5 1 mknod /dev/ptmx c 5 2 mknod /dev/fb c 29 0 mknod /dev/hvc0 c 229 0 mknod /dev/tty0 c 4 0 mknod /dev/tty1 c 4 1 mknod /dev/tty2 c 4 2 mknod /dev/tty3 c 4 3 mknod /dev/tty4 c 4 4 mknod /dev/tty5 c 4 5 mknod /dev/tty6 c 4 6 mknod /dev/tty7 c 4 7 mknod /dev/tty8 c 4 8 mknod /dev/tty9 c 4 9 mknod /dev/tty10 c 4 10 mknod /dev/tty11 c 4 11 mknod /dev/tty12 c 4 12 mknod /dev/ttyS0 c 4 64 mknod /dev/ttyS1 c 4 65 mknod /dev/ttyS2 c 4 66 mknod /dev/ttyS3 c 4 67 daemonize --ignore-missing /bin/plymouthd echo Setting up hotplug. hotplug /lib/udev/console_init tty0 plymouth --show-splash echo Creating block device nodes. mkblkdevs echo Creating character device nodes. mkchardevs echo Making device-mapper control node mkdmnod modprobe scsi_wait_scan rmmod scsi_wait_scan mkblkdevs echo Scanning logical volumes lvm vgscan --ignorelockingfailure echo Activating logical volumes lvm vgchange -ay --ignorelockingfailure vg_ultra resume /dev/mapper/vg_ultra-lv_swap echo Creating root device. mkrootdev -t ext4 -o defaults,ro /dev/mapper/vg_ultra-lv_root echo Mounting root filesystem. mount /sysroot cond -ne 0 plymouth --hide-splash echo Setting up other filesystems. setuproot loadpolicy plymouth --newroot=/sysroot echo Switching to new root and running init. switchroot echo Booting has failed. sleep -1
In Fedora 12, /sbin/mkinitrd is not available and the shell script /sbin/dracut must be used to build an initramfs file. Like mkinitrd, this script has numerous options but you will probably never need to use most of them. Like mkinitrd, the script creates a series of subdirectories and populates them with assorted files using various Dracut modules from the /usr/share/dracut/modules.d subdirectories. Finally, it uses the following command line to create the image file:
( cd "$initdir"; find . |cpio -R 0:0 -H newc -o --quiet |gzip -9 > "$outfile"; )
Here is the contents of a functionally equivalent initramfs built on Fedora 11 using /sbin/dracut instead of /sbin/mkinitrd:
init initqueue-settled pre-udev pre-udev/30block-genrules.sh pre-udev/30resume-genrules.sh pre-pivot pre-pivot/31crypt-cleanup.sh pre-pivot/50selinux-loadpolicy.sh pre-pivot/30crypt-cleanup.sh pre-pivot/90plymouth-newroot.sh tmp dracut-002-9.git99fd62e3.fc11 var var/run sbin sbin/initqueue sbin/cryptsetup sbin/switch_root sbin/pidof sbin/modprobe sbin/lvm_scan sbin/udevd sbin/lvm-cleanup sbin/rmmod sbin/lvm sbin/udevadm sbin/cryptroot-ask initqueue etc etc/sysconfig etc/sysconfig/i18n etc/sysconfig/keyboard etc/udev etc/udev/rules.d etc/udev/rules.d/64-lvm.rules etc/udev/rules.d/59-persistent-storage-volid.rules etc/udev/rules.d/61-persistent-storage.rules etc/udev/rules.d/95-udev-late.rules etc/udev/rules.d/80-drivers.rules etc/udev/rules.d/01-ignore.rules etc/udev/rules.d/60-pcmcia.rules etc/udev/rules.d/61-persistent-storage-edd.rules etc/udev/rules.d/50-firmware.rules etc/udev/rules.d/60-persistent-storage.rules etc/udev/rules.d/70-luks.rules etc/udev/rules.d/10-console.rules etc/udev/rules.d/50-udev-default.rules etc/udev/udev.conf etc/lvm etc/lvm/lvm.conf etc/modprobe.d etc/modprobe.d/dist-oss.conf etc/modprobe.d/blacklist-visor.conf etc/modprobe.d/ipv6.conf etc/modprobe.d/blacklist.conf etc/modprobe.d/blacklist-nouveau.conf etc/modprobe.d/floppy-pnp.conf etc/modprobe.d/dist.conf etc/modprobe.d/anaconda.conf etc/fedora-release etc/system-release etc/group initqueue-finished usr usr/sbin usr/sbin/chroot usr/lib64 usr/lib64/libusb-0.1.so.4 usr/lib64/plymouth usr/lib64/plymouth/details.so usr/lib64/plymouth/text.so usr/lib64/libpng12.so.0.37.0 usr/lib64/libpng12.so.0 usr/lib64/libplybootsplash.so.2.0.0 usr/lib64/libplybootsplash.so.2 usr/lib64/libusb-0.1.so.4.4.4 usr/bin usr/bin/flock usr/lib usr/share usr/share/plymouth usr/share/plymouth/bizcom.png usr/share/plymouth/themes usr/share/plymouth/themes/details usr/share/plymouth/themes/details/details.plymouth usr/share/plymouth/themes/text usr/share/plymouth/themes/text/text.plymouth usr/share/plymouth/themes/default.plymouth sys emergency emergency/50plymouth-emergency.sh lib64 lib64/libgpg-error.so.0.4.0 lib64/libpopt.so.0.0.0 lib64/libnss_files-2.10.1.so lib64/libz.so.1 lib64/libpthread.so.0 lib64/libattr.so.1.1.0 lib64/libc.so.6 lib64/libpthread-2.10.1.so lib64/libuuid.so.1 lib64/libvolume_id.so.1 lib64/libpopt.so.0 lib64/libz.so.1.2.3 lib64/libtinfo.so.5.7 lib64/libudev.so.0 lib64/librt.so.1 lib64/libreadline.so.5 lib64/libcryptsetup.so.0.0.0 lib64/libdl-2.10.1.so lib64/libglib-2.0.so.0 lib64/libreadline.so.5.2 lib64/libm.so.6 lib64/libvolume_id.so.1.1.0 lib64/libacl.so.1 lib64/librt-2.10.1.so lib64/libtinfo.so.5 lib64/libuuid.so.1.2 lib64/libcap.so.2 lib64/libgcrypt.so.11 lib64/libglib-2.0.so.0.2000.5 lib64/libudev.so.0.2.0 lib64/libply.so.2.0.0 lib64/libacl.so.1.1.0 lib64/libselinux.so.1 lib64/libply.so.2 lib64/libcryptsetup.so.0 lib64/libblkid.so.1.0 lib64/libgcrypt.so.11.5.2 lib64/libblkid.so.1 lib64/libsepol.so.1 lib64/libc-2.10.1.so lib64/libcap.so.2.16 lib64/libm-2.10.1.so lib64/libdl.so.2 lib64/ld-linux-x86-64.so.2 lib64/libattr.so.1 lib64/ld-2.10.1.so lib64/libdevmapper.so.1.02 lib64/libgpg-error.so.0 lib64/libnss_files.so.2 bin bin/setfont bin/cp bin/loadkeys bin/plymouth bin/uname bin/ln bin/mkdir bin/cat bin/rm bin/plymouthd bin/sleep bin/basename bin/sh bin/mknod bin/ls bin/mount bin/mv bin/sed bin/dmesg bin/dash mount mount/99mount-root.sh mount/10resume.sh lib lib/dracut-lib.sh lib/kbd lib/kbd/consolefonts lib/kbd/consolefonts/latarcyrheb-sun16.psfu lib/kbd/keymaps lib/kbd/keymaps/i386 lib/kbd/keymaps/i386/include lib/kbd/keymaps/i386/include/linux-with-alt-and-altgr.inc lib/kbd/keymaps/i386/include/linux-keys-bare.inc lib/kbd/keymaps/i386/include/euro1.map lib/kbd/keymaps/i386/include/compose.inc lib/kbd/keymaps/i386/include/qwerty-layout.inc lib/kbd/keymaps/i386/qwerty lib/kbd/keymaps/i386/qwerty/us.map lib/kbd/keymaps/include lib/kbd/keymaps/include/compose.latin4 lib/kbd/keymaps/include/compose.8859_8 lib/kbd/keymaps/include/compose.latin1 lib/kbd/keymaps/include/compose.latin3 lib/kbd/keymaps/include/compose.8859_7 lib/kbd/keymaps/include/compose.latin2 lib/kbd/keymaps/include/compose.latin lib/modules lib/modules/2.6.30.9-96.fc11.x86_64 lib/modules/2.6.30.9-96.fc11.x86_64/modules.symbols lib/modules/2.6.30.9-96.fc11.x86_64/modules.alias.bin lib/modules/2.6.30.9-96.fc11.x86_64/modules.alias lib/modules/2.6.30.9-96.fc11.x86_64/modules.symbols.bin lib/modules/2.6.30.9-96.fc11.x86_64/modules.ofmap lib/modules/2.6.30.9-96.fc11.x86_64/modules.pcimap lib/modules/2.6.30.9-96.fc11.x86_64/modules.dep lib/modules/2.6.30.9-96.fc11.x86_64/modules.isapnpmap lib/modules/2.6.30.9-96.fc11.x86_64/modules.dep.bin lib/modules/2.6.30.9-96.fc11.x86_64/modules.usbmap lib/modules/2.6.30.9-96.fc11.x86_64/modules.ccwmap lib/modules/2.6.30.9-96.fc11.x86_64/modules.seriomap lib/modules/2.6.30.9-96.fc11.x86_64/kernel lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/i2c lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/i2c/algos lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/i2c/algos/i2c-algo-bit.ko lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/i2c/i2c-core.ko lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/scsi lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/scsi/scsi_wait_scan.ko lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/gpu lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/gpu/drm lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/gpu/drm/drm.ko lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/gpu/drm/nouveau lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/gpu/drm/nouveau/nouveau.ko lib/modules/2.6.30.9-96.fc11.x86_64/modules.inputmap lib/modules/2.6.30.9-96.fc11.x86_64/modules.ieee1394map lib/udev lib/udev/edd_id lib/udev/hid2hci lib/udev/vol_id lib/udev/firmware.sh lib/udev/usb_id lib/udev/ata_id lib/udev/pcmcia-socket-startup lib/udev/rules.d lib/udev/fw_unit_symlinks.sh lib/udev/pcmcia-check-broken-cis lib/udev/scsi_id lib/udev/console_init lib/udev/path_id lib/udev/create_floppy_devices lib/udev/cdrom_id lib/terminfo lib/terminfo/d lib/terminfo/d/dumb lib/terminfo/a lib/terminfo/a/ansi lib/terminfo/l lib/terminfo/l/linux lib/terminfo/v lib/terminfo/v/vt100-nav lib/terminfo/v/vt100 lib/terminfo/v/vt200 lib/terminfo/v/vt102 lib/terminfo/v/vt100-am lib/terminfo/v/vt52 lib/terminfo/v/vt220 cmdline cmdline/30parse-lvm.sh cmdline/01version.sh cmdline/10parse-root-opts.sh cmdline/30parse-crypt.sh cmdline/20parse-blacklist.sh cmdline/95parse-block.sh cmdline/20parse-i18n.sh cmdline/10parse-resume.sh pre-trigger pre-trigger/10plymouth-pretrigger.sh sysroot dev dev/pts proc
Note that the nash script interpreter is not part of the initramfs image. Instead /bin/dash is included. The following is the contents of the init script from this initramfs. As you can see it is significantly different from the init script included in the initramfs built using /sbin/mkinitrd.
#!/bin/sh # # Licensed under the GPLv2 # # Copyright 2008, Red Hat, Inc. # Jeremy Katzemergency_shell() { exec >/dev/console 2>&1 </dev/console echo ; echo echo $@ source_all emergency echo if getarg rdshell || getarg rdbreak; then echo "Dropping to debug shell." echo sh -i else echo "Boot has failed, sleeping forever." while :; do sleep 365d;done fi } export PATH=/sbin:/bin:/usr/sbin:/usr/bin export TERM=linux NEWROOT="/sysroot" trap "emergency_shell Signal caught!" 0 . /lib/dracut-lib.sh mknod /dev/null c 1 3 # mount some important things mount -t proc /proc /proc >/dev/null 2>&1 mount -t sysfs /sys /sys >/dev/null 2>&1 if [ ! -c /dev/ptmx ]; then # try to mount devtmpfs if ! mount -t devtmpfs -omode=0755 udev /dev >/dev/null 2>&1; then # if it failed fall back to normal tmpfs mount -t tmpfs -omode=0755 udev /dev >/dev/null 2>&1 # Make some basic devices first, let udev handle the rest mknod /dev/null c 1 3 mknod /dev/ptmx c 5 2 mknod /dev/console c 5 1 mknod /dev/kmsg c 1 11 fi fi if getarg rdinitdebug; then set -x fi mkdir /dev/shm mkdir /dev/pts mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts >/dev/null 2>&1 UDEVVERSION=$(udevadm --version) source_conf /etc/conf.d # run scriptlets to parse the command line getarg 'rdbreak=cmdline' && emergency_shell "Break before cmdline" source_all cmdline [ -z "$root" ] && die "No or empty root= argument" [ -z "$rootok" ] && die "Don't know how to handle 'root=$root'" # Network root scripts may need updated root= options, # so deposit them where they can see them (udev purges the env) { echo "root='$root'" echo "rflags='$rflags'" echo "fstype='$fstype'" echo "netroot='$netroot'" echo "NEWROOT='$NEWROOT'" } > /tmp/root.info # pre-udev scripts run before udev starts, and are run only once. getarg 'rdbreak=pre-udev' && emergency_shell "Break before pre-udev" source_all pre-udev # start up udev and trigger cold plugs udevd --daemon UDEV_LOG_PRIO_ARG=--log-priority UDEV_QUEUE_EMPTY="udevadm settle --timeout=0" if [ $UDEVVERSION -lt 140 ]; then UDEV_LOG_PRIO_ARG=--log_priority UDEV_QUEUE_EMPTY="udevadm settle --timeout=1" fi getarg rdudevinfo && udevadm control $UDEV_LOG_PRIO_ARG=info getarg rdudevdebug && udevadm control $UDEV_LOG_PRIO_ARG=debug getarg 'rdbreak=pre-trigger' && emergency_shell "Break before pre-trigger" source_all pre-trigger # then the rest udevadm trigger $udevtriggeropts >/dev/null 2>&1 getarg 'rdbreak=initqueue' && emergency_shell "Break before initqueue" i=0 while :; do check_finished && break udevsettle check_finished && break if [ -f /initqueue/work ]; then rm /initqueue/work fi for job in /initqueue/*.sh; do [ -e "$job" ] || break job=$job . $job check_finished && break 2 done $UDEV_QUEUE_EMPTY >/dev/null 2>&1 || continue modprobe scsi_wait_scan && rmmod scsi_wait_scan $UDEV_QUEUE_EMPTY >/dev/null 2>&1 || continue for job in /initqueue-settled/*.sh; do [ -e "$job" ] || break job=$job . $job check_finished && break 2 done $UDEV_QUEUE_EMPTY >/dev/null 2>&1 || continue # no more udev jobs and queues empty. sleep 0.5 i=$(($i+1)) [ $i -gt 20 ] \ && { flock -s 9 ; emergency_shell "No root device found"; } 9>/.console_lock done unset job unset queuetriggered # pre-mount happens before we try to mount the root filesystem, # and happens once. getarg 'rdbreak=pre-mount' && emergency_shell "Break pre-mount" source_all pre-mount getarg 'rdbreak=mount' && emergency_shell "Break mount" # mount scripts actually try to mount the root filesystem, and may # be sourced any number of times. As soon as one suceeds, no more are sourced. i=0 while :; do [ -d "$NEWROOT/proc" ] && break; for f in /mount/*.sh; do [ -f "$f" ] && . "$f" [ -d "$NEWROOT/proc" ] && break; done i=$(($i+1)) [ $i -gt 20 ] \ && { flock -s 9 ; emergency_shell "Can't mount root filesystem"; } 9>/.console_lock done { echo -n "Mounted root filesystem " while read dev mp rest; do [ "$mp" = "$NEWROOT" ] && echo $dev; done < /proc/mounts } | vinfo getarg 'rdbreak=pre-pivot' && emergency_shell "Break pre-pivot" source_all pre-pivot # by the time we get here, the root filesystem should be mounted. # Try to find init. for i in "$(getarg init=)" /sbin/init /etc/init /init /bin/sh; do [ -f "$NEWROOT$i" -a -x "$NEWROOT$i" ] && { INIT="$i"; break; } done [ "$INIT" ] || { echo "Cannot find init!" echo "Please check to make sure you passed a valid root filesystem!" emergency_shell } getarg rdbreak && emergency_shell "Break before switch_root" HARD="" while pidof udevd >/dev/null 2>&1; do for pid in $(pidof udevd); do kill $HARD $pid >/dev/null 2>&1 done HARD="-9" done # Clean up the environment for i in $(export -p); do i=${i#declare -x} i=${i#export} i=${i%%=*} [ "$i" = "root" -o "$i" = "PATH" -o "$i" = "HOME" -o "$i" = "TERM" ] || unset $i done initargs="" if getarg init= >/dev/null ; then ignoreargs="console BOOT_IMAGE" # only pass arguments after init= to the init read CLINE </proc/cmdline CLINE=${CLINE#*init=} set $CLINE for x in "$@"; do for s in $ignoreargs; do [ "${x%%=*}" = $s ] && continue 2 done initargs="$initargs $x" done unset CLINE fi # Prepare network opts for passing if [ -e /tmp/net.ifaces ]; then mkdir /dev/.initramfs/ cp /tmp/net.* /dev/.initramfs/ >/dev/null 2>&1 mkdir -p /dev/.initramfs/state/etc/sysconfig/network-scripts/ cp /tmp/resolv.conf /dev/.initramfs/state/etc/ >/dev/null 2>&1 echo "files /etc/sysconfig/network-scripts" > /dev/.initramfs/rwtab cp -a /tmp/ifcfg/* /dev/.initramfs/state/etc/sysconfig/network-scripts/ >/dev/null 2>&1 fi # Debug: Copy state if getarg rdcopystate; then cp /tmp/* /dev/.initramfs/ >/dev/null 2>&1 fi info "Switching root" exec switch_root "$NEWROOT" "$INIT" $initargs || { echo "Something went very badly wrong in the initramfs. Please " echo "file a bug against dracut." emergency_shell }
Note the use of udev to discover devices, the use of /sysroot for mounting filesystems, and how breakpoints are handled. The purpose of the /sbin/switch_root executable is similar to the switchroot command in nash. Basically it changes the current directory to /, removes a lot of temporary subdirectories, chroots . and exec’s the init process.
Well, hopefully I have covered Dracut in sufficient detail to enable you to understand what has changed in Fedora 12 with respect to the boot process and building an initramfs file. The changes are significant and I expect that it will be a while before all the corner cases are found and fixed. If I have missed anything important regarding Dracut in this post, please add the information via a comment so that others can share in the knowledge.