Bash one-liner 仅删除旧内核

Ale*_*dro 25 bash kernel boot-partition

我已经看到很多关于如何在 /boot 分区上释放空间的主题,这也是我的目标。但是,我只对删除内核感兴趣,而不是删除每个内核,而是删除当前内核。

我需要解决方案是单行的,因为我将从 Puppet 运行脚本并且我不想有额外的文件。到目前为止,我得到了以下信息:

dpkg -l linux-* | awk '/^ii/{print $2}' | egrep [0-9] | sort -t- -k3,4 --version-sort -r | sed -e "1,/$(uname -r | cut -f1,2 -d"-")/d" | grep -v -e `uname -r | cut -f1,2 -d"-"` | xargs sudo apt-get -y purge
Run Code Online (Sandbox Code Playgroud)

更准确地说,它目前的作用如下:

  • 列出所有 linux-* 包并打印它们的名称。
  • 只列出有数字的那些并对其进行排序,返回相反的结果。这样,较旧的内核会列在最后。
  • 仅打印当前内核之后的结果
  • 由于有一些 linux-{image,headers} 结果,请确保我不会清除与当前内核相关的任何内容
  • 呼叫易于清除

这行得通,但我确信该解决方案可以更优雅,并且对于生产环境来说是安全的,因为我们至少有 20 台服务器运行 Ubuntu。

谢谢你的时间,亚历杭德罗。

Mal*_*ppa 25

挺好看的,简单评论几句。前两个注释使命令更安全,而第三个和第四个注释使其更短。随意关注或忽略其中任何一个。虽然我强烈建议遵循前两个。您想确保它尽可能安全。我的意思是认真的。您正在向sudo apt-get -y purge一些自动生成的包列表抛出一个。那太邪恶了!:)

  1. 列出所有内容linux-*会给您带来许多误报,例如 (example from my output) linux-sound-base。尽管这些可能会被您的其他命令稍后过滤掉,但我个人觉得不首先列出它们会更安全。更好地控制要删除的包。不要做可能会产生意外结果的事情。所以我会开始

    dpkg -l linux-{image,headers}-*
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在我看来,你的正则表达式“只列出有数字的”有点太简单了。例如,linux-libc-dev:amd64当您在 64 位系统上时有该包。您的正则表达式将匹配。你不希望它匹配。诚然,如果您遵循我的第一个建议,那么linux-libc-dev:amd64无论如何都不会被列出,但仍然如此。我们对版本号结构的了解比“有一个数字”这样的简单事实要多。此外,引用正则表达式通常是个好主意,只是为了防止 shell 潜在的误解。所以我会做那个 egrep 命令

     egrep '[0-9]+\.[0-9]+\.[0-9]+'
    
    Run Code Online (Sandbox Code Playgroud)
  3. 然后是这个排序的事情。你为什么排序?既然您无论如何都将删除所有内核(当前内核除外),那么在新内核之前删除旧内核是否重要?我不认为这有什么区别。或者你只是这样做,所以你可以sed用来“只打印当前内核之后的结果”?但 IMO 这感觉太复杂了。为什么不简单地过滤掉与您当前内核相对应的结果,就像您已经在做grep -v的那样,然后完成?老实说,如果我接受你命令的第一部分(结合我之前的两个建议),在我的机器上我得到

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | sort -t- -k3,4 --version-sort -r | sed -e "1,/$(uname -r | cut -f1,2 -d"-")/d" | grep -v -e `uname -r | cut -f1,2 -d"-"`
    linux-image-3.8.0-34-generic
    linux-image-3.5.0-44-generic
    
    Run Code Online (Sandbox Code Playgroud)

    删除排序/ sed 的东西,我得到

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | grep -v -e `uname -r | cut -f1,2 -d"-"`
    linux-image-3.5.0-44-generic
    linux-image-3.8.0-34-generic
    linux-image-extra-3.5.0-44-generic
    linux-image-extra-3.8.0-34-generic
    
    Run Code Online (Sandbox Code Playgroud)

    所以你更复杂的命令实际上会错过我机器上的两个包,我想删除(现在这些linux-image-extra-*东西可能依赖于linux-image-*thingys,因此无论如何都会被删除,但明确表示不会有什么坏处)。无论如何,我看不出你分类的意义;一个简单的grep -v没有花哨的预处理应该没问题,大概更好。我是 KISS 原则的支持者。这将使您以后更容易理解或调试。此外,如果没有排序,它的效率会更高一些;)

  4. 这纯粹是出于美学考虑,但使用这个稍短的变体,您将获得相同的输出。:-)

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | grep -v $(uname -r | cut -d- -f-2)
    linux-image-3.5.0-44-generic
    linux-image-3.8.0-34-generic
    linux-image-extra-3.5.0-44-generic
    linux-image-extra-3.8.0-34-generic
    
    Run Code Online (Sandbox Code Playgroud)

因此,我最终得到了更简单、更安全的命令

$ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | grep -v $(uname -r | cut -d- -f-2) | xargs sudo apt-get -y purge
Run Code Online (Sandbox Code Playgroud)

由于您实际上想要清理/boot分区,因此完全不同的方法是列出 的内容/boot,用于dpkg -S确定各个文件所属的包,过滤掉属于当前内核的包,并删除生成的包。但我更喜欢你的方法,因为它还会找到过时的软件包,例如linux-headers-*,它们没有安装到/boot,而是安装到/usr/src.


jar*_*rno 9

我编写了这个脚本来删除版本低于当前启动的版本的“linux-*”包。我认为没有必要测试包状态。该命令在清除包之前要求确认。如果您不想这样做,请在 apt-get 命令中添加 -y 选项。

sudo apt-get purge $(dpkg-query -W -f'${Package}\n' 'linux-*' |
sed -nr 's/.*-([0-9]+(\.[0-9]+){2}-[^-]+).*/\1 &/p' | linux-version sort | 
awk '($1==c){exit} {print $2}' c=$(uname -r | cut -f1,2 -d-))
Run Code Online (Sandbox Code Playgroud)

但是,为了能够留下可配置数量的备用内核,我建议使用linux-purge带有--keep选项的脚本。有关脚本的更多信息,请参见此处