il faut verifier que les vol sous zroot/ROOT on le bon format de nom un 'mauvais' nom peut etre fait avec zfs boot menu
343 lines
8.6 KiB
Bash
Executable File
343 lines
8.6 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Time-stamp: <2025-02-16 07:42:28 nomad>
|
|
|
|
# Michel Le Cocq <lecocq@ipgp.fr>
|
|
# <nomad@neuronfarm.net>
|
|
|
|
# Licence Art Libre 1.3 (LAL 1.3)
|
|
|
|
# upsnapz.sh
|
|
|
|
# Script to upgrade your system install on zfs root with zfs boot menu (only Debian for the moment).
|
|
#
|
|
# refresh apt
|
|
# zfs snapshot
|
|
# apt upgrade
|
|
# apt autoremove
|
|
# zfs clone promote
|
|
# check zfs boot menu release
|
|
# check zfs pool status
|
|
|
|
# Depend :
|
|
# - gh
|
|
# - full sudo permission
|
|
|
|
# To do or not :
|
|
#
|
|
# ajouter zpool upgrade or not
|
|
# ajouter question cleanup zroot
|
|
#
|
|
# regarder si un nouveau kernel existe et si oui faire ce qu'il y a a faire
|
|
#
|
|
# verifier que les noms des zroot/ROOT/vol sont conformes au format attendu
|
|
|
|
function cleansnap
|
|
{
|
|
printf '\nClean snapshot.\n'
|
|
|
|
printf 'Current available bootfs:\n'
|
|
zfs list -o name,used,usedbysnapshots -r zroot/ROOT -s creation | grep -v '^zroot/ROOT .*'
|
|
oldest=$(zfs list -H -o name -r zroot/ROOT -s creation | grep -v '^zroot/ROOT$' | head -n 1)
|
|
oldestdate=$(echo $oldest | cut -d "_" -f 3- | tr '_' '-')
|
|
current=$(zpool get -H bootfs zroot -o value)
|
|
printf '\ncurrent bootfs: %s\n' $current
|
|
printf 'oldest bootfs: %s\n' $oldest
|
|
printf '\nzroot/ROOT status : \n'
|
|
zfs list -o used,available,quota,usedbychildren zroot/ROOT
|
|
|
|
printf '\nsnapshot to clean older than %s:\n' $oldestdate
|
|
zfs list -H -o name -t snapshot -s creation -r $current | grep $oldestdate -B10000 | grep -v $oldestdate
|
|
|
|
if [ $? -ne 1 ]
|
|
then
|
|
printf '\nDo snapshots cleanup ? : %s [Y-n]' $sugsname
|
|
read docleanup
|
|
if [ -z $dopromote ]
|
|
then
|
|
dopromote='y'
|
|
fi
|
|
|
|
if [[ "$dopromote" == "y" ]]
|
|
then
|
|
for z in $(zfs list -H -o name -t snapshot -s creation -r $current | grep $oldestdate -B10000 | grep -v $oldestdate)
|
|
do
|
|
printf 'zfs destroy %s\n' $z
|
|
sudo zfs destroy $z
|
|
done
|
|
fi
|
|
usedbysnapshots=$(zfs list -H -o usedbysnapshots $current)
|
|
printf '\nused by snapshot : %s\n' $usedbysnapshots
|
|
else
|
|
printf '\tno snapshot older than %s\n' $oldestdate
|
|
fi
|
|
}
|
|
|
|
function check_zpool_status
|
|
{
|
|
# check zpool status if it's upgradable
|
|
|
|
printf 'Check ZFS pool status:\n'
|
|
e=$(zpool status | grep action | grep 'zpool upgrade')
|
|
if [ $? -eq 0 ]
|
|
then
|
|
printf 'One or more ZFS pool can be upgraded\n'
|
|
zpool status
|
|
printf 'In case of ZFS Root be carefull that your bootloader is up to date and compatible with this new ZFS feature.\n'
|
|
else
|
|
printf 'every things ok for ZFS pool.\n'
|
|
fi
|
|
}
|
|
|
|
function check_ZFS_BOOT_MENU
|
|
{
|
|
# check last zfs boot menu release
|
|
# compare if we are on last release
|
|
|
|
# pas tout à fait satisfait de cette fonction !
|
|
|
|
printf '\nCheck ZFS_BOOT_MENU:\n'
|
|
PA="https://get.zfsbootmenu.org/sha256.txt"
|
|
echo " Hit:zfsbootmenu "$PA
|
|
curl -s -o /tmp/sha256.txt -L $PA
|
|
e=$(grep $(sha256sum /boot/efi/EFI/ZBM/VMLINUZ.EFI | awk '{print $1}') /tmp/sha256.txt | awk -F"[()]" '{print $2}' )
|
|
echo -n " Installed Release : "
|
|
e=$(echo $e | awk -F'-' '{print $4}')
|
|
if [ -z $e ]
|
|
then
|
|
echo " /!\ sha256sum of ZBM/VMLINUZ.EFI"
|
|
echo " not in sync with : "$PA
|
|
echo ' avaible release :'
|
|
cat /tmp/sha256.txt | grep EFI | grep release | awk -F"[()]" '{print $2}'
|
|
else
|
|
echo $e
|
|
# pas tout a fait satisfait de cette methode avec gh
|
|
# force a s'authentifier sur github !
|
|
dpkg -l gh &> /dev/null
|
|
if [ $? -eq 0 ]
|
|
then
|
|
# ici souci ! si non authentifié sur github ne "fonctionne pas"
|
|
f=$(gh release list --repo https://github.com/zbm-dev/zfsbootmenu | grep Latest | awk -F' ' '{print $4}')
|
|
if [ "$e" != "$f" ]
|
|
then
|
|
echo " /!\ Installed Release and lastest are not same !"$PA
|
|
printf ' Latest Release : '
|
|
echo $f
|
|
fi
|
|
fi
|
|
fi
|
|
rm /tmp/sha256.txt
|
|
}
|
|
|
|
function askpromote()
|
|
{
|
|
# ask if we wanted to promote that last snapshot
|
|
# promote last bootfs snapshot to a new bootfs env
|
|
# suggest name for new bootfs env
|
|
# clone promote activate new bootfs
|
|
# ask to reboot to new bootfs
|
|
|
|
snapname=$1
|
|
bootfs=$2
|
|
parents=$(zfs list -o name | grep $bootfs | awk 'BEGIN{FS=OFS="/"}{NF--; print}')
|
|
printf '\nclone and promote before upgrade %s or not \nhost will reboot to new bootfs : [Y-n]' $bootfs@$snapname
|
|
read dopromote
|
|
if [ -z $dopromote ]
|
|
then
|
|
dopromote='y'
|
|
echo y
|
|
fi
|
|
|
|
if [[ "$dopromote" == "y" ]]
|
|
then
|
|
printf '\nactual bootfs : %s\n' $bootfs
|
|
printf 'other bootfs :\n' $bootfs
|
|
zfs list -o name,creation -r $parents -s creation | grep -v ^$parents$
|
|
e=$(lsb_release -is)
|
|
f=$(date +%b)
|
|
sugsname="${e,,}_"$(lsb_release -cs)"_"$(date +%Y)"_"$(date +%m)"_"$(date +%d)
|
|
zfs list -H -o name | grep $sugsname
|
|
if [ $? -eq 0 ]
|
|
then
|
|
sugsname=$sugsname"_"$(date +%Y-%m-%d-%H%M%S)
|
|
fi
|
|
printf '\nname suggestion for new zpool bootfs : %s [Y-n]' $sugsname
|
|
|
|
read namepros
|
|
if [ -z $namepros ]
|
|
then
|
|
echo y
|
|
namepros='y'
|
|
fi
|
|
|
|
if [[ "$namepros" == "n" ]]
|
|
then
|
|
printf 'new bootfs name :'
|
|
read sugsname
|
|
if [ $(zfs list -H -o name | grep $sugsname) -eq 0 ]
|
|
then
|
|
sugsname=$newname_$(date +%Y-%m-%d-%H%M%S)
|
|
printf '%s already exist I siggest : %s\n'
|
|
fi
|
|
printf 'name suggestion : %s\n' $sugsname
|
|
fi
|
|
sudo zfs clone $bootfs@$snapname $parents/$sugsname
|
|
sudo zfs promote $parents/$sugsname
|
|
sudo zfs set -u mountpoint=/ $parents/$sugsname
|
|
sudo zfs set canmount=noauto $parents/$sugsname
|
|
sudo zpool set bootfs=$parents/$sugsname zroot
|
|
printf '%s will reboot to new bootfs %s in 5s\nHit Ctrl^c to abort' $(hostname) $sugsname
|
|
printf "\nRun again current script $(basename $0) after reboot.\n"
|
|
echo -n '.'; sleep 1; echo -n '.'; sleep 1; echo -n '.'; sleep 1; echo -n '.'; sleep 1; echo -n '.';sleep 1; echo -n '.';sleep 1; echo -n '.'
|
|
sudo reboot
|
|
else
|
|
echo no
|
|
fi
|
|
}
|
|
|
|
function askautoclean()
|
|
{
|
|
# ask to autoremove and zfs snapshot before
|
|
|
|
printf '\napt-get -s autoremove\n'
|
|
if [ $(apt-get -s autoremove | sed -n '/The following packages will be REMOVED:/,/^[0-9+] upgraded, [0-9+] newly installed, [0-9+] to remove and [0-9+] not upgraded.$/p' | wc -l) -gt 0 ]
|
|
then
|
|
apt-get -s autoremove | sed -n '/The following packages will be REMOVED:/,/^[0-9+] upgraded, [0-9+] newly installed, [0-9+] to remove and [0-9+] not upgraded.$/p'
|
|
printf '\n%s\n' 'Do we run an autoremove ? : [Y-n]'
|
|
read autoclean
|
|
if [ -z $autoclean ]
|
|
then
|
|
echo y
|
|
autoclean='y'
|
|
fi
|
|
|
|
if [[ "$autoclean" == "y" ]]
|
|
then
|
|
printf 'before autoremove : '
|
|
asksnap
|
|
sudo apt-get -y autoremove
|
|
else
|
|
echo
|
|
fi
|
|
fi
|
|
sudo apt autoclean
|
|
echo
|
|
}
|
|
|
|
function asksnap()
|
|
{
|
|
# print creation info of last bootfs snapshot
|
|
# ask if we want a snapshot of bootfs
|
|
# snapshot bootfs
|
|
|
|
bootfs=$(zpool get bootfs -o value -H zroot)
|
|
l=$(zfs list -H -t snapshot -o creation,name -S creation $(zpool get bootfs -o value -H zroot) | head -n1)
|
|
printf 'last snapshot : \n%s\n' "$l"
|
|
printf '%s <- now\n' "$(date '+%a %b %d %H:%M %Y')"
|
|
printf 'snapshot bootfs %s or not ? : [Y-n]' $bootfs
|
|
read dosnap
|
|
if [ -z $dosnap ]
|
|
then
|
|
echo y
|
|
dosnap='y'
|
|
fi
|
|
if [[ "$dosnap" == "y" ]]
|
|
then
|
|
snapname=$(date +%Y-%m-%d-%H%M%S)
|
|
sudo zfs snapshot $bootfs@$snapname
|
|
zfs list -H -o name $bootfs@$snapname
|
|
askpromote $snapname $bootfs
|
|
else
|
|
echo no
|
|
fi
|
|
}
|
|
|
|
function snapchange
|
|
{
|
|
# check/show snap change/refresh
|
|
|
|
dpkg -l snapd &> /dev/null
|
|
if [ $? -eq 0 ]
|
|
then
|
|
printf '%s\n' 'snap refresh && snap changes'
|
|
sudo snap refresh
|
|
snap changes
|
|
fi
|
|
}
|
|
|
|
function askupgrade()
|
|
{
|
|
# run apt update
|
|
# if there were upgrade ask for upgrade or not
|
|
# ask for making a snapshot
|
|
# run apt upgrade
|
|
# else
|
|
# ask for making a snapshot
|
|
|
|
printf '%s\n' 'apt update'
|
|
sudo apt update
|
|
if [ $(apt list --upgradable 2>/dev/null | wc -l) -gt 1 ]
|
|
then
|
|
printf '\n%s\n' 'apt list --upgradable'
|
|
apt list --upgradable
|
|
|
|
printf '\nUpgrade or not : [Y-n]'
|
|
read answer
|
|
|
|
if [ -z $answer ]
|
|
then
|
|
echo y
|
|
answer='y'
|
|
fi
|
|
|
|
if [[ "$answer" == "y" ]]
|
|
then
|
|
printf 'before upgrade : '
|
|
asksnap
|
|
printf '%s\n' 'apt -y upgrade'
|
|
sudo apt -y upgrade
|
|
else
|
|
echo no
|
|
fi
|
|
else
|
|
echo
|
|
asksnap
|
|
fi
|
|
}
|
|
|
|
function usage()
|
|
{
|
|
echo "Usage: $(basename $0) [-h]"
|
|
echo "-b : only check zfs boot menu"
|
|
}
|
|
|
|
while getopts 'hb' OPTION; do
|
|
case "$OPTION" in
|
|
h)
|
|
usage
|
|
exit 1
|
|
;;
|
|
b)
|
|
check_ZFS_BOOT_MENU
|
|
echo
|
|
exit 1
|
|
;;
|
|
?)
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
askupgrade
|
|
askautoclean
|
|
snapchange
|
|
echo
|
|
check_zpool_status
|
|
check_ZFS_BOOT_MENU
|
|
echo
|
|
zpool status
|
|
cleansnap
|
|
printf '\nNothing else to do.\n'
|
|
|