View previous topic :: View next topic |
Author |
Message |
Goverp Advocate
Joined: 07 Mar 2007 Posts: 2176
|
Posted: Thu Jan 21, 2021 7:05 pm Post subject: depclean script to protect installed kernels |
|
|
The following script will scan a directory such as /boot for kernels of the name "vmlinuz*" and generate an "emerge --depclean --exclude ..." command to prevent depcleaning the sys-kernel/gentoo-sources package slots for any of those kernels. You can pass depclean parameters on the command line, such as "--ask" in the usual way.
It doesn't handle /boot directories that need mounting before use. It's not intended to be secure or idiot proof, so it's only safe if your system has only one administrator, and that's you. It needs modification if you use a different set of kernel sources such as tuxonice or similar.
Enjoy. (or criticise)
Code: | #!/bin/sh
### Run emerge --depclean, but excluding the source for any kernels in boot directory
### Note - this is neither secure nor idiot-proof.
### It should only be run in environments where nobody will be putting strange stuff in /boot,
### or calling this script with silly parameters while running as root.
### That said, the only dangerous command is emerge --depclean, and that's pretty limited.
# Configuration option - specify your kernel directory
DIRECTORY="/boot" # Might be /boot/efi or even /boot/efi/EFI
# Build a list of kernel versions to keep; the list contains the kernel version strings, like uname -v
keep=$(
file -L $DIRECTORY/vmlinuz* | grep -Eo 'version [0-9.]+.*-gentoo' | sort -uV | while read txt ver
do
printf '%s\n' "$ver"
done
)
# Depclean everything else.
# Note that command line parameters to this script (e.g. "--ask") get passed to the "emerge --depclean" command
for ver in $keep
do
excludes="$excludes --exclude sys-kernel/gentoo-sources:${ver%-gentoo} "
done
emerge --depclean $excludes $* |
_________________ Greybeard |
|
Back to top |
|
|
Zucca Moderator
Joined: 14 Jun 2007 Posts: 3687 Location: Rasi, Finland
|
Posted: Thu Jan 21, 2021 7:28 pm Post subject: |
|
|
I just emerge --noreplace <kernel_package>:<slot/version>
It should keep installed kernels away from depclean.
EDIT: Haven't ran the script yet, but looks like on the last line you should have "$@" (with the double quotes) instead of $*. Also arrays aren't supported in /bin/sh (the posix/dash ones), so maybe shebang should be #!/bin/bash?
EDIT02: Also the "keep" array can be used without the last loop creating the --exclude switches: emerge --exclude "${keep[*]}"
--exclude can take multiple package atoms separated with space, and thus the whole argument for --exclude needs to be quoted.
Note that I haven't tested this yet... Just my observations. ;) _________________ ..: Zucca :..
My gentoo installs: | init=/sbin/openrc-init
-systemd -logind -elogind seatd |
Quote: | I am NaN! I am a man! |
|
|
Back to top |
|
|
Goverp Advocate
Joined: 07 Mar 2007 Posts: 2176
|
Posted: Fri Jan 22, 2021 10:52 am Post subject: |
|
|
Thanks for feedback.
Zucca wrote: | ... Haven't ran the script yet, but looks like on the last line you should have "$@" (with the double quotes) instead of $*. Also arrays aren't supported in /bin/sh (the posix/dash ones), so maybe shebang should be #!/bin/bash? |
Nope, as far as I was concerned, I was writing (AND testing) it for dash. Arrays? we don't need no stinking arrays
Quote: | Also the "keep" array can be used without the last loop creating the --exclude switches: emerge --exclude "${keep[*]}"
--exclude can take multiple package atoms separated with space, and thus the whole argument for --exclude needs to be quoted.... |
I think I tried that version and ran into trouble with the extra quotes getting passed through to emerge; possibly one of those cases that needs eval, or maybe I'm misremembering; I'll give your version a spin.
Whatever, you need to put the "sys-kernel/gentoo-sources:" in front of each word of the "keep" string (for that's what it is). _________________ Greybeard |
|
Back to top |
|
|
Goverp Advocate
Joined: 07 Mar 2007 Posts: 2176
|
Posted: Fri Jan 22, 2021 12:16 pm Post subject: |
|
|
OK, here's the better version, one less loop (thanks Zucca). It's definitely OK for dash and it's ilk, no bashisms.
<edit> OOPS, forgot to check for errors such as unmounted /boot"</edit>
Code: | #!/bin/sh
### Run emerge --depclean, but excluding the source for any kernels in boot directory
### Note - this is neither secure nor idiot-proof.
### It should only be run in environments where nobody will be putting strange stuff in /boot,
### or calling this script with silly parameters while running as root.
### That said, the only command is emerge --depclean, and that's pretty limited.
# Configuration option - specify your kernel directory
DIRECTORY="/boot" # Might be /boot/efi or even /boot/efi/EFI
# Build a list of kernel versions to keep; the grep result filters the kernel version strings, like uname -r, from file's output for kernels
keep=$(
file -L $DIRECTORY/vmlinuz* | grep -Eo 'version [0-9.]+.*-gentoo' | sort -uV | while read -r _ ver
do
printf 'sys-kernel/gentoo-sources:%s ' "${ver%-gentoo}"
done
)
if [ -z "$keep" ]
then
printf "No kernels found in %s. Did you forget to mount a filesystem?\n" "$DIRECTORY"
exit 1
fi
emerge --depclean --exclude "$keep" "$@" |
_________________ Greybeard
Last edited by Goverp on Sat Jan 23, 2021 9:58 am; edited 1 time in total |
|
Back to top |
|
|
figueroa Advocate
Joined: 14 Aug 2005 Posts: 3005 Location: Edge of marsh USA
|
Posted: Sat Jan 23, 2021 4:35 am Post subject: |
|
|
I add the kernel versions I don't want depcleaned into /var/lib/portage/world. I keep two or more kernels on board, usually three or four. When I want a kernel source depcleaned, I remove it from world. I think this goes contrary to conventional wisdom, but it's what I do. I currently have:
Code: | $ grep sources /var/lib/portage/world
sys-kernel/gentoo-sources
sys-kernel/gentoo-sources:4.19.160
sys-kernel/gentoo-sources:4.9.240
sys-kernel/gentoo-sources:5.4.80-r1 |
Usually the three or four sources are from the same major family, but I've been in the process of moving up. _________________ Andy Figueroa
hp pavilion hpe h8-1260t/2AB5; spinning rust x3
i7-2600 @ 3.40GHz; 16 gb; Radeon HD 7570
amd64/23.0/split-usr/desktop (stable), OpenRC, -systemd -pulseaudio -uefi |
|
Back to top |
|
|
Goverp Advocate
Joined: 07 Mar 2007 Posts: 2176
|
Posted: Sat Jan 23, 2021 10:02 am Post subject: |
|
|
figueroa wrote: | I add the kernel versions I don't want depcleaned into /var/lib/portage/world. ... |
Understood. Depending on your bootmanager, that may be enough to decide which kernels come up. My script is so I only need to maintain the contents of /boot (or whatever). I have a glitzy script for that, a bit like eselect kernel, but with more features. When I have time, I'll put it on sourceforge or somewhere. _________________ Greybeard |
|
Back to top |
|
|
Zucca Moderator
Joined: 14 Jun 2007 Posts: 3687 Location: Rasi, Finland
|
Posted: Sat Jan 23, 2021 11:20 am Post subject: |
|
|
Oh. My neurons didn't fire propely as I have quite a bad flu (tested negative for COVID-19, yay).
I thought keep was an array, but the syntax was missing an extra (). :P
I find it amusing that the output of file isn't very easily machine parseable, except for the -print0 which appends NULL-character after each filename so that one can cut out filenames containing special characters. Well. It helps some...
So I started to test if there was a clean way to parse file output...
I ended up here Code: | $ find /boot/ -type f -name 'vmlinuz*' -exec file -L0 {} + | awk '{split($0,a,"\0"); if (a[2] ~ /^:[[:space:]]+Linux kernel/) {split(a[2],b,", version "); print substr(b[2],1,index(b[2]," ")) } }'
5.4.40
5.4.52
5.4.60
5.4.64
5.4.64-CEPTER_NY310-01_YS13G
5.4.64-CEPTER_NY310-01_YS13G
5.4.72-CEPTER_NY310-01_YS13G
5.4.83-CEPTER_NY310-01_YS13G
5.4.83-CEPTER_NY310-01_YS13G | ... and gave up that route. The awk part seems too complex (and should have an extra if -statement or a pipe to uniq).
To be able to extract version string from that output one may need to use qatom, because as an example right there I have extra string appended to the kernel version string. You cannot just rely to cut from first dash (-) as, for example, -r3 can be a part of version string... This may be impossible to make fully "waterproof". There's no fully reliable way to match a kernel binary file to a ebuild... afaik. Any kernel packagers here to comment? ;) _________________ ..: Zucca :..
My gentoo installs: | init=/sbin/openrc-init
-systemd -logind -elogind seatd |
Quote: | I am NaN! I am a man! |
|
|
Back to top |
|
|
Goverp Advocate
Joined: 07 Mar 2007 Posts: 2176
|
Posted: Sat Jan 23, 2021 11:31 am Post subject: |
|
|
I did a bit of digging on this myself, when I realized my UEFI laptop setup had three kernels - vmlinuz, vmlinuz.old and vmlinuz.new, and of course those filenames don't tell you the version. Various web things say there's a chain of offsets in the kernel file that will lead you to the release and version strings; I wasn't interested in chasing them down, so I wondered if any packages might have done the work for me. (Hence discovering "file" does. AFAIK, file makes no guarantees about it's output, so my script can stop working at any new release, but it definitely shows "version " followed by the "uname-r" release string. Since I'm only supporting gentoo-sources, the script can rely on -gentoo appearing in the release name. As an aside, you also get the version datestamp information "uname -v", so it's possible to tie the booted kernel to the file from which it was booted (assuming there are no duplicates). _________________ Greybeard |
|
Back to top |
|
|
Zucca Moderator
Joined: 14 Jun 2007 Posts: 3687 Location: Rasi, Finland
|
Posted: Sat Jan 23, 2021 11:46 am Post subject: |
|
|
Yeah. That works as long as one hasn't specified CONFIG_LOCALVERSION. _________________ ..: Zucca :..
My gentoo installs: | init=/sbin/openrc-init
-systemd -logind -elogind seatd |
Quote: | I am NaN! I am a man! |
|
|
Back to top |
|
|
Goverp Advocate
Joined: 07 Mar 2007 Posts: 2176
|
Posted: Sat Jan 23, 2021 3:09 pm Post subject: |
|
|
LOCALVERSION comes after the "-gentoo", so it works for me. _________________ Greybeard |
|
Back to top |
|
|
Zucca Moderator
Joined: 14 Jun 2007 Posts: 3687 Location: Rasi, Finland
|
Posted: Sat Jan 23, 2021 5:15 pm Post subject: |
|
|
Goverp wrote: | LOCALVERSION comes after the "-gentoo", so it works for me. | Ah. Then it's not a problem.
Since I use sys-kernel/gentoo-kernel (which is sort of a Fedora kernel) on my laptop I got different results while probing kernel images. _________________ ..: Zucca :..
My gentoo installs: | init=/sbin/openrc-init
-systemd -logind -elogind seatd |
Quote: | I am NaN! I am a man! |
|
|
Back to top |
|
|
figueroa Advocate
Joined: 14 Aug 2005 Posts: 3005 Location: Edge of marsh USA
|
Posted: Sat Jan 23, 2021 5:44 pm Post subject: |
|
|
Goverp wrote: | I did a bit of digging on this myself, when I realized my UEFI laptop setup had three kernels - vmlinuz, vmlinuz.old and vmlinuz.new, ... |
It would seem better to make vmlinuz~ to be symlinks to actual kernels with meaningful human-readable kernel filenames. _________________ Andy Figueroa
hp pavilion hpe h8-1260t/2AB5; spinning rust x3
i7-2600 @ 3.40GHz; 16 gb; Radeon HD 7570
amd64/23.0/split-usr/desktop (stable), OpenRC, -systemd -pulseaudio -uefi |
|
Back to top |
|
|
Goverp Advocate
Joined: 07 Mar 2007 Posts: 2176
|
Posted: Sun Jan 24, 2021 1:34 pm Post subject: |
|
|
figueroa wrote: | ... It would seem better to make vmlinuz~ to be symlinks to actual kernels with meaningful human-readable kernel filenames. |
Indeed, what I do on my desktop, which uses Grub to boot. But the laptop boots using the kernel EFI stub loader directly from UEFI. That means the kernel file has to (a) have a fixed name in the EFI boot variables and (b) be in the EFI partition, which generally has to be FATish. So no symlinks or meaningful names. _________________ Greybeard |
|
Back to top |
|
|
Ant P. Watchman
Joined: 18 Apr 2009 Posts: 6920
|
Posted: Sun Jan 24, 2021 1:50 pm Post subject: |
|
|
figueroa wrote: | Goverp wrote: | I did a bit of digging on this myself, when I realized my UEFI laptop setup had three kernels - vmlinuz, vmlinuz.old and vmlinuz.new, ... |
It would seem better to make vmlinuz~ to be symlinks to actual kernels with meaningful human-readable kernel filenames. |
That's one of the things you lose with this half-baked distro automation - the kernel makefile already does that for you automatically. |
|
Back to top |
|
|
|