Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

Occasionally, my system gets into a state where some kernels are missing a module or two, because DKMS somehow forgot to compile those modules for that kernel. Rather than spend time diagnosing the problem, it would be nice if there was a single command I could run that woudl just rebuild every dkms-controlled module for every installed kernel. Is there such a command?

share|improve this question
    
I always get the output Module broadcom-sta/5.100.82.112 already installed on kernel 2.6.38jon-64/x86_64 I really want a --force or a --rebuild --just-do-what-i-say option ;) –  user140350 Mar 14 '13 at 21:14

3 Answers 3

up vote 10 down vote accepted

I figured out a couple of shell one-liner to do it:

ls /usr/src/linux-headers-* -d | sed -e 's/.*linux-headers-//' | \
  sort -V | tac | sudo xargs -n1 /usr/lib/dkms/dkms_autoinstaller start

alternatively:

ls /var/lib/initramfs-tools | sudo xargs -n1 /usr/lib/dkms/dkms_autoinstaller start
share|improve this answer
    
it gave some errors because it came up headers-xxx and headers-xxx-generic but it seemed to rebuild the correct stuff despite the errors –  frankster Feb 14 '12 at 19:09

Doesn't look like the dkms command allows you to do that. I created a small Python script that should do what you want. You can put an alias in your ~/.bashrc like

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

Of course you'd need to make it executable first. Here's the code:

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

Tested it here, seems to work just fine:

$ 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

If you also want to install the modules, replace build with install in the second last line.

share|improve this answer

Combining @htorque and @Ryan Thompson's answers, here's my (as root) one-liner:

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
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.