¿Comando para reconstruir todos los módulos DKMS para todos los núcleos instalados?

39

Ocasionalmente, mi sistema entra en un estado en el que a algunos núcleos les falta uno o dos módulos, porque DKMS de alguna manera olvidó compilar esos módulos para ese núcleo. En lugar de pasar tiempo diagnosticando el problema, sería bueno si hubiera un solo comando que pudiera ejecutar que simplemente reconstruyera cada módulo controlado por dkms para cada núcleo instalado. ¿Hay tal comando?

Ryan C. Thompson
fuente
Siempre obtengo el Módulo de salida broadcom-sta / 5.100.82.112 ya instalado en el kernel 2.6.38jon-64 / x86_64 Realmente quiero una opción --force o --rebuild --just-do-what-i-say;)

Respuestas:

47

Descubrí una concha de una línea para hacerlo:

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

Esto funciona porque los nombres de los directorios /var/lib/initramfs-toolsson exactamente los nombres de las versiones del núcleo a los que debe pasar dkms_autoinstallerpara indicar que reconstruya todos los módulos para esas versiones del núcleo. Tenga en cuenta que si ha desinstalado algunos núcleos antiguos, es posible que sus directorios todavía estén por ahí y provoquen que se informen algunos errores, pero esto no es un problema porque dkms_autoinstallersimplemente no hará nada para las versiones de kernel que no están instaladas.

Ryan C. Thompson
fuente
1
dio algunos errores porque aparecieron headers-xxx y headers-xxx-generic pero parecía reconstruir las cosas correctas a pesar de los errores
frankster
@frankster Después de encontrar múltiples "¡Error! No se pudo encontrar el archivo dkms.conf". para una nueva instalación de kernel, pude instalar módulos de kernel anteriores listados dkms statuspara el nuevo kernel usando los siguientes módulos específicos que quería de "/ usr / src". Los parámetros deben cambiarse según sea necesario para -c, -m, -v. Aquí hay un ejemplo para el módulo 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

No parece que el dkmscomando te permita hacer eso. Creé un pequeño script de Python que debería hacer lo que quieras. Puedes poner un alias en tu me ~/.bashrcgusta

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

Por supuesto, primero deberías hacer que sea ejecutable. Aquí está el código:

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

Probado aquí, parece funcionar bien:

$ 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

Si también desea instalar los módulos, reemplace build con install en la segunda última línea.

htorque
fuente
4

Combinando las respuestas de @htorque y @Ryan Thompson, aquí está mi (como root) una frase:

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
fuente
1

Lo anterior no funciona en todas las variantes, esto podría ser un poco más útil en esos casos ...

$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
fuente
¿Podría explicar qué hace esto que no hacen los otros métodos?
Ryan C. Thompson
Funciona en sistemas que no tienen / usr / src / linux-headers- * y / var / lib / initramfs-tools
stu
considere la situación en la que lo necesita para ejecutarse en varias distribuciones de Linux diferentes que solo tienen el hecho de que dkms (más o menos) funciona, en común.
Stu
0

dkms statusy dkms_autoinstallerno funciona en ubuntu 16.x. Entonces, algún script de shell servirá. Esta secuencia de comandos supone que tiene *-dkmsinstalado el paquete deb adecuado y bashes su shell.

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
fuente
0

Una edición del script por @htorque. Utilizarlo en caso de que quiera una fuerza de reconstruir (e instalar) de módulos ya construidas. Cambiado a python3, subprocess.run()requiere 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
fuente