Just a little script

What could be easier?

Tuesday, October 28, 2008

Gnus is awesome

Gnus is my mail client. It's my NNTP and feed-reading client too. Gnus runs inside Emacs and is fancier than a Swiss Army knife. Here's a quick example.

Messages sent to the Puppet bugs list don't thread well. Redmine puts the bug's status in the middle of the subject. For example, this is the subject for a newly submitted bug:
  • [Puppet - Bug #1686] (Unreviewed) Class names containing '-' cannot be used to scope variables
The next message about this bug has this subject:
  • [Puppet - Bug #1686] (Needs design decision) Class names containing '-' cannot be used to scope variables
The stuff in parentheses prevents these two messages from displaying as part of the same thread. Of course I want threading so I can read all related messages at the same time and easily skip over bugs that I don't care about.

Gnus to the rescue! 8 lines of elisp gets me the threading I want. The hardest part is the regexp. Here's the code:
(defun map-alter-message-id (header)
(let ((subject (mail-header-subject header)))
(when (string-match "^\\(.*\\) \\(([^)]*)\\) \\(.*\\)$" subject)
(setq map-temp header)
(mail-header-set-subject
header
(concat (match-string 1 subject) " " (match-string 3 subject))))))
(setq gnus-alter-header-function 'map-alter-message-id)
This takes me from these 20 lines of unthreaded subjects:
  • [Puppet - Bug #1686] (Unreviewed) Class names containing '-' cannot be used to scope variables
  • [Puppet - Bug #1679] Control characters can't be used within a file resource
  • [Puppet - Bug #1687] (Unreviewed) SELinux operations don't appear to be working on RHEL4
  • [Puppet - Bug #1687] (Accepted) SELinux operations don't appear to be working on RHEL4
  • [Puppet - Bug #1688] (Unreviewed) puppetca can't clean unsigned certs
  • [Puppet - Bug #1688] (Accepted) puppetca can't clean unsigned certs
  • [Puppet - Bug #1680] (Accepted) Setting user password on Solaris does not work
  • [Puppet - Bug #1689] (Unreviewed) Hundreds of log messages a second because of dns resolution
  • [Puppet - Bug #1690] (Unreviewed) Dependencies for class not preserved
  • [Puppet - Bug #1690] (Rejected) Dependencies for class not preserved
  • [Puppet - Bug #1686] (Needs design decision) Class names containing '-' cannot be used to scope variables
  • [Puppet - Bug #1683] (Needs more information) "Random" errors coming from puppetmasterd
  • [Puppet - Bug #1691] (Unreviewed) Realization fails if variable is used to represent array
  • [Puppet - Bug #1691] Realization fails if variable is used to represent array
  • [Puppet - Bug #1691] Realization fails if variable is used to represent array OR multiple realizes exist in a single 'if' statement
  • [Puppet - Bug #1692] (Unreviewed) k5login fails to set mode when file is created
  • [Puppet - Bug #1692] (Accepted) k5login fails to set mode when file is created
  • [Puppet - Refactor #1693] (Accepted) All mentions of EPM should be removed from Rakefile and build library
  • [Puppet - Refactor #1693] (Ready for Checkin) All mentions of EPM should be removed from Rakefile and build library
To just 8 after threading:
  • [Puppet - Bug #1686] Class names containing '-' cannot be used to scope variables...
  • [Puppet - Bug #1679] Control characters can't be used within a file resource...
  • [Puppet - Bug #1687] SELinux operations don't appear to be working on RHEL4...
  • [Puppet - Bug #1688] puppetca can't clean unsigned certs...
  • [Puppet - Bug #1680] Setting user password on Solaris does not work...
  • [Puppet - Bug #1689] Hundreds of log messages a second because of dns resolution...
  • [Puppet - Bug #1690] Dependencies for class not preserved...
  • [Puppet - Bug #1683] "Random" errors coming from puppetmasterd...
Many thanks to Larsi for Gnus and for Gmane too!

Tuesday, October 14, 2008

It's easier than you think

Long ago I was known for saying "Ah, just a little script!" in response to whatever sysadmin challenge was presenting itself at the moment. It probably started innocently enough when I learned things like how useful a for loop can be when used on the command-line or in a little 'go' script. Especially with my buddies sed, awk, grep, etc. "You want a list of IP addresses that have logged in this month sorted from most logins to least? No problem! That's just a little script!"

As more and more was expected out of fewer and fewer people it became comical...

Me: "Um, you want a DHCP service for all the newly deployed cable modems in the dorms? And it has to give out a private non-routable IP when a student first connects, send the student to a registration page no matter where they try to go on the web, let them register their MAC address, update dhcpd.conf so they get a routable IP next time they ask, and have a management interface for the Helpdesk types supporting students in the dorm? Is that all?"

Boss: "Actually, not quite all. We've got a guy who's tossed something together for 2 or 3 dorms. He's running one machine and DHCP server per dorm and his code is nearly the same on all three boxes! Take that over and clean it up too. Oh and it has to be in production by fall."

Of course the marching orders were not quite that clear but the need was clear enough. Later I'm sure I said something like this to my co-workers: "Heh, sure, uh, just a little script! Ha ha!"

And so it was. Or, at least, a handful of little scripts that eventually got the job done. Always "script" because, hey, I'm no programmer! "Just a little script" became a comical mantra intoned in the face of insurmountable problems and little ones too.

We just released YaketyStats--about a year after we decided to release. Giving it away was at least as hard as writing it in the first place. And sure it was hard and took time but was it that hard? After all it's just a bunch of little scripts! Jart is an exception, of course, because Sam did all of that and it's cool and not little.

So"just a little script" it's a joke but it's real too. Anything's possible. Create your own happiness. Don't wait. Just do it.