Difference between revisions of "Kexec"
(From systemd > v236 the command 'systemctl kexec' requires systemd-boot) |
(update behavior of systemctl kexec) |
||
Line 26: | Line 26: | ||
# kexec -l /boot/vmlinuz-linux --initrd=/boot/initramfs-linux.img --reuse-cmdline | # kexec -l /boot/vmlinuz-linux --initrd=/boot/initramfs-linux.img --reuse-cmdline | ||
# systemctl kexec | # systemctl kexec | ||
+ | |||
=== Systemd === | === Systemd === | ||
− | + | By default, if [[Systemd-boot]] is used and no kernel was loaded manually using {{ic|kexec -l}} before, systemd will load the kernel specified in the default boot loader entry. For example, to reboot into the newer kernel after a system update, you may simply run: | |
+ | |||
+ | # systemctl kexec | ||
+ | |||
+ | The command will refuse to execute if you have several initrd entries (currently not supported). A common use of several initrd entries is [[Microcode|early microcode updates]]. | ||
+ | |||
+ | ==== Custom unit file ==== | ||
+ | |||
+ | If the default behavior does not work for you or you desire to conveniently load custom kernels, you may wrap the kernel loading into a service unit. Create a new unit file, {{ic|kexec-load@.service}}, that will load the specified kernel to be kexec'ed: | ||
{{hc|/etc/systemd/system/kexec-load@.service|2= | {{hc|/etc/systemd/system/kexec-load@.service|2= |
Revision as of 13:45, 12 October 2018
Kexec is a system call that enables you to load and boot into another kernel from the currently running kernel. This is useful for kernel developers or other people who need to reboot very quickly without waiting for the whole BIOS boot process to finish. Note that kexec may not work correctly for you due to devices not fully re-initializing when using this method, however this is rarely the case.
Contents
Installation
Install the kexec-tools package.
Rebooting using kexec
Manually
You can manually invoke kexec using:
# kexec -l /boot/vmlinuz-linux --initrd=/boot/initramfs-linux.img --reuse-cmdline # kexec -e
kexec -e
directly will not unmount active filesystems or terminate any running services gracefully.It is also possible to load kernel manually and then let systemd handle service shutdown and kexec for you. This, however, requires the bootloader to be Systemd-boot.
# kexec -l /boot/vmlinuz-linux --initrd=/boot/initramfs-linux.img --reuse-cmdline # systemctl kexec
Systemd
By default, if Systemd-boot is used and no kernel was loaded manually using kexec -l
before, systemd will load the kernel specified in the default boot loader entry. For example, to reboot into the newer kernel after a system update, you may simply run:
# systemctl kexec
The command will refuse to execute if you have several initrd entries (currently not supported). A common use of several initrd entries is early microcode updates.
Custom unit file
If the default behavior does not work for you or you desire to conveniently load custom kernels, you may wrap the kernel loading into a service unit. Create a new unit file, kexec-load@.service
, that will load the specified kernel to be kexec'ed:
/etc/systemd/system/kexec-load@.service
[Unit] Description=load %i kernel into the current kernel Documentation=man:kexec(8) DefaultDependencies=no Before=shutdown.target umount.target final.target [Service] Type=oneshot ExecStart=/usr/bin/kexec -l /boot/vmlinuz-%i --initrd=/boot/initramfs-%i.img --reuse-cmdline [Install] WantedBy=kexec.target
Then enable the service file for the kernel you want to load, for example simply the default kernel linux
:
# systemctl enable kexec-load@linux
ln -s '/etc/systemd/system/kexec-load@.service' '/etc/systemd/system/kexec.target.wants/kexec-load@linux.service'
Ensure that the shutdown hook is not part of your initramfs image by removing it from the HOOKS
array in /etc/mkinitcpio.conf
. If it is, remove it and rebuild your initrd image with mkinitcpio -p linux
.
Then to kexec
# systemctl kexec
If you wish to load a different kernel for the next kexec, for example linux-lts
, disable the service for the current kernel and enable the one for the new kernel:
# systemctl disable kexec-load@linux # systemctl enable kexec-load@linux-lts
Separate /boot partition
The above systemd unit file will fail if /boot is not on the root file system, as systemd will likely unmount /boot before it runs the kexec-load unit file. An alternative approach is to load a "hook" unit file that does nothing on startup and invokes kexec upon termination. By making this unit file conflict with kexec.target and only kexec.target, you can ensure the new kernel gets loaded early enough and only after a "systemctl kexec" command. Here is an alternate /etc/systemd/system/kexec-load@.service
file that follows this strategy:
[Unit] Description=hook to load vmlinuz-%i kernel upon kexec Documentation=man:kexec(8) DefaultDependencies=no Requires=sysinit.target After=sysinit.target [Service] Type=oneshot ExecStart=-/usr/bin/true RemainAfterExit=yes ExecStop=/usr/bin/kexec -l /boot/vmlinuz-%i --initrd=/boot/initramfs-%i.img --reuse-cmdline [Install] WantedBy=basic.target
Note that Conflicts=shutdown.target is not really needed, as it's implicitly guaranteed by strict ordering on systinit.target which itself Conflicts= with shutdown.target.