Hatred's Log Place

DON'T PANIC!

Mar 19, 2023 - 2 minute read - Linux

ArchLinux: сохранение модулей текущего ядра при обновлении

Проблема: когда мы в ArchLinux и производных дистрибутивах обновляем ядро и если поменялась минорная цифра сменилась, то меняется и директория для модулей, а старая удаляется. В результате чего после обновления вы или сразу должны перезагрузиться с новым ядром или получать эпичные глюки: флешка там не примонтируется или ещё чего.

Очевидное решение: временно сохранить текущую диреторию для ядра. Почистить потом можно, на загрузке, к примеру.

Решение ниже - хуки для pacman, которое это делают.

Сами хуки, их два.

Первый, /etc/pacman/hooks/backup-current-kernel-modules-post.hook:

[Trigger]  
Type = Package  
Operation = Upgrade  
Target = linux[0-9]*  
  
[Action]  
Description = Kernel update detected. Restore current Kernel modules from backup  
Depends = rsync  
When = PostTransaction  
Exec = /home/hatred/bin/pacman-backup-current-kernel-modules post

Второй, /etc/pacman/hooks/backup-current-kernel-modules-pre.hook:

[Trigger]  
Type = Package  
Operation = Upgrade  
Target = linux[0-9]*  
  
[Action]  
Description = Kernel update detected. Backup current Kernel modules  
Depends = rsync  
When = PreTransaction  
Exec = /home/hatred/bin/pacman-backup-current-kernel-modules pre

Ну и сам скрипт, /home/hatred/bin/pacman-backup-current-kernel-modules:

#!/usr/bin/env bash  
  
# man pacman-hooks  
  
# TBD: detect suffix automatically  
suffix="-MANJARO"  
  
mods="/lib/modules"  
ver=$(uname -r)  
  
orig="$mods/$ver"  
backup="$mods/backup-$ver"  
  
# Useful for clean-up on startup  
flag=".htrd-backup-current-kernel-modules"  
  
# YES/NO, case is a matter  
#actual_clean="NO"  
  
backup()  
{  
   rsync -a $orig/ $backup  
   touch $backup/$flag  
}  
  
  
restore()  
{  
   rsync -a $backup/ $orig  
   depmod -aA  
}  
  
  
clean()  
{  
   local installed=($(pacman -Q | grep '^linux[0-9]\+ ' | awk '{print $2}'))  
   local old=$(ls /lib/modules/*/$flag | xargs -I{} dirname {} | xargs -I{} basename {})  
  
   for dir in $old  
   do  
       local ver_only=$(basename $dir $suffix)  
  
       if [[ ! " ${installed[*]} " =~ " ${ver_only} " ]]; then  
           echo "Directory flagged as backup and not found in installed, remove: $dir"  
           if [ "$actual_clean" = "YES" ]; then  
               true  
               #rm -rf "$mods/$dir"  
           fi  
       fi  
  
   done  
}  
  
  
case "$1" in  
   pre)  
       backup  
   ;;  
   post)  
       restore  
   ;;  
   clean)  
       clean  
   ;;  
esac  
  
exit 0

С параметром clean его вызвать можно на старте, например, из /etc/rc.local ( rc-local).