jasonwryan.com

Miscellaneous ephemera…

Managing modules with Awk

This is an addendum to my two previous posts on compiling kernels and automating the process. In the first of those posts I wrote about a wonderful tool to track the modules necessary for building a custom kernel with make localmodconfig, graysky’s modprobed_db. A simple bash script, modprobed_db allows you to build up an array of modules and—as the name suggests—modprobe all of them prior to compilation.

I forked it on github and started to play around with the script (mostly because I am slightly OCD about constructions like this:

modprobed_db lines 62-63
1
2
3
cat /proc/modules | awk '{print $1}' | sort -k 1,1 | \
  grep -Ev "$(echo ${IGNORE[*]} | sed -e 's/^/^(/' -e 's/ /|/g' -e 's/$/)$/')" \
  >/tmp/.inmem

After hacking a while, I started to realize that the venerable UNIX programme Awk would, in many ways, be a better tool for this job. Essentially, we want to manage three lists: the modules in /proc/modules, a list of modules to ignore, and the master list of all modules required prior to compilation. This seems perfectly suited to Awk.

So, in the interests of learning Awk, I decided to rewrite the required functionality (or, more correctly, the subset that I required) in this language. This wasn’t a straightforward task for me. I got stuck a couple of times and, as I work in a building full of neckbeards, I thought I could ask for a couple of pointers. To my surprise, no-one I asked seemed interested in Awk. Typical responses were along the lines of “just use Perl.”

Aside from not knowing any Perl, and being unlikely to learn any in the immediate future, I was bemused by the notion that none of these skilled developers rated Awk as a language worth knowing. One of the #awk FAQ’s specifically addresses this: Why would anyone still use awk instead of perl? The quote by Tom Christiansen is worth repeating here:

Awk is a venerable, powerful, elegant, and simple tool that everyone should know. Perl is a superset and child of awk, but has much more power that comes at expense of sacrificing some of that simplicity.

In a happy coincidence, this question on Unix & Linux SE showed up just as I was completing my script and it neatly illustrates (to my unututored eye, anyway) an example of a typical situation where Awk’s strengths make it a better approach than Perl.

In any event, my rewriting of modprobed_db in Awk1 resulted in this:

awkmodules
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/usr/bin/awk -f
# script to manage modules for kernel builds

BEGIN { dbfile = ARGV[2] }

function red(s) {
    printf "\033[1;31m" s "\033[0m "
}

# read in the array
FILENAME != ARGV[3] {
  modlist[$1]++; next
}

# check for ignored modules
!modlist[$1]++ {
  print $1 >> dbfile
  close(dbfile)
  }

{
# modprobe modules
if (p == 1) {
  modload="sudo modprobe -a $(<"dbfile")"
  system(modload)
  close(modload)
  }
}

{
# update module count
if ( getline < dbfile ) {
  count++
  }
}

END {
  print red(count) "modules listed."
}

# vim:set ts=2 sts=2 sw=2 et:

Just prior to compiling a kernel, I can invoke this script with (the admittedly rather ungainly line):

1
awkmodules p=1 .config/kmod_db/ignored .config/kmod_db/modules_db /proc/modules

It does work, but I don’t claim that it is either idiomatic or attractive. The use of getline to update the module count strikes me as especially kludgy but I haven’t been able to think of a more correct way to handle it.

Incidentally, the gawk manual2, Gawk: Effective AWK Programming has only just been updated3 so Awk is, unlike it’s homonym, clearly alive and well.

Notes

  1. In my bitbucket repo.
  2. The number of variants of awk is as much a delight as it is perplexing…
  3. May, 2013

Public Domain image of the Great Auk by John James Audubon, from his book The Birds of America.

Comments