Команда перестроить все модули DKMS для всех установленных ядер?

Иногда моя система попадает в состояние, когда в некоторых ядрах отсутствует модуль или два, потому что DKMS почему-то забыл скомпилировать эти модули для этого ядра. Вместо того чтобы тратить время на диагностику проблемы, было бы неплохо, если бы я мог запустить одну команду, которая просто перестроит каждый модуль, контролируемый dkms, для каждого установленного ядра. Есть ли такая команда?

7 ответов

Решение

Я понял, что оболочка однострочная для этого:

ls /var/lib/initramfs-tools | \
    sudo xargs -n1 /usr/lib/dkms/dkms_autoinstaller start

Это работает, потому что имена каталогов в /var/lib/initramfs-tools это именно те имена версий ядра, которые вам нужно передать dkms_autoinstaller сказать ему перестроить все модули для этих версий ядра. Обратите внимание, что если вы удалили некоторые старые ядра, их каталоги все еще могут лежать и вызывать сообщения об ошибках, но это не проблема, потому что dkms_autoinstaller просто ничего не сделает для тех версий ядра, которые не установлены.

Не похоже на dkms Команда позволяет вам сделать это. Я создал небольшой скрипт на Python, который должен делать то, что вы хотите. Вы можете поместить псевдоним в свой ~/.bashrc лайк

alias dkms-buildall='sudo ./wherever/your/script/is'

Конечно, сначала нужно сделать его исполняемым. Вот код:

#!/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)

Протестировано здесь, кажется, работает просто отлично:

$ 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

Если вы также хотите установить модули, замените build на install во второй последней строке.

Комбинируя ответы @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

Недостаточно репутации, чтобы комментировать @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

Редактирование сценария @htorque. Используйте его, если вы хотите принудительно перестроить (и установить) уже созданные модули. Перешел на python3, subprocess.run() требует Python 3.5+.

#!/usr/bin/env python3
#
# 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']
dkms_status = subprocess.run(cmd, stdout=subprocess.PIPE).stdout.decode("utf-8").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/']
kernels = subprocess.run(cmd, stdout=subprocess.PIPE).stdout.decode("utf-8").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:
         for action in ['remove', 'install']:
            cmd = ['dkms', action, '-m', module, '-v', version, '-k', kernel]
            subprocess.run(cmd)

Вышеупомянутое не работает на всех вариантах, это может быть немного более полезным в этих случаях...

$modulename="whatever"
$moduleversion=`modinfo $modulename | grep "^version:" | awk '{ print $2 }'`
dkms status | grep $modulename | tr -d ',' | awk '{ print $3 }' | xargs -n1 dkms build $modulename/$moduleversion -k

dkms status а также dkms_autoinstaller не работает в Ubuntu 16.x. Так что некоторые сценарии оболочки будут делать. Этот сценарий предполагал, что вы правильно *-dkms установлен deb-пакет и bash это твоя оболочка

for k in $(ls /var/lib/initramfs-tools) ; do
 for d in $(cd /usr/src; ls -d *-*) ; do
  [[ -f /usr/src/${d}/dkms.conf ]] || continue
  m=$(echo $d | sed -r -e 's/-([0-9]).+//')
  v=$(echo $d | sed -r -e 's/[^0-9]+-([0-9])/\1/')
  sudo /usr/sbin/dkms install -c /usr/src/$d/dkms.conf -m $m -v $v -k $k
 done
done 
Другие вопросы по тегам