Chris Adams

The bash exec function has an underutilized feature allowing you to redirect stdin or stderr for the entire script, avoiding the need to make sure that the user always runs myscript.sh > output.log:

exec > example.`date +%Y-%m-%d`.log

Unfortunately, when the documentation says "If FILE is not specified, the redirections take effect in this shell" there's a key omission: you can't simply use a normal pipe to have your output go to mail, logger, etc. or in non-interactive environments like grid / batch schedulers which don't allow you to specify a pipe for job output.

Googling won't turn up much useful other than some hacks which redirect to a temporary file/pipe or re-exec the script and I wanted something cleaner. The solution is to use the bash process substitution feature which allows you to create a file handle for a given command and use that where you might normally use a filename. This is normally demoed for cool input hacks such as diff-ing the output of two commands but it's also useful for our purposes:

#!/bin/bash
exec > >(mail -s "$0: normal job output" user@example.edu)
exec 2> >(mail -s "$0: error job output" syadmin@example.edu)

... commands which will be executed normally ...

Here's a simple example of how to use the Python ctypes module to load the Security framework on OS X and use it to delete an item from the keychain: keychain-delete.py

Inspired by a talk, I'm getting around to posting a script I've been using for a bit over a year to track down locking performance issues on OS X, particularly with network filesystems:

#!/usr/sbin/dtrace -s
/*
  Traces system locking activity and attempts to print the process and filename for each lock request

  Accounts for locks resulting from the following calls:
  flock()
  fcntl(SETLK|SETLKW)
  open(..., O_SHLOCK|O_EXLOCK)
*/

#pragma D option quiet

BEGIN {
  start = timestamp;
}

ERROR {
  printf("dtrace error in %s[%d] error on probe ID %d action #%d at DIF offset %d: %d : %x\n", execname, pid, arg1, arg2, arg3, arg4, arg5)
}

syscall::flock:entry
/ (arg1 & 1) || (arg1 & 2) /
{
  @locks[execname, pid, probefunc, arg1 & 1 ? "LOCK_SH" : "LOCK_EX", fds[arg0].fi_pathname ] = count();
} 

syscall::fcntl:entry
/ (arg1 == 8) || (arg1 == 9)/
{
  /* F_SETLK / F_SETLKW */
  @locks[execname, pid, probefunc, arg1 == 8 ? "F_SETLK" : "F_SETLKW", fds[arg0].fi_pathname ] = count();
} 

syscall::open:entry
/ (arg1 & O_SHLOCK) || (arg1 & O_EXLOCK) /
{
  self->locktype = arg1
} 

syscall::open:return
/ arg0 >= 0 /
{
  @locks[execname, pid, probefunc, self->locktype & O_SHLOCK ? "O_SHLOCK" : "O_EXLOCK", fds[arg0].fi_pathname ] = count();
}

tick-$1 {
  normalize(@locks, (timestamp - start) / 1000000000);
  printa("%16s[%u]\t%8s %8s %s\n", @locks);
  trunc(@locks);
  printf("----- %Y\n", walltimestamp);
}

If you spend a lot of time working on public networks or are worried about an unethical ISP injecting ads into your web pages, here's an easy way to keep your traffic intact and a bit more secure. OpenSSH has a handy DynamicProxy mode which allows it to provide a local SOCKS proxy: enable it and your traffic will be secure until it leaves your remote server. Besides thwarting a malicious network this is also a handy way to access intranet pages or things like scientific journals which restrict access to work/campus network addresses.

The only drawback to using this is that it requires you to keep an ssh session open all the time - this is where launchd and OS X 10.5's built-in SSH agent support come in handy. Once you've setup public-key authentication you won't be prompted each time it restarts, so there are only two steps for seamless remote working:

  1. Add this to your ~/.ssh/config file to enable keepalives, ensuring that ssh will be restarted quickly when your system resumes from sleep:
    TCPKeepAlive yes
    ServerAliveInterval 30
    
  2. Create a Launch Agent by storing this in ~/Library/LaunchAgents/org.openssh.dynamic-proxy.plist:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>KeepAlive</key>
        <true/>
        <key>Label</key>
        <string>org.openssh.dynamic-proxy</string>
        <key>LimitLoadToSessionType</key>
        <string>Aqua</string>
        <key>OnDemand</key>
        <false/>
        <key>ProgramArguments</key>
        <array>
            <string>/usr/bin/ssh</string>
            <string>-D1080</string>
            <string>-Nn</string>
            <string>-n</string>
            <string>-C</string>
            <string>shell.example.org</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
    </dict>
    </plist>
    
  3. Tell launchd to load the agent (it will keep it loaded in the future):
    launchctl load -w -S Aqua ~/Library/LaunchAgents/org.openssh.dynamic-proxy.plist
  4. Open the advanced section of your network preferences and enable a SOCKS proxy using 127.0.0.1 port 1080: 2512311692_4cbed5a480.jpg?v=1211401576
  5. If you use Firefox, you'll need to configure it to use the SOCKS proxy as it doesn't use the system settings.
  6. Visit whatismyip.com to confirm that your traffic appears to originate from your remote server's address

If you use the standard Python logging library, the syslog handler doesn't work by default on OS X 10.5. The problem is that SyslogHandler assumes that it can send to localhost:514. In 10.5 Apple disabled network syslog by default, which is a good security measure but it means that previously working code will no longer work (rdar://5871746). The solution is simple - if you used to do logging.handlers.SysLogHandler(address) you now need something like this:

if sys.platform == "darwin":
	# Apple made 10.5 more secure by disabling network syslog:
	address = "/var/run/syslog"
else:
	address = ('localhost', 514)
				
syslog = logging.handlers.SysLogHandler(address)
2008-4-17 08:16

A great example of how bad customer service works: Comcast cut David Winer's service for exceeding a secret transfer limit. He calls and is immediately confronted with a hostile legal department convinced that customers should pay for service they're not allowed to use. Hilarity ensues.

The interesting question: will it be too late by the time the cable companies realize they don't have a monopoly any more? Bandwidth already has competition and now more and enough companies are starting to offer their content on iTunes, Hulu, etc. that the cable company's $60/mo is starting to look rather excessive…

2008-4-11 09:11

Finally, a blog-meme I can related to. Here's what I do all day at home and at work - numbers which I'm sure have changed dramatically since I started living in TextMate a few years ago:

chris@home:~ $ history|awk '{print $2}'|sort|uniq -c|sort -rn|head
 166 python
  52 ls
  47 cd
  37 ssh
  34 svn
  16 pydoc
  16 mv
  16 essh
  15 vim
  12 cat
cadams@work:~ $ history|awk '{print $2}'|sort|uniq -c|sort -rn|head
 93 sudo
 56 ls
 53 cat
 42 man
 41 cd
 25 svn
 16 vim
 14 grep
  9 top
  8 rm

For years the tech press has denigrated Apple users as being shallow flash-seekers. This is an amusing bit of projection given the key role they play in the hype-cycle, selling shiny-but-useless crap to anyone unfortunate enough to trust them. It's getting a bit annoying watching yet another repetition of the "iPhone killer" article which completely misses why the iPhone was successful. Here's Gizmodo breathlessly hyping the Samsung Instinct (“At Last, a Decent iPhone Competitor”):

Samsung's Instinct may be the best stab at the coveted title of iPhone killah this CTIA. The 3.1-inch touchscreen phone has localized haptic feedback, plus three hard navigation keys. … The Instinct rocks EV-DO Rev A and GPS, in both cases besting what's in the fruit phone. And then content and app wise, Sprint's own wares are basically swapped in for Apple's. … On top of that, its customizable homescreen is amazing

Here's Gizmodo on the Instinct today pointing out that this is the kind of flash-without-substance everyone likes to accuse Apple of selling:

The iPhone-challenging visual voicemail, for instance, ain't quite live. Plus, it locked up when I was messing around with the music store, and needed a hard reset for the more money shot voice command features, which still didn't quite work (or finding a McDonald's is just too much). And the web browser doesn't, um, touch mobile Safari, at least not in its present state.

The thing which almost always gets ignored by tech writers is that iPhone has never been popular with people like the Gizmodo writers because it basically has one new feature (the multitouch interface); it otherwise ignominiously loses a feature–matrix comparison: no 3g, small screen, poor battery life, restricted bluetooth, no MMS, no third-party apps, no flash cards, etc. Everything on the feature list has been done for years by cheaper, less restricted competitors. Logically, this means that the iPhone sucks and the people buying it are brain-washed fashionistas, right?

The catch, of course, is that feature matrixes only matter to marketing people and tech journalists who want to become marketing people. Everyone else tends to care more about how well a few basic features actually work - and that's where the iPhone shines, just as with the similarly disparaged iPod before it:

I've been cell-phone only since 1999 or so and I've used a fair number of phones during that period. The iPhone is the first phone I've had which can honestly claim to have a usable web browser. It's also the first one other than the Palm devices to have an address book or calendar which are usable with more than a dozen entries. It's the first one which lets me dial my fiancé with less than a dozen clicks. It's the first phone I haven't needed to reset because it locked up or got unusably slow.

Note how 3G didn't enter into the picture? It's not really necessary, any more than broadband was a prerequisite for the Internet to enter mainstream life. The trick was that Apple actually paid attention to usability and wrote software which does things like transferring email in the background so you don't have to wait - an advanced 1980s technique which could save Motorola if they copy it quickly (the SLVR my iPhone replaced couldn't scroll text anywhere near as fast as my old PC XT).

Update:Here's another example from The Inquirer:

The Instinct was partly designed by Sprint based on Java software and will have features that the iPhone lacks such as the ability to use EV-DO Rev A, the fastest cellular broadband technology available on the Sprint and Verizon Wireless networks.


This will make it a lot faster than the Iphone. It will also be smaller and feature a GPS chip

In theory, many phones are faster than the iPhone. In practice, the network engineers' hard work has been squandered by the poorly designed browsers shipped on just about everything else. The Instinct may avoid this trend but it's likely it will be yet another 3G phone which is slower than the iPhone if you browse on the phone but faster if you tether it to a laptop and use a real browser. This, incidentally, is another example of another over-emphasized iPhone critique: you can't tether a laptop but I've never needed to, either. A few hardcore road-warriors would need a 3G card but most people can find a WiFi hotspot if they need more than web+email.

Older Entries