Boot-Repair tool for Ubuntu

I installed 32-bit Gentoo Linux on my computer in 2002, and kept running that same OS install without reinstalling (but with nightly updates) for over a decade. (It's morally the same computer even though I've incrementally upgraded every piece of it except the keyboard and floppy drive. Kind of like George Washington's axe.)

But I finally ran into a problem with KDE that I didn't have the patience to solve, and decided it was time for a reinstall anyway so I could use a 64-bit OS and run processes larger than 4 GB. I went with Kubuntu 12.04 rather than Gentoo this time, to avoid having to recompile the world.

Kubuntu installed fine and worked fine for a few weeks, then I needed to reboot to apply a kernel update. And when I rebooted, it didn't come back up.

So I booted from the install CD into rescue mode, and Googled for "ubuntu fix boot" or somesuch. Ran into the page for the Boot-Repair utility. It's not in base Ubuntu yet, so I had to install it from a ppa. Then I ran it, and it fixed my boot problem, and I rebooted and all was well.

Normally this kind of problem takes about half an hour of web searching and/or reading man pages then a magic incantation using fdisk. Having a mostly idiot-proof program do it for me was pretty nice. Recommended.


Comments (0)


Switched from KDE to Gnome

In the beginning (of fancy Linux desktops), I was a KDE user, because it was first.

Then I was a Gnome user, because it's what came on Red Hat and I didn't care that much.

Then Gnome 2.0 decided to remove lots of features in the name of ease-of-use, and one of the features they removed was proper Unix-style point-to-focus, which I cared about a lot more than I cared about Gnome, so I was a KDE user again.

Until last night. My KDE 4.2 plasma app kept crashing. Without plasma, I had no toolbars and no way to restore a minimized window. An hour into trying to debug the problem, it hit me that I didn't need to do this. I could just switch back to Gnome.

Sure enough, gnome 2.24 is stable. It has point-to-focus. It doesn't have a terminal as nice as konsole, or a CD burner as nice as k3b, or a music player as nice as amarok used to be before they wrecked it, but it's not crashing.

You can keep most users with inertia. It takes hard work to chase them away. Stability first. Not removing basic useful features second. New stuff last.


Comments (0)


Finding a missing print server

I have a TrendNet TE100-P1P print server. It's a little $30 gizmo with an Ethernet jack on one end and a parallel printer port on the other, so that you can turn a printer into a network printer without hanging it off a computer. Bought it because my new motherboard didn't have a parallel port. The other benefit is that now the printer works when my main desktop computer is off.

Anyway, we had a power failure, and the printer stopped working. No "lexmark" found in local DNS. No DHCP lease for the TrendNet gizmo.

The gizmo was still there, but I couldn't find it. There's no UI on the device, just the network jack. So I wrote a little script (below) to portscan my LAN for anything that answered on port 631. That found it.

Turns out that when the power goes out, the print server reconfigures its network settings from DHCP to fixed. It keeps its last network settings, but the DHCP / DNS server no longer has any record of them, so you can't find it unless you remember what its last IP was.

Here's the script. Because I had 700+ addresses to check, and it sometimes takes a few seconds for a failed socket connection to timeout, I used 250 threads to make it faster. (I initally tried using a separate thread for each IP, but I hit an OS limit at 255 threads, and decided to use a fixed-size pool and two shared work queues.)

#!/usr/bin/env python

"""Hunting for the TrendNet print server"""

import socket
import threading
import Queue


port = 631
num_threads = 250

class ConnectThread(threading.Thread):
    def __init__(self, in_queue, out_queue):
        self.in_queue = in_queue
        self.out_queue = out_queue

    def run(self):
        while True:
            ip = self.in_queue.get()
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.connect((ip, port))
            except socket.error:
                self.out_queue.put((ip, False))
                self.out_queue.put((ip, True))

def main():
    job_queue = Queue.Queue()
    result_queue = Queue.Queue()
    count = 0
    for net in range(3):
        for addr in range(1, 255 + 1):
            ip = "192.168.%d.%d" % (net, addr)
            count += 1
    for unused in xrange(num_threads):
        ConnectThread(job_queue, result_queue).start()

    for unused in xrange(count):
        ip, status = result_queue.get()
        if status:
            print ip

if __name__ == "__main__":


Comments (0)


Verizon FiOS, Double Routers

Seemed like Comcast was raising their prices every other month, and Verizon offered a FiOS combo deal of $99 / month for net / TV / phone, so I switched.

The good: Got a really competent installer. FiOS mostly works well. It's significantly cheaper than Comcast was, for more TV channels and (slightly) faster Internet. Also got about 50 movie channels free for 3 months.

The bad: Verizon is, well, evil.

  1. When they were digging holes in our yard to lay fiber, they cut the cable TV wire.
  2. They immediately sold the email address I gave them to a spammer, in violation of their stated privacy policy.
  3. They flat-out refused to do a CableCard-only install without a set-top box.  I had to order a STB in order to get TV service at all.  Getting a CableCard for my Tivo required a second phone call to a second number.  The helpful rep took my info and said the CableCard would be added to the order, but it wasn't, and the installer had to scrounge one.
  4. They sold out their customers to participate in blatantly unconstitutional warrantless wiretapping, then bribed ^W made campaign contributions to enough Congresscritters to receive immunity for these actions.

Yeah, it's possible that a couple of those actions were just incompetence rather than malice. But all of them? Unfortunately, most of the other major phone and cable companies have similar moral and legal shortcomings, and it appears that the choice is dealing with the devil, or communicating via carrier pigeon.

The tricky: The Actiontec router provided by Verizon basically worked, but the wireless range on it was lousy. Performance near the router was fine; from across the house there was connectivity, but performance was awful. (TCP is sometimes too robust for its own good. If it didn't work at all I would have diagnosed and fixed the problem much sooner.) My old Linksys WRT54G with Tomato firmware has much better wireless range. But the Actiontec has the required coax connector. So I ended up using both routers. The Actiontec has its wireless turned off, and its DHCP server supplies IPs to the STB (over coax) and to the Linksys router (over wired Ethernet from the Actiontec's LAN port to the Linksys's WAN port.). The Linksys has wireless on, and provides DHCP addresses and local DNS for both wired and wireless clients. Port forwarding is a bit tricky: it requires forwarding from the Actiontec to the Linksys, and then from the Linksys to the end computer. Surprisingly, it works fine. Also, I had to turn off the Linksys's DDNS update feature, since it was publishing the non-routable IP address that the Actiontec gave it.


Comments (0)


Simple Linux backup solution

My desktop computer, which runs Gentoo Linux, has a 120 GB drive (used for my / and /boot and swap partitions) and a 480 GB drive (used for /home).  I decided to add another drive for backups.  Ended up with a 720 GB drive, which is bigger than the others combined with room to spare, and only cost me about $100.

(Backing up to another hard drive on the same box is easy, and fast, and protects from a single drive failing, but does not protect against the computer being stolen or the house burning down.  So I still need to push really important stuff, like source code, offsite.)

I mount the new drive as /mnt/backup.  I use rsync to backup everything, minus a few excluded directories, to /mnt/backup/{TIMESTAMP}.  I tell rsync to use hard links when a file is the same as the file in the previous backup.  That way I have a full backup tree per day, but the incremental hard disk space used is only equivalent to the size of the files that actually changed that day.

I control the backup with this Python script (sh or perl would work too, but I like Python), which lives at /usr/local/bin/


"""Backup most of a filesystem to a backup disk, using rsync."""

import subprocess
import time
import os

SOURCE = "/"
DESTINATION = "/mnt/backup"
RSYNC = "/usr/bin/rsync"

def find_latest_destdir():
    latest = 0
    for fn in os.listdir(DESTINATION):
        if fn.isdigit() and len(fn) == 14:
            timestamp = int(fn)
            latest = max(timestamp, latest)
    if latest:
        return str(latest)
    return None

def main():
    cmd = [RSYNC]
    for exclude in EXCLUDES:
        cmd.append("--exclude=%s" % exclude)
    latest = find_latest_destdir()
    if latest:
        cmd.append("--link-dest=%s" % (os.path.join(DESTINATION, latest)))
    timestamp = time.strftime("%Y%m%d%H%M%S")
    cmd.append(os.path.join(DESTINATION, timestamp))
    print cmd
    returncode =

if __name__ == "__main__":

And here's the crontab line that runs it every night at 3 a.m, added with "sudo crontab -e":

0 3  * * *      /usr/local/bin/

Automated nightly backups are now so easy (thanks to tools like rsync, and the cheapness of hard drives) that there's really no excuse not to do them.


Comments (0)


Installing goocanvas on RHEL 5

We have some code at work that uses the old GnomeCanvas. I wanted to update it to a Cairo-using canvas to get antialiasing and better font scaling. Looked at CrCanvas, FooCanvas, GooCanvas, and HippoCanvas. Decided to use GooCanvas, based on docs and examples and Python bindings and license.

Unfortunately, the latest GooCanvas (0.10) wants Cairo 1.4, and Red Hat Enterprise 5 (which we have to use at work) is stuck at Cairo 1.2, and half of the Gnome stack seems to depend on Cairo.

The solution was pretty simple: use GooCanvas 0.9. Feels weird to deliberately install an old version of something, but when you're running Red Hat, sometimes you just have to pretend it's still 2006.

After a few hours of working with GooCanvas (from Python), I'm pretty happy with it. The install went well except that it put the Python libraries in /usr/local/lib/python2.4 instead of /usr/lib/python2.4 by default. I got a bit confused by SvgSurface (which is for output not input), but ended up using an SVG example that comes with 0.10 to make a custom SVG-based component. (The alternative was converting SVGs to PNGs on startup and then every time the scale was changed, which would have worked but seemed a bit gross.)

I see that gtkmm (C++ bindings for GTK+) is now using Cairo behind the standard GTK DrawingArea widget by default, so you don't need to scrounge up a third-party Cairo canvas. Great idea. I hope it spreads to the other GTK+ bindings.


Comments (0)


Cups stuck in landscape? Try gtklp

My printer (Lexmark Optra 312L, hanging off a Gentoo box's parallel port) had been stuck in landscape mode for a while. I couldn't find anyplace in the cups web GUI to fix this. Someone on the Gentoo forums recommend backing up then nuking /etc/cups, uninstalling then reinstalling cups, and reconfiguring the printer. That didn't work either.

Then I found gtklp. It's a little gtk app with the Tabbed Dialog From Hell interface. One of the 9 tabs is labeled Output. The Output tab has a portrait / landscape selector. Switched to portrait, hit save, and now the printer is back in portrait mode.


Comments (0)


SLOC counts for various version control systems

At work I'm currently using Git and Subversion and Mercurial for version control. Other people there are using Bazaar and CVS. Too many programs to learn! We need to eventually standardize on a primary third-generation distributed tool to replace Subversion, but it hasn't happened yet.

There are lots of opinions on which third-generation distributed version control system should replace Subversion. (I like Mercurial a lot, respect Git's power despite its ridiculous learning curve, and haven't used Bazaar enough to have a strong opinion about it, except that it used to be unusably slow.)

Here's one data point you won't see in all the comparisons: code size as measured by sloccount:

Name Version SLOC
CVS 1.12.12 136,873
Subversion 1.4.6 492,564
Mercurial 0.9.5 40,682
Git 1.5.4rc1 142,669
Bzr 1.1 125,637

Why is Subversion more than triple the size of any of its main competitors? C, two backends, language bindings, separate libraries for client and server, Apache / Webdav integration, separate admin tool, yadda yadda yadda. Do you really need all that?

Why is Mercurial less than a third the size of any of its main competitors? It's in Python, and there's definitely an aversion to feature creep, to the point where lots of features that would be core in other programs are extensions in Mercurial. (Note that the extensions that are bundled with the project are included in its SLOC number, while the ones you'd need to download separately are not.) What else? It is missing some features compared to, say, Git, but it's sure not missing two-thirds of them. Why is Bzr, which is also written in Python and has a roughly comparable feature set, three times as big?

How important is lean code? What features can the Mercurial team implement by the time Subversion merge tracking is done and stable? Is there actually anyone who can name all 143 programs that git put in my /usr/bin/ directory?


Comments (0)