13

I want to use kexec to speed up reboots of my CentOS 7 machine. How can I do that in a way that nicely integrates with existing shutdown/reboot systemd targets? What's the proper (official) way to do this?

11

I figured out a way to make a kexec loading script that works well and will load the default kernel in grub, meaning it should load the new kernel after a kernel update.

File: /usr/bin/kexec-load

#!/usr/bin/env bash

GRUBBY_FILE="/var/log/grubby"
TMP=$(mktemp)

#  Command "grubby --default-kernel" has a bug/feature that fsyncs
#  after writting each line to a debug log file, making it slow (several seconds).
#  Workaround is to write to /dev/null instead.
if [ -e $GRUBBY_FILE ]
        then rm -f $GRUBBY_FILE
fi
ln -s /dev/null $GRUBBY_FILE
KERNEL_IMG=$(grubby --default-kernel)
unlink $GRUBBY_FILE

#  Get the detailed information of the default kernel (as seen by grub)
#  This will create a temporary file in /tmp
grubby --info=$KERNEL_IMG | grep -v title > $TMP
source $TMP
rm $TMP

#  Simple log to see if this script gets executed
date --rfc-3339=seconds >> /var/log/kexec

#  Load (prepare) the kernel for execution
kexec -l $kernel --initrd=$initrd --command-line="root=$root $args"

File: /etc/systemd/system/kexec-load.service

[Unit]
Description=loads the kernel
Documentation=man:kexec(8)
DefaultDependencies=no
Before=shutdown.target umount.target final.target

[Service]
Type=oneshot
ExecStart=/usr/bin/kexec-load

[Install]
WantedBy=kexec.target 

$ chmod +x /usr/bin/kexec-load
$ systemctl enable kexec-load.service
$ systemctl kexec
  • 1
    Marvellous, I don't quite understand why this haven't got 289 upvotes yet... – kubanczyk Oct 28 '16 at 8:34
  • 3
    To keep it simple, I get rid of script file and I use instead ExecStart=/bin/sh -c "kexec -l $$(grubby --default-kernel) --initrd=$$(grubby --default-kernel | sed 's!vmlinuz!initramfs!;s/$/.img/') --reuse-cmdline" – kubanczyk Oct 28 '16 at 9:23
7

This is pretty straightforward.

First stage the kernel to be booted:

kexec -l /boot/vmlinuz-3.10.0-123.6.3.el7.x86_64 \
--initrd=/boot/initramfs-3.10.0-123.6.3.el7.x86_64.img \
--command-line="root=/dev/mapper/centos-root ro rd.lvm.lv=centos/swap vconsole.font=latarcyrheb-sun16 rd.lvm.lv=centos/root crashkernel=auto  vconsole.keymap=us rhgb quiet LANG=en_US.UTF-8"

These options having been swiped out of the generated grub configuration.

Now tell systemd to do its magic.

systemctl start kexec.target

Or on more recent versions of systemd:

systemctl kexec

A few seconds later, you will be up in your new kernel.


I've recently written a distribution-agnostic script to help automate this (bug reports welcome).

  • And, if you're bored, watch a video of the kexec reboot process that I took while preparing this answer. – Michael Hampton Aug 13 '14 at 18:27
  • Wouldn't --command-line=$(cat /proc/cmdline) work as well? – Dennis Kaarsemaker Aug 13 '14 at 18:35
  • 1
    @DennisKaarsemaker Yeah, probably so. But changing the command line options might be one of the things being done, so I wouldn't necessarily always do that. – Michael Hampton Aug 13 '14 at 18:37
  • Thank you for the answer. Is there a way to automate the "kexec preparation"? Can systemd be configured to automatically prepare kexec when I exectute "systemctl start kexec.target"? – Matrix Aug 13 '14 at 19:36
  • @Matrix Good question. If there is such a way, I'm not aware of it. And anyway, rebooting is something you generally want to think about. – Michael Hampton Aug 13 '14 at 19:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.