Is this command to remove old kernels safe to use?
I'd say: don't use it in the current form
It makes changes without asking you. The
apt-get -y purge
part allows the one-liner to start executing purging packages, without your confirmation. If any error in the script exists, then you could be screwed.No source, no author given. The source of it makes a difference here. In case it would come from a thoroughly tested system package we can trace the testing being done onto it. From a random source, we can't trust it.
dpkg -l
runs fine withoutsudo
. I don't see why the original author thought this was necessary.
Use common sense
Remove the harmful parts and leave out anything that runs as root.
For example, cut it down to this:
dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d'
which just only outputs stuff and runs with regular user permissions. Once you agree with these kernels to be removed, you can append | xargs sudo apt-get purge
yourself. It's without the -y
option, intentionally, so you'll be asked for confirmation on the changes about to be made to your system.
Explanation
dpkg -l
Outputs the list of all packages. In this case it will only list packages starting withlinux-
as the name.|
(a pipe) pipes the output of the command on the left (we call thatstdout
) to the input of the command on the right (we call thatstdin
).sed
is a tool to manipulate strings using regular expressions. In this case it manipulates the output of the command on the left of the pipe and filters for installed packages (relying on theii
as given bydpkg
). It is even being nested in this case. It would be too hard to explain the whole use ofsed
here, as its use is very complicated with the complex regular expressions. (the\(.*\)-\([^0-9]\+\)"
is an example of a regular expression.- Regular expressions are very widely used to find matches based on the expression they represent.
\1
is the replacement reference to do a sort of universal search-and-replace (referencing to the first 'hit' with1
). The regular expression themselves can't do any harm. However, if they manipulate the input in a wrong way, they can have you remove the wrong packages or even do shell injection. In this case it looks like a way to find the name of the kernel package based on the version provided byuname -r
. uname -r
outputs the current version of the kernel running.xargs
appends the lines of the input left of the pipe as arguments to the command. In this case, the kernel versions on each line are converted to a horizontal space-separated list and appended to thesudo apt-get
command.sudo apt-get -y purge [packagename]
purges (removes everything) of the packages given (as arguments).
Alternatives
Quite some question are probably already asked about this. Relevant ones I found so far:
- How to "clean" previous kernels after update?
- How do I remove old kernel versions to clean up the boot menu?
From this answer, the following command seems to do the same in a much safer and more common way:
sudo apt-get purge $( dpkg --list | grep -P -o "linux-image-\d\S+" | grep -v $(uname -r | grep -P -o ".+\d") )
You asked for a step-by-step explanation so here goes:
sudo dpkg -l 'linux-*'
Lists packages starting with linux-
in the package name
| sed
and pipe the list into sed
"s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d'
which will use a very complicated regular expression to edit the list
| xargs
which will pipe the new list into xargs
, which will send it as an argument to
sudo apt-get -y purge
which will purge those packages without giving you a chance to change your mind.
Or perhaps it's more accurate to say it will send that list into the purge command and leave it at that. Whether or not anything is purged — and importantly — exactly what is purged depends on the ouput of the previous commands.
Is it safe? In this case that all depends on how well the author of the post where you found it understands regular expressions and sed
syntax. And there are whole books on both of those topics.
I started by dissecting the commands, reading the man
page for each.
dpkg -l
: list pacakges, sodpkg -l linux-*
would list all packages that started withlinux-
(usually kernels).sed
: The output ofdpkg -l linux-*
is piped tosed
with several regular expressions whichsed
decodes.uname -r
uname
prints system information
uname - print system information
The -r
handle specifically prints kernel releases:
-r, --kernel-release print the kernel release
The output of uname -r
is then piped to sed
with more regular expressions, the output of which is passed to xargs
So xargs
translates the sed
output into package names and passes them onto sudo apt-get purge -y
which automatically answers 'yes' to all prompts:
-y, --yes, --assume-yes Automatic yes to prompts; assume "yes" as answer to all prompts and run non-interactively. If an undesirable situation, such as changing a held package, trying to install a unauthenticated package or removing an essential package occurs then apt-get will abort. Configuration Item: APT::Get::Assume-Yes.
Altogether it seems this command will do what you want, though to know for sure we'd have to translate sed
's regular expressions.
I just ran:
dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d'
here is a screenshot:
All old kernel versions iirc.