由于/boot分区磁盘空间不足,无法升级。

我尝试执行do-release-upgrade,但是出现以下错误信息:

磁盘空间不足

升级已中止。升级需要在磁盘'/boot'上至少25.7 M的可用空间。请释放至少额外的25.7 M磁盘空间在'/boot'上。清空垃圾箱并使用'sudo apt-get clean'命令删除以前安装的临时软件包。

df命令的输出结果为:
                    237251272 214797108  10402504  96% /
udev                    488120         4    488116   1% /dev
tmpfs                   198676       668    198008   1% /run
none                      5120         0      5120   0% /run/lock
none                    496684         0    496684   0% /run/shm
/dev/sda1               233191    225867         0 100% /boot

怎么会启动盘上没有剩余空间了?这是 ls -as /boot 的输出结果:
total 221839
    4 .
    4 ..
  645 abi-2.6.32-34-generic-pae
  698 abi-2.6.35-30-generic-pae
  727 abi-2.6.38-12-generic-pae
  727 abi-3.0.0-12-generic-pae
  727 abi-3.0.0-13-generic-pae
  727 abi-3.0.0-14-generic-pae
  727 abi-3.0.0-15-generic-pae
  727 abi-3.0.0-16-generic-pae
  727 abi-3.0.0-17-generic-pae
  727 abi-3.0.0-19-generic-pae
  761 abi-3.0.0-20-generic-pae
  115 config-2.6.32-34-generic-pae
  128 config-2.6.35-30-generic-pae
  136 config-2.6.38-12-generic-pae
  140 config-3.0.0-12-generic-pae
  140 config-3.0.0-13-generic-pae
  140 config-3.0.0-14-generic-pae
  140 config-3.0.0-15-generic-pae
  140 config-3.0.0-16-generic-pae
  140 config-3.0.0-17-generic-pae
  140 config-3.0.0-19-generic-pae
  140 config-3.0.0-20-generic-pae
    5 grub
10773 initrd.img-2.6.32-34-generic-pae
13619 initrd.img-2.6.35-30-generic-pae
15365 initrd.img-2.6.38-12-generic-pae
16481 initrd.img-3.0.0-12-generic-pae
16487 initrd.img-3.0.0-13-generic-pae
16501 initrd.img-3.0.0-14-generic-pae
16476 initrd.img-3.0.0-15-generic-pae
16481 initrd.img-3.0.0-16-generic-pae
16478 initrd.img-3.0.0-17-generic-pae
   12 lost+found
  174 memtest86+.bin
  176 memtest86+_multiboot.bin
 1700 System.map-2.6.32-34-generic-pae
 1841 System.map-2.6.35-30-generic-pae
 2115 System.map-2.6.38-12-generic-pae
 2141 System.map-3.0.0-12-generic-pae
 2141 System.map-3.0.0-13-generic-pae
 2143 System.map-3.0.0-14-generic-pae
 2146 System.map-3.0.0-15-generic-pae
 2147 System.map-3.0.0-16-generic-pae
 2147 System.map-3.0.0-17-generic-pae
 2148 System.map-3.0.0-19-generic-pae
 2149 System.map-3.0.0-20-generic-pae
    2 vmcoreinfo-2.6.32-34-generic-pae
    2 vmcoreinfo-2.6.35-30-generic-pae
    2 vmcoreinfo-2.6.38-12-generic-pae
    2 vmcoreinfo-3.0.0-12-generic-pae
    2 vmcoreinfo-3.0.0-13-generic-pae
    2 vmcoreinfo-3.0.0-14-generic-pae
    2 vmcoreinfo-3.0.0-15-generic-pae
    2 vmcoreinfo-3.0.0-16-generic-pae
    2 vmcoreinfo-3.0.0-17-generic-pae
    2 vmcoreinfo-3.0.0-19-generic-pae
    2 vmcoreinfo-3.0.0-20-generic-pae
 4092 vmlinuz-2.6.32-34-generic-pae
 4347 vmlinuz-2.6.35-30-generic-pae
 4567 vmlinuz-2.6.38-12-generic-pae
 4675 vmlinuz-3.0.0-12-generic-pae
 4676 vmlinuz-3.0.0-13-generic-pae
 4681 vmlinuz-3.0.0-14-generic-pae
 4698 vmlinuz-3.0.0-15-generic-pae
 4700 vmlinuz-3.0.0-16-generic-pae
 4700 vmlinuz-3.0.0-17-generic-pae
 4703 vmlinuz-3.0.0-19-generic-pae
 4705 vmlinuz-3.0.0-20-generic-pae

uname -a的输出:

 Linux kitsch 3.0.0-17-generic-pae #30-Ubuntu SMP Thu Mar 8 17:53:35 UTC 2012 i686 i686 i386 GNU/Linux

相关 - http://askubuntu.com/questions/65096/how-to-clean-previous-kernels-after-update - adempewolff
sudo apt-get autoremove 运行得非常顺利。 在我的情况下,它清理了未使用的内核文件,使磁盘使用率从100%降低到40%。 - user310604
7个回答

你的/boot分区被旧内核填满了。有时候会出现这种情况,不确定为什么从未修复过。如果你知道它们来自哪些软件包,你可以轻松地删除这些旧内核。
首先运行uname -a命令来检查你当前的版本。
然后执行以下命令:
dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d'

这个命令将列出所有你不再需要的软件包。我不喜欢自动删除它们,我希望在删除内核时保持控制。因此,对于列出的每个软件包,请执行以下操作:
sudo apt-get -y purge some-kernel-package

幕间

这个幕间更详细地描述了命令如何工作,并尝试修复linux-libc-dev:amd64的问题。大多数用户可以跳过这一段。

  • dpkg -l 'linux-*' - 列出所有以'linux-'开头的软件包
  • sed '/^ii/!d; - 移除所有不以ii开头的行
  • uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/" - 查找当前运行的内核版本
  • /'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d - 移除除了包含当前运行的内核版本号之外的所有行
  • s/^[^ ]* [^ ]* \([^ ]*\).*/\1/ - 对于每一行,只列出软件包名称
  • /[0-9]/!d - 移除不包含数字的行。
为了解决Frederick Nord的问题,我认为可以将命令修改如下:
dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d;/^linux-\(headers\|image\)/!d'

它基本上添加了一个额外的过滤器:

  • /^linux-\(headers\|image\)/!d - 删除所有不以linux-headerslinux-image开头的行

/插曲

其中some-kernel-package可以替换为列表中的任意一个包。只要注意不要删除当前正在使用的内核包(由uname -a列出),例如:sudo apt-get purge -y linux-headers-3.0.0-12等。

可以进一步使用xargs命令自动化,但我不喜欢那样做。这是个人的事情。然而,以下是执行此操作的命令:

dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d' | xargs sudo apt-get -y purge

这是我的/boot目录的样子,有一个备用内核(2.6.38-11)以防万一,当前使用的是3.2.0-24。
$ ls -l /boot
total 59388
-rw-r--r-- 1 root root   730545 Sep 13  2011 abi-2.6.38-11-generic
-rw-r--r-- 1 root root   791023 Apr 25 13:51 abi-3.2.0-24-generic
-rw-r--r-- 1 root root   130326 Sep 13  2011 config-2.6.38-11-generic
-rw-r--r-- 1 root root   140341 Apr 25 13:51 config-3.2.0-24-generic
drwxr-xr-x 3 root root     5120 May 27 17:46 grub
-rw-r--r-- 1 root root 20883146 Oct  1  2011 initrd.img-2.6.38-11-generic
-rw-r--r-- 1 root root 22474219 May  5 09:04 initrd.img-3.2.0-24-generic
drwxr-xr-x 2 root root    12288 Apr 16  2009 lost+found
-rw-r--r-- 1 root root   176764 Nov 27 11:00 memtest86+.bin
-rw-r--r-- 1 root root   178944 Nov 27 11:00 memtest86+_multiboot.bin
-rw------- 1 root root  2656297 Sep 13  2011 System.map-2.6.38-11-generic
-rw------- 1 root root  2884358 Apr 25 13:51 System.map-3.2.0-24-generic
-rw------- 1 root root     1369 Sep 13  2011 vmcoreinfo-2.6.38-11-generic
-rw------- 1 root root  4526784 Sep 13  2011 vmlinuz-2.6.38-11-generic
-rw------- 1 root root  4965776 Apr 25 13:51 vmlinuz-3.2.0-24-generic

文件系统使用情况:
$ df -h /boot
Filesystem Size Used Avail Use% Mounted
/dev/sda5  228M  63M  154M  29% /boot

2这个解决方案受到了OzzyFrank在http://ubuntugenius.wordpress.com/2011/01/08/ubuntu-cleanup-how-to-remove-all-unused-linux-kernel-headers-images-and-modules/上一篇文章的很大启发。 - jippie
10是的,为什么这成了一个问题呢?这不应该由用户来处理。 - Elijah Lynn
我使用了这个解决方案的次数比我愿意承认的多。 - Gautam
3顺便说一句:这对我来说也匹配了linux-libc-dev:amd64。所以它可能过于宽容了一点。 - Frederick Nord
@FrederickNord 请查看我在答案中添加的插曲。 - jippie
5有时候它会这样做,不确定为什么它从来没有被修复。Ubuntu已经做出了决定,无论是好是坏,提供定期的新内核作为新软件包而不是升级现有软件包,以便选择安装多个内核并随意切换。我同意这种假设并不适合那些只想要最新内核(也许还有一个备用内核以防启动问题)的95%的人,他们不想自己管理已安装的内核。也许在未来,Ubuntu会改变这种行为。目前,请确保你的/boot分区足够大。 - thomasrutter
3@thomasrutter 如果你(像我和你所说的95%的人一样)认为这个错误很重要,请在这里投票:https://bugs.launchpad.net/ubuntu/+source/update-manager/+bug/1183692 - FriendFX

sudo apt-get autoremove

这对我来说起了作用,它成功清理了所有未使用的内核包。

5这是不正确的。从man apt-get中可以看出,autoremove用于删除为了满足某个软件包的依赖关系而自动安装的软件包,而这些软件包现在不再需要。内核不会被安装来满足依赖关系,它们是在升级过程中安装的。 - dward
5@neon_overload 我只是发布了它,因为对我来说起到了作用。 - topless
1@dward 它确实为我释放了一些空间: 之前的自动删除: /dev/sda1,总共 240M,已使用 171M,剩余 57M,使用率 75%,/boot 之后: /dev/sda1,总共 240M,已使用 129M,剩余 98M,使用率 57%,/boot - Stefan Rogin
@clickstefan第一个答案是正确的。还可以查看http://askubuntu.com/questions/89710/how-do-i-free-up-more-space-in-boot/259092?noredirect=1 - dward
这应该是被选中的答案。 - opengrid
11在“磁盘空间不足”对话框中应该有一个按钮来执行此任务。这将特别帮助那些对命令行不熟悉的新手用户。 - Martin R.
2成功地完成任务,而不损坏我的操作系统。 - Ruthvik Vaila

与其他GUI答案相比,这个答案的优势在于使用本地的Ubuntu Bash而无需安装第三方应用程序。
Zenity和Bash提供了一个漂亮的GUI界面,可以在终端上处理列表并使用单选按钮选择项目。

rm-kernels 1

当前使用的内核无法删除,并且不在列表中。报告的大小是将在/boot目录中节省的空间。由于内核二进制文件也驻留在其他区域,因此磁盘上保存了更多内容。2017年7月27日的说明:目录/usr/src/*kernel_version*和/lib/modules/*kernel_version*现在也包括在内。
修改日期是使用stat命令发现的。在我的系统上,每次使用这个cron重启脚本(如何找出特定内核版本上次启动的时间?)启动内核时,该日期会被“触发”。但是,在您的系统上,该日期将是内核发布日期,而不是您最后一次启动它的时间。
apt-get purge给您一个中止的机会
您将有最后一次机会查看将被清除的所有内容,并查看将要恢复的总磁盘空间(有些误导)。
The following packages will be REMOVED:
  linux-headers-4.7.1-040701* linux-headers-4.7.1-040701-generic*
  linux-headers-4.7.2-040702* linux-headers-4.7.2-040702-generic*
  linux-headers-4.7.3-040703* linux-headers-4.7.3-040703-generic*
  linux-headers-4.8.1-040801* linux-headers-4.8.1-040801-generic*
  linux-headers-4.8.10-040810* linux-headers-4.8.10-040810-generic*
  linux-headers-4.8.11-040811* linux-headers-4.8.11-040811-generic*
  linux-headers-4.8.4-040804* linux-headers-4.8.4-040804-generic*
  linux-headers-4.8.5-040805* linux-headers-4.8.5-040805-generic*
  linux-image-4.7.1-040701-generic* linux-image-4.7.2-040702-generic*
  linux-image-4.7.3-040703-generic* linux-image-4.8.1-040801-generic*
  linux-image-4.8.10-040810-generic* linux-image-4.8.11-040811-generic*
  linux-image-4.8.4-040804-generic* linux-image-4.8.5-040805-generic*
0 upgraded, 0 newly installed, 24 to remove and 2 not upgraded.
After this operation, 2,330 MB disk space will be freed.
Do you want to continue? [Y/n] 

代码

将此代码复制到名为rm-kernels的可执行文件中,放置在/usr/local/bin目录下:

#!/bin/bash

# NAME: rm-kernels
# PATH: /usr/local/bin
# DESC: Provide zenity item list of kernels to remove

# DATE: Mar 10, 2017. Modified Jul 28, 2017.

# NOTE: Will not delete current kernel.

#       With 10 kernels on an SSD, empty cache from sudo prompt (#) using:
#       # free && sync && echo 3 > /proc/sys/vm/drop_caches && free
#       First time for `du` 34 seconds.
#       Second time for `du` 1 second.

# PARM: If any parm 1 passed use REAL kernel size, else use estimated size.
#       By default `du` is not used and estimated size is displayed.

# Must be running as sudo
if [[ $(id -u) != 0 ]]; then
    zenity --error --text "root access required. Use: sudo rm-kernels"
    exit 99
fi

OLDIFS="$IFS"
IFS="|"
choices=()

current_version=$(uname -r)

for f in /boot/vmlinuz*
do
    if [[ $f == *"$current_version"* ]]; then continue; fi # skip current version
    [[ $f =~ vmlinuz-(.*) ]]
    v=${BASH_REMATCH[1]}        # example: 4.9.21-040921-generic
    v_main="${v%-*}"            # example: 4.9.21-040921

    # Kernel size in /boot/*4.9.21-040921-generic*
    s=$(du -ch /boot/*-$v* | awk '/total/{print $1}')

    if [[ $# -ne 0 ]] ; then    # Was a parameter passed?
        if [[ -d "/usr/src/linux-headers-"$v_main ]] ; then
             # Kernel headers size in /usr/src/*4.9.21-040921*
             s2=$(du -ch --max-depth=1 /usr/src/*-$v_main* | awk '/total/{print $1}')
        else
             s2="0M"            # Linux Headers are not installed
        fi
        # Kernel image size in /lib/modules/4.9.21-040921-generic*
        s3=$(du -ch --max-depth=1 /lib/modules/$v* | awk '/total/{print $1}')
    else
        # Estimate sizof of optional headers at 125MB and size of image at 220MB
        if [[ -d "/usr/src/linux-headers-"$v_main ]] ; then
             s2="125M"
        else
             s2="0M"            # Linux Headers are not installed
        fi
        s3="220M"
    fi

    # Strip out "M" provided by human readable option of du and add 3 sizes together
    s=$(( ${s//[^0-9]*} + ${s2//[^0-9]*} + ${s3//[^0-9]*} ))
    t=$(( t + s ))
    s=$s" MB"
    d=$(date --date $(stat -c %y $f) '+%b %d %Y') # Last modified date for display
    choices=("${choices[@]}" false "$v" "$d" "$s")
done

# adjust width & height below for your screen 640x480 default for 1920x1080 HD screen
# also adjust font="14" below if blue text is too small or too large

choices=(`zenity \
        --title "rm-kernels - Total: $t MB excluding: $current_version" \
        --list \
        --separator="$IFS" \
        --checklist --multiple \
        --text '<span foreground="blue" font="14">Check box next to kernel(s) to remove</span>' \
        --width=640 \
        --height=480 \
        --column "Select" \
        --column "Kernel Version Number" \
        --column "Modified Date" \
        --column " Size " \
        "${choices[@]}"`)
IFS="$OLDIFS"

i=0
list=""
for choice in "${choices[@]}" ; do
    if [ "$i" -gt 0 ]; then list="$list- "; fi # append "-" from last loop
    ((i++))

    short_choice=$(echo $choice | cut -f1-2 -d"-")
    header_count=$(find /usr/src/linux-headers-$short_choice* -maxdepth 0 -type d | wc -l)

    # If -lowlatency and -generic are purged at same time the _all header directory
    # remains on disk for specific version with no -generic or -lowlatency below.
    if [[ $header_count -lt 3 ]]; then
        # Remove all w.x.y-zzz headers
        list="$list""linux-image-$choice- linux-headers-$short_choice"
    else
        # Remove w.x.y-zzz-flavour header only, ie -generic or -lowlatency
        list="$list""linux-image-$choice- linux-headers-$choice" 
    fi

done

if [ "$i" -gt 0 ] ; then
     apt-get purge $list
fi

注意:您需要使用sudo权限来创建文件,因此请使用以下命令:
gksu gedit /usr/local/bin/rm-kernels

要使文件可执行,请使用以下命令:
sudo chmod +x /usr/local/bin/rm-kernels

注意:如果您需要服务器(基于文本而非图形界面)版本的脚本,请参考:如何删除旧内核版本以清理启动菜单?

2017年7月28日更新

我们现在从/boot/*kernel_version*中获取每个内核的计算大小,其中包括5个文件总共约50MB。现在我们的公式已经更改,包括了/usr/src/*kernel_version*/lib/modules/*kernel_version*中的文件。现在每个内核的计算大小为约400MB。上述代码中的rm-kernelsrm-kernels-server已经更新。但是,上述示例屏幕尚未反映这些更改。

默认情况下,我们估算linux-headers文件大小为125MB,linux-image文件大小为220MB,因为除非文件被缓存,否则du命令的速度会非常慢。如果要使用du来获取真实大小,请向脚本传递任何参数。

所有内核大小的总和(不包括当前正在运行的版本,该版本无法删除)现在显示在标题栏中。

用于显示每个内核的上次访问日期的对话框。在备份或类似操作期间,所有内核的此日期可能会被重写。对话框现在显示修改日期


你太棒了!真的非常感谢!你让我很开心! - zhartaunik
太棒了!谢谢分享。终于有了处理这个无聊的内核管理的简单方便的方法。 - Skazzi
@Skazzi 这个脚本已经有将近四年的历史了。很可能是在Ubuntu引入“签名内核”之前编写的。如果在使用脚本后还有剩余文件,请告诉我,我会进行更新。 - WinEunuuchs2Unix
不再工作了吗?“rmdir:无法删除'/lib/modules/5.15.0-43-generic':目录非空” - smartmouse
1@smartmouse 在回答发布之后的几年里,modules库出现了。 - WinEunuuchs2Unix

你可以通过Synaptic软件包管理器轻松处理内核。 但首先,你应该知道当前使用的内核版本名称。你可以在终端提示符中运行uname -r来找到这个信息。
linux@linux-desktop:~$ uname -r
4.4.0-75-generic

至少这个版本你应该保持不变。 打开Synaptic并开始填写快速过滤器占位符,如下所示:

quick filter search box at top in synaptic

现在您可以选择要删除的所有软件包,并执行以下操作:
标记为完全删除 > 应用
我建议至少保留一个最新的当前内核软件包和一个先前的内核软件包。例如,在这种情况下,您可以安全地摆脱 linux-image-4.4.0-66-generic 和 linux-image-extra-4.4.0-66-generic,但最好保留 4.4.0-72 和当然 4.4.0-75。

为了方便使用命令行:

https://github.com/erichs/bootnukem

git clone https://github.com/erichs/bootnukem.git
cd bootnukem
sudo ./install.sh

那么

sudo bootnukem --dry-run


我在使用软件更新器进行更新时遇到了类似的问题,对我来说,使用sudo apt full-upgrade解决了这个问题。