Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Log stage-{1,2} output to secondary consoles #42255

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions nixos/modules/system/boot/stage-1-init.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#! @shell@

targetRoot=/mnt-root
console=tty1

extraUtils="@extraUtils@"
export LD_LIBRARY_PATH=@extraUtils@/lib
Expand All @@ -24,6 +23,15 @@ fail() {

@preFailCommands@

# Figure out a console device to use for the interactive shell.
# Plain /dev/console isn't good because terminal size queries don't work (useful for e.g. less).
# Same approach is taken by Debian's initramfs-tools and dracut.
console=$(cat /proc/consoles | head -n1 | cut -d' ' -f1)
if [ "$console" = tty0 ] || [ -z "$console" ]; then
# tty0 is a pseudo-console representing the current VT, replace that with a specific VT.
console=tty1
fi

# If starting stage 2 failed, allow the user to repair the problem
# in an interactive shell.
cat <<EOF
Expand Down Expand Up @@ -112,34 +120,34 @@ specialMount() {
}
source @earlyMountScript@

# Log the script output to /dev/kmsg or /run/log/stage-1-init.log.
mkdir -p /tmp
# Extract the list of secondary consoles from kernel. /sys/class/tty/console/active contains a list
# of all the active consoles, from which we filter out the primary console (the last one in the file).
# See https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-tty.
secondaryConsoles="$(cat /sys/class/tty/console/active | sed -e 's/[^ ]*$//')"

# Log the script output to either /dev/kmsg or /run/log/stage-1-init.log and to all secondary consoles.
mkdir -p /tmp /run/log
mkfifo /tmp/stage-1-init.log.fifo
logOutFd=8 && logErrFd=9
eval "exec $logOutFd>&1 $logErrFd>&2"
if test -w /dev/kmsg; then
tee -i < /tmp/stage-1-init.log.fifo /proc/self/fd/"$logOutFd" | while read -r line; do
if test -n "$line"; then
echo "<7>stage-1-init: $line" > /dev/kmsg
fi
done &
else
mkdir -p /run/log
tee -i < /tmp/stage-1-init.log.fifo /run/log/stage-1-init.log &
fi
tee -i < /tmp/stage-1-init.log.fifo /proc/self/fd/"$logOutFd" | while read -r line; do
if test -w /dev/kmsg; then
echo "<7>stage-1-init: $line" > /dev/kmsg
else
echo "$line" >> /run/log/stage-1-init.log
fi

for c in $secondaryConsoles; do
echo "$line" >> "/dev/$c"
done
done &
exec > /tmp/stage-1-init.log.fifo 2>&1


# Process the kernel command line.
export stage2Init=/init
for o in $(cat /proc/cmdline); do
case $o in
console=*)
set -- $(IFS==; echo $o)
params=$2
set -- $(IFS=,; echo $params)
console=$1
;;
init=*)
set -- $(IFS==; echo $o)
stage2Init=$2
Expand Down
35 changes: 23 additions & 12 deletions nixos/modules/system/boot/stage-2-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ ln -s /proc/mounts /etc/mtab
[ -e /proc/bus/usb ] && mount -t usbfs usbfs /proc/bus/usb # UML doesn't have USB by default
install -m 01777 -d /tmp
install -m 0755 -d /var/{log,lib,db} /nix/var /etc/nixos/ \
/run/lock /home /bin # for the /bin/sh symlink
/run/lock /run/log /home /bin # for the /bin/sh symlink


# Miscellaneous boot time cleanup.
Expand Down Expand Up @@ -110,19 +110,30 @@ if [ -n "@useHostResolvConf@" ] && [ -e /etc/resolv.conf ]; then
resolvconf -m 1000 -a host </etc/resolv.conf
fi

# Log the script output to /dev/kmsg or /run/log/stage-2-init.log.

# Extract the list of secondary consoles from kernel. /sys/class/tty/console/active contains a list
# of all the active consoles, from which we filter out the primary console (the last one in the file).
# See https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-tty.
# Except don't do this inside a container, as apparently at least LXC doesn't contain them from the host.
secondaryConsoles=""
if [ -z "$container" ]; then
secondaryConsoles="$(cat /sys/class/tty/console/active | sed -e 's/[^ ]*$//')"
fi

# Log the script output to /dev/kmsg or /run/log/stage-2-init.log and to all secondary consoles.
# Only at this point are all the necessary prerequisites ready for these commands.
exec {logOutFd}>&1 {logErrFd}>&2
if test -w /dev/kmsg; then
exec > >(tee -i /proc/self/fd/"$logOutFd" | while read -r line; do
if test -n "$line"; then
echo "<7>stage-2-init: $line" > /dev/kmsg
fi
done) 2>&1
else
mkdir -p /run/log
exec > >(tee -i /run/log/stage-2-init.log) 2>&1
fi
exec > >(tee -i /proc/self/fd/"$logOutFd" | while read -r line; do
if test -w /dev/kmsg; then
echo "<7>stage-2-init: $line" > /dev/kmsg
else
echo "$line" >> /run/log/stage-2-init.log
fi

for c in $secondaryConsoles; do
echo "$line" >> "/dev/$c"
done
done) 2>&1


# Run the script that performs all configuration activation that does
Expand Down
1 change: 1 addition & 0 deletions nixos/modules/system/boot/stage-2.nix
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ let
inherit (config.system.build) earlyMountScript;
path = lib.makeBinPath [
pkgs.coreutils
pkgs.gnused
pkgs.utillinux
pkgs.openresolv
];
Expand Down