命令为所有已安装的内核重建所有 DKMS 模块?

Rya*_*son 49 kernel kernel-modules dkms

有时,我的系统会进入某些内核缺少一两个模块的状态,因为 DKMS 不知何故忘记为该内核编译这些模块。与其花时间诊断问题,还不如有一个我可以运行的单一命令,该命令只需为每个已安装的内核重建每个dkms 控制的模块。有这样的命令吗?

Rya*_*son 60

我想出了一个外壳单线来做到这一点:

ls /var/lib/initramfs-tools | \
    sudo xargs -n1 /usr/lib/dkms/dkms_autoinstaller start
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为 中目录的/var/lib/initramfs-tools名称正是您需要传递给dkms_autoinstaller它以告诉它为这些内核版本重建所有模块的内核版本名称。请注意,如果您卸载了一些旧内核,它们的目录可能仍然存在并导致报告一些错误,但这不是问题,因为dkms_autoinstaller对于那些未安装的内核版本将不执行任何操作。


hto*_*que 8

看起来该dkms命令不允许您这样做。我创建了一个小的 Python 脚本,它应该可以做你想做的事。你可以在你~/.bashrc喜欢的地方放一个别名

alias dkms-buildall='sudo ./wherever/your/script/is'
Run Code Online (Sandbox Code Playgroud)

当然,您首先需要使其可执行。这是代码:

#!/bin/env python
#
# NOTE: This assumes that all modules and versions are built for at
#       least one kernel. If that's not the case, adapt parsing as needed.
import os
import subprocess

# Permission check.
if os.geteuid() != 0:
    print "You need to be root to run this script."
    exit(1)

# Get DKMS status output.
cmd = ['dkms', 'status']
process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
dkms_status = process.communicate()[0].strip('\n').split('\n')
dkms_status = [x.split(', ') for x in dkms_status]

# Get kernel versions (probably crap).
cmd = ['ls', '/var/lib/initramfs-tools/']
# Alternative (for use with Arch Linux for example)
# cmd = ['ls', '/usr/lib/modules/']
process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
kernels = process.communicate()[0].strip('\n').split('\n')

# Parse output, 'modules' will contain all modules pointing to a set
# of versions.
modules = {}

for entry in dkms_status:
   module = entry[0]
   version = entry[1].split(': ')[0]
   try:
      modules[module].add(version)
   except KeyError:
      # We don't have that module, add it.
      modules[module] = set([version])

# For each module, build all versions for all kernels.
for module in modules:
   for version in modules[module]:
      for kernel in kernels:
         cmd = ['dkms', 'build', '-m', module, '-v', version, '-k', kernel]
         ret = subprocess.call(cmd)
Run Code Online (Sandbox Code Playgroud)

在这里测试过,似乎工作得很好:

$ dkms status
nvidia-current, 275.09.07, 3.0.0-5-generic, x86_64: installed
virtualbox, 4.0.10, 3.0.0-5-generic, x86_64: installed

$ sudo python dkms.py
...

$ dkms status
nvidia-current, 275.09.07, 3.0.0-5-generic, x86_64: installed
nvidia-current, 275.09.07, 3.0-2-generic, x86_64: built
nvidia-current, 275.09.07, 3.0-3-generic, x86_64: built
virtualbox, 4.0.10, 3.0.0-5-generic, x86_64: installed
virtualbox, 4.0.10, 3.0-2-generic, x86_64: built
virtualbox, 4.0.10, 3.0-3-generic, x86_64: built
Run Code Online (Sandbox Code Playgroud)

如果您还想安装模块,请将最后一行中的build替换为install


phs*_*phs 6

结合@htorque 和@Ryan Thompson 的答案,这是我的(作为 root 用户)单行:

dkms status | sed s/,//g | awk '{print "-m",$1,"-v",$2}' | while read line; do ls /var/lib/initramfs-tools | xargs -n 1 dkms install $line -k; done
Run Code Online (Sandbox Code Playgroud)


小智 5

没有足够的声誉来评论@Ryan Thompson的答案,但这可能对某人有用。在 Ubuntu 22.04 中没有/var/lib/initramfs-tools目录,但是,每个安装的内核版本initrd.img-<kernel version>中都存在映像/boot,而这些<kernel version>正是dkms(和dkms_autoinstaller)所需要的。那么让我们使用它们:

ls /boot/initrd.img-* | cut -d- -f2- | \
    sudo xargs -n1 /usr/lib/dkms/dkms_autoinstaller start
Run Code Online (Sandbox Code Playgroud)