July 21, 2007

Non-cooked mode input problems with piping over SSH

Posted in Coding, input redirection, Linux, Software, ssh at 8:46 pm by mj

Thought I’d share this, since what I thought was a 2-hour Saturday early morning side project went horribly awry.

Consider this Perl code snippet:

use Term::ReadKey;

ReadMode('cbreak');
while (1) {
    my $key = ReadKey(-1);
    if (defined($key)) {
        print "Got key $key\\n";
        last; 
   }
}
ReadMode('normal');

Simple enough: it does nothing until you press a key. This idiom might be used, for example, with non-blocking reads while you’re processing another file, as below:

use Term::ReadKey;
use IO::Select;

my $handle = IO::File->new("tail -f /some/file |");
my $selectable = IO::Select->new();
$selectable->add($handle);

my ($tailCommandPid) = getChildPids();

ReadMode('cbreak');
while (1) {
    my $key = ReadKey(-1);
    if (defined($key)) {
        print "Got key $key\\n";
        last; 
    }
    my @ready = $selectable->can_read(1);
    foreach my $h (@ready) {
        my $line = <$h>;
        print $line if defined($line);
    }
}
ReadMode('normal');
$selectable->remove($handle);
kill 9, $tailCommandPid;
$handle->close();

This also works. It continually echoes the lines it reads, until you press a key.

But what if you want to read the lines from a remote shell? Can we replace the line

my $handle = IO::File->new("tail -f /some/file |");

with

my $handle = IO::File->new("ssh someServer tail -f /some/file |");

and be on our merry way?

Well, no. In this case, your input on STDIN is completely ignored, unless you switch back to plain-old cooked mode.

Or is it really ignored? Maybe ssh is using your input for its own nefarious purposes. Makes perfect sense if your program is but a mediary between your user and an interactive remote shell.

Turns out, ssh accepts -f as an argument to force it into the background. Will that work?

my $handle = IO::File->new("ssh -f someServer tail -f /some/file |");

Success! But now we’re killing the wrong process at the end.

By forcing itself into the background, ssh is really daemonizing itself: its parent PID (on Linux) is 1. Your program will exit, but you’ll leave ssh happily running in the background, unless you result to less-than-safe tricks with ps and grep.

Further down in the man page, however, and we find the trick: -n keeps ssh running as a normal child process, but does not read from STDIN:

my $handle = IO::File->new("ssh -n someServer tail -f /some/file |");

And this, my friends, is a mistake I will never make again. And neither will you.

June 10, 2007

Back on Fedora

Posted in Life, Linux, Me at 11:45 am by mj

I’m kicking myself for not thinking of this earlier–fastboot!. This allows me to boot my old FC6 system, which allows me to be productive and hold off on configuring a new system (I’ve concluded Kubuntu is just broken, too many things didn’t work for me). I don’t get to take advantage of the new 64-bit system, but I can get some work done. Which is more important?

On the off-chance somebody else may find themselves in a similar position someday, searching Google or Technorati for an answer at 4AM, here’s essentially what I did to get up (granted, I took the scenic route). Remember, on the system with the fried motherboard, I have an old IDE primary HDD, but the new system only boots SATA. I also bought my new PowerEdge with 2x160GB SATA drives (“for free” if you believe Dell’s special offers). This means:

  • Disk A. Old primary IDE HDD, with working system and no dependencies on secondary drives.
  • Disk B. New primary SATA HDD.
  • Disk C. New secondary SATA HDD.

If I only had a single new primary SATA HDD, I probably would have bought a cheap IDE-to-SATA adapter from Fry’s to see if the new system would boot it that way. But I try to avoid Fry’s if I can, especially the one in Milpitas.

Step 1. Install new Linux distro on Disk B. Doesn’t really matter which distro at this point, since you’re not going to use it.

Step 2. Copy an image of Disk A onto Disk C. Be sure to connect disk A before booting. In my case, it meant disconnecting the CD-ROM and sitting the old drive on top of the case. Your command might look like this:

$ dd if=/dev/sda of=/dev/sdc

This will, undoubtedly, take a while (I got 18.1MB/s for 80GB data–for a total of 74 minutes). It doesn’t matter if disk A is smaller than disk C.

As above, an IDE-to-SATA adapter might have worked. But this way, whatever happens to your data as you’re messing with it (including the remote possibility of a poorly-wired new system that fries all your components), you’re just working off a copy.

Step 3. Reboot. This is the only way I know to get Linux to refresh its view of the volumes on disk C. There may be other ways.

Step 4. fsck your new volumes manually. Just to make sure they’re OK.

$ e2fsck -f -c /dev/sdc1
$ e2fsck -f -c /dev/sdc2

Step 5. Disable init-time fsck. I think the problem with e2fsck failing during init has something to do with moving from IDE to SATA, with the device view switcheroo that entails. Never really figured it out.

$ sudo mkdir /mnt/sdc2
$ sudo mount /dev/sdc2 /mnt/sdc2
$ sudo mv /mnt/sdc2/.autofsck /mnt/sdc2/NO.autofsck
$ sudo touch /mnt/sdc2/fastboot

Step 6. Disable disk B and boot into disk C. In your BIOS, turn off SATA controller 0, or else it’ll never boot disk C.

You should now see the GRUB (or LILO) boot menu from your old system. I tried passing various kernel boot parameters to the system (GRUB allows you to edit the command before booting), but no hint I provided the kernel about the root device or root filesystem prevented the e2fsck failure. Hence, the need for fastboot.

Your experience and results may vary. I’m just excited to be able to get some work done.

June 9, 2007

Frustrated with Kubuntu

Posted in Life, Linux, Me at 4:23 pm by mj

This is just a rant, nothing more.

After my motherboard died, I decided it’s still OK to continue patronizing Dell, and bought their PowerEdge 840 with a “special offer.” And I decided to try out Kubuntu.

This is the first time I’ve run a Debian-based distribution since Debian 1.3.1 in 1997! That was my first Linux distribution, and, aside from the cool package management UI, I was not satisfied with some of its configuration choices. I know the version because I still have the 9 floppies I used at that time.

Debian is also where I learned to pronounce “Linux”–incorrectly! So, I happily went around for a year sounding like a total fool (some would say I’ve sounded like a total fool for the last 30 years, har har). Update: Actually, it was probably the Linux FAQ at li.org with the pronunciation guide for “Linux”.

So far, I am less impressed with Kubuntu than I expected. Sure, it boots fast. But several things that worked out of the box with Fedora, just don’t in Kubuntu.

For example, SCIM/SKIM. I’ve futzed with that for hours, and still no love. Comments on various forums and blogs lead me to believe this is a long-standing problem with Kubuntu/Ubuntu, since everybody’s concluded it just won’t work with KDE. But, that’s patently untrue. FC guides me through a wizard at install, and it works the first time I log in. I’ve spent more time on this than I should. Sure, it’s not a core tool I use–I use it for practicing Chinese and doing a quick sanity check of how well my applications support international input, both of which I could do in Windows–but it’s still irritating.

Also, for some reason, Kubuntu does not install all KDE components. I’m not talking about the games and edutainment, I’m talking about adjusting your monitor resolution. I had to manually install all the KDE components just to do simple configuration tasks. (I do give Kubuntu credit for correctly detecting my widescreen monitor, which I was afraid wouldn’t work given the specs for this on-board video card. Still, I prefer not to run at full resolution because it hurts my eyes.)

Speaking of manual package installation–the whole “desktop” versus “server” downloads for Ubuntu tripped me up. Kubuntu is only the “desktop” option, and there doesn’t appear to be any metapackage that allows me to install all the “server” packages. I’ve tracked down a number of packages–emacs, mysql client, etc., none of which I really consider “server” software–but still have more to install.

I do really love Adept and Synaptic, though. Really slick.

The disheartening thing is all this futzing is in addition to the normal upgrade woes. I’ve grown accustomed to removing the god-awful gcj and so on. That takes an hour or two anyway.

This is really why I try to avoid clean installs, and why I tend to stick with the same distro. Upgrades put you through enough pain, but complete reinstalls make it even worse.

I tried booting my old disk, but the new PowerEdge won’t boot IDE disks, grub won’t even see IDE disks for chain loading, and copying the disk image onto a SATA drive results in a phantom boot-time e2fsck failure (despite manual e2fsck runs working just fine). So much for trying to save time until I can truly spare a few days to configure a new system.

Now I’m starting to remember why I considered never buying from Dell again. That motherboard is the first time I’ve had any computer die on me in 20 years. I wouldn’t even be surprised if it caused a chain reaction, perhaps starting with this 9-year old Pentium II sitting around collecting dust, whose (sentimental) disk contents I still haven’t backed up…

breathe

Looks like I still have a weekend of configuration to do, then a week of quiet meditation, then maybe I can get some real work done.

October 18, 2006

Clearing Linux Filesystem Read Cache?

Posted in Linux, Questions at 8:24 pm by mj

Anybody know how to clear the Linux filesystem read cache? A good answer would be much appreciated.

I have some performance tests that are being adversely affected by the filesystem’s read cache. If it makes any difference, we’re using ext3. I don’t want to disable the cache, simply clear it between tests.

A chance conversation on my walk to BART this evening got me in mind to simply copy my files between each round of tests. This kind of works. My full test data is ~140GB, but I can get by with ~20GB for tests running during the day. It takes a while to copy, but that’s better than nothing.

Luckily, my data set compresses well (5.5:1 @ 1.5GB/m), so it’s possible to blow away even the full set and restore. I haven’t tried that yet – hopefully the cache is doing a simple “has this inode/block changed recently?” test, and copying the same data back over a cached block still invalidates the cache.

That’s how I’d do it. Actually, I’d implement it using IDirectConnectionToMJsBrain to obtain my intent at every stage. But I won’t fault anybody for overlooking this.