Memerintahkan untuk membangun kembali semua modul DKMS untuk semua kernel yang diinstal?

39

Kadang-kadang, sistem saya masuk ke keadaan di mana beberapa kernel kehilangan satu atau dua modul, karena DKMS entah bagaimana lupa untuk mengkompilasi modul-modul untuk kernel itu. Daripada menghabiskan waktu mendiagnosis masalah, alangkah baiknya jika ada satu perintah yang dapat saya jalankan yang hanya akan membangun kembali setiap modul yang dikendalikan dkms untuk setiap kernel yang diinstal. Apakah ada perintah seperti itu?

Ryan C. Thompson
sumber
Saya selalu mendapatkan Modul output broadcom-sta / 5.100.82.112 yang sudah diinstal pada kernel 2.6.38jon-64 / x86_64 Saya benar-benar menginginkan opsi --force atau --rebuild --just-do-what-i-say;)

Jawaban:

47

Saya menemukan shell one-liner untuk melakukannya:

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

Ini berfungsi karena nama-nama direktori di dalamnya /var/lib/initramfs-toolsadalah nama-nama versi kernel yang harus Anda lewati dkms_autoinstalleruntuk mengatakannya untuk membangun kembali semua modul untuk versi-versi kernel tersebut. Perhatikan bahwa jika Anda telah menghapus beberapa kernel lama, direktori mereka mungkin masih ada dan menyebabkan beberapa kesalahan dilaporkan, tetapi ini bukan masalah karena dkms_autoinstallerhanya akan melakukan apa-apa untuk versi kernel yang tidak diinstal.

Ryan C. Thompson
sumber
1
itu memberikan beberapa kesalahan karena muncul header-xxx dan header-xxx-generik tetapi tampaknya untuk membangun kembali hal-hal yang benar meskipun ada kesalahan
frankster
@frankster Setelah menemukan beberapa "Kesalahan! Tidak dapat menemukan file dkms.conf." untuk instalasi kernel baru, saya dapat menginstal modul-modul kernel sebelumnya yang terdaftar oleh dkms statuske kernel baru menggunakan modul-modul berikut yang saya inginkan dari "/ usr / src". Parameter perlu diubah sesuai kebutuhan untuk -c, -m, -v. Berikut ini adalah contoh untuk modul nvidia-384-384.90: ls /var/lib/initramfs-tools | \ sudo xargs -n1 /usr/sbin/dkms install -c /usr/src/nvidia-384-384.90/dkms.conf -m nvidia -v 384-384.90 -k
m1st0
8

Tidak terlihat seperti dkmsperintah yang memungkinkan Anda melakukan itu. Saya membuat skrip Python kecil yang harus melakukan apa yang Anda inginkan. Anda dapat memasukkan alias di ~/.bashrcsuka

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

Tentu saja Anda harus membuatnya dapat dieksekusi terlebih dahulu. Ini kodenya:

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

Mengujinya di sini, tampaknya berfungsi dengan baik:

$ 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

Jika Anda juga ingin menginstal modul, ganti build dengan install di baris terakhir kedua.

htorque
sumber
4

Menggabungkan jawaban @htorque dan @Ryan Thompson, inilah one-liner (sebagai root) saya:

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
phs
sumber
1

Di atas tidak bekerja pada semua varian, ini mungkin sedikit lebih membantu dalam kasus-kasus ...

$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
stu
sumber
Bisakah Anda menguraikan apa yang tidak dilakukan oleh metode lain ini?
Ryan C. Thompson
Ini bekerja pada sistem yang tidak memiliki / usr / src / linux-headers- * dan / var / lib / initramfs-tools
stu
pertimbangkan situasi di mana Anda memerlukannya untuk berjalan di berbagai distro linux yang hanya memiliki fakta bahwa dkms (semacam) bekerja, secara umum.
stu
0

dkms statusdan dkms_autoinstallertidak berfungsi di ubuntu 16.x. Jadi beberapa skrip shell akan dilakukan. Script ini mengasumsikan Anda memiliki *-dkmspaket deb yang tepat diinstal, dan bashshell Anda.

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 
sehari24jam
sumber
0

Edit skrip oleh @htorque. Gunakan jika Anda ingin kekuatan membangun kembali (dan menginstal) modul yang sudah dibangun. Beralih ke python3, subprocess.run()membutuhkan 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)
Alex Potapenko
sumber