This introduces support for the rd.log and rd.debug kernel command line
options, which log early userspace activity to /run/initramfs/init.log.
Code is largely inspired by Dracut's implementation of early userspace
logging, but without needless complexity and redundancies.
Signed-off-by: Dave Reisner
---
init | 5 ++
init_functions | 147 +++++++++++++++++++++++++++++++++++++++++++++------
install/base | 2 +-
man/mkinitcpio.8.txt | 25 +++++++++
4 files changed, 162 insertions(+), 17 deletions(-)
diff --git a/init b/init
index dfebd53..7859aa3 100644
--- a/init
+++ b/init
@@ -19,6 +19,9 @@ mkdir -m755 /run/initramfs
# parse the kernel command line
parse_cmdline /run/initramfs/root-fsck
- elif fsck_ret 4; then
+ elif bitfield_has_bit $fsckret 4; then
err "Bailing out. Run 'fsck $root' manually"
printf '%s\n' \
"********** FILESYSTEM CHECK FAILED **********" \
@@ -163,7 +208,7 @@ fsck_root() {
echo ":: Automatic reboot in progress"
sleep 2
reboot -f
- elif fsck_ret 2; then
+ elif bitfield_has_bit $fsckret 2; then
printf '%s\n' \
"************** REBOOT REQUIRED **************" \
"* *" \
@@ -172,13 +217,13 @@ fsck_root() {
"*********************************************"
sleep 10
reboot -f
- elif fsck_ret 8; then
+ elif bitfield_has_bit $fsckret 8; then
err "fsck failed on '$root'"
- elif fsck_ret 16; then
+ elif bitfield_has_bit $fsckret 16; then
err "Failed to invoke fsck: usage or syntax error"
- elif fsck_ret 32; then
+ elif bitfield_has_bit $fsckret 32; then
echo ":: fsck cancelled on user request"
- elif fsck_ret 128; then
+ elif bitfield_has_bit $fsckret 128; then
err "fatal error invoking fsck"
fi
fi
@@ -254,4 +299,74 @@ default_mount_handler() {
fi
}
+rdlogger_start() {
+ [ -n "$rd_log" ] || return
+ mkfifo /run/initramfs/rdlogger.pipe
+ rdlogger /dev/console 2>&1 &
+ exec >/run/initramfs/rdlogger.pipe 2>&1
+ [ -n "$rd_debug" ] && set -x
+}
+
+rdlogger_stop() {
+ local i=0
+
+ [ -e /run/initramfs/rdlogger.pipe ] || return
+
+ [ -n "$rd_debug" ] && { set +x; } 2>/dev/null
+
+ # signal logger to exit by redirecting FDs back to /dev/console
+ exec 0<>/dev/console 1<>/dev/console 2<>/dev/console
+
+ # wait up to 1 second for rdlogger to exit gracefully
+ while [ -e /run/initramfs/rdlogger.pipe ] && [ $i -lt 10 ]; do
+ sleep 0.1
+ i=$(( i + 1 ))
+ done
+
+ [ $i -eq 10 ] && kill %1 2>/dev/null
+}
+
+rdlogger() {
+ local line
+
+ # always cleanup on exit
+ trap 'rm -f /run/initramfs/rdlogger.pipe' EXIT
+
+ # establish log targets. Either redirect to an appropriate file descriptor,
+ # or to /dev/null. This way, logging can Just Happen and the attached FD
+ # will Do The Right Thing™.
+
+ # rd.log=kmsg
+ if [ -c /dev/kmsg ] && bitfield_has_bit "$rd_log" "$_rdlog_kmsg"; then
+ exec 5>/dev/kmsg
+ else
+ exec 5>/dev/null
+ fi
+
+ # rd.log=file
+ if bitfield_has_bit "$rd_log" "$_rdlog_file"; then
+ exec 6>/run/initramfs/init.log
+ else
+ exec 6>/dev/null
+ fi
+
+ # rd.log=console
+ if ! bitfield_has_bit "$rd_log" "$_rdlog_cons" || [ -n "$quiet" ]; then
+ exec >/dev/null
+ fi
+
+ while read -r line; do
+ # rd.log=kmsg
+ printf '<31>initramfs: %s\n' "$line" >&5
+
+ # rd.log=file
+ printf '%s\n' "$line" >&6
+
+ # rd.log=console
+ printf '%s\n' "$line"
+ done
+
+ # EOF, shutting down...
+}
+
# vim: set ft=sh ts=4 sw=4 et:
diff --git a/install/base b/install/base
index ad0e5f2..397168f 100644
--- a/install/base
+++ b/install/base
@@ -3,7 +3,7 @@
build() {
local applet
- add_binary /usr/lib/initcpio/busybox /bin/busybox
+ add_binary /usr/lib/initcpio/busybox /usr/bin/busybox
for applet in $(/usr/lib/initcpio/busybox --list); do
add_symlink "/usr/bin/$applet" busybox
diff --git a/man/mkinitcpio.8.txt b/man/mkinitcpio.8.txt
index 56ac571..4f2db59 100644
--- a/man/mkinitcpio.8.txt
+++ b/man/mkinitcpio.8.txt
@@ -248,6 +248,31 @@ the kernel command line:
device to show up, if it is not available immediately. This defaults to 5
seconds. If an invalid integer is passed, this variable will have no effect.
+*rd.debug*::
+ Enables shell debug (xtrace). This option is only useful in combination with
+ the 'rd.log' option.
+
+*rd.log*['=']::
+ Enables logging of early userspace messages. If specified, the optional
+ parameter describes where this information is logged. Multiple options can be
+ OR'd together using the pipe (|) character. Messages are always logged
+ to the console unless the 'quiet' parameter is passed.
+
+ *console*;;
+ Writes log output to '/dev/console'.
+
+ *file*;;
+ Writes log output to '/run/initramfs/init.log'
+
+ *kmsg*;;
+ Writes output to the kernel ring buffer using the '/dev/kmsg' device
+ (introduced in Linux 3.5). This option is a no-op if your kernel does
+ not support this device.
+
+ *all*;;
+ Writes output to all known log targets. This is the default if no option
+ is specified.
+
These are only the variables that the core of mkinitcpio honor. Additional
hooks may look for other environment variables and should be documented by the
help output for the hook.
--
1.8.3.1