Monday, July 27, 2009

Linux Google Chrome, the Alpha Version

I've been trying out the Linux alpha of Google Chrome. I started on Monday, June 8 09:40:37 MDT 2009 with version 3.0.183.1 . A month and a half later, it's at 3.0.195.1 . I haven't had any crashes. That's not bad.

I'm trying to switch to it, not because I'm unhappy with Firefox, but because it's the only way I ever learn new stuff -- by forcing myself to use it.

Sunday, July 26, 2009

What's this Colon Doing in My Comments?

Shell comments start with '#' -- except when they start with ':'.

Before 1981, they all started with ':', and they weren't really comments, they were commands. They still are.

$ type :
: is a shell builtin
':' is a no-op. Like true, it's a command that always succeeds, and does nothing.

Since it doesn't do anything, you can give it whatever arguments you want.

: This is a command that does nothing. And, a comment.
With one wrinkle: since it's a command, the shell processes its arguments. Side-effects? You bet.

Here's a surprisingly common idiom in shell scripts. (Look through the /etc/ directory for these.)

: ${FOO:=bar}
Huh? Okay, step at a time:

  1. $FOO is the value of the variable FOO.
  2. ${FOO:-bar} has the value $FOO, unless FOO doesn't have a value. If FOO is unset or null, then the value of this typographic mess is the string, "bar".
  3. ${FOO:=bar} is like that, but it also assigns FOO the value bar as a side-effect if it didn't already have a value.
  4. So this command

: ${FOO:=bar}

sets FOO to the default value "bar", if it hasn't already been set to something else. And then, it goes on to the next line in the script, because the command itself is a no-op.

The entire purpose of that null command is the side-effect produced when the shell evaluates its arguments -- it announces a default value for $FOO.

More verbose ways to say this include these:

$ FOO=${FOO:-bar}
or

$ [ "$FOO" ] || FOO=bar
or even

$ if [ "$FOO" = "" ]; then FOO=bar; fi
But if you want to understand the scripts in the /etc/ directory, you need to at least recognize:

${FOO:=bar}
and not be intimidated by it.

Plus, knowing this lets you make sense of shell scripts that are more than 29 years old. Since this is the 40th anniversary of Unix, that seems fitting.

Saturday, July 25, 2009

File Access Times as Debugging Tools

"Is that configuration file actually being read? I'm sure I changed it. Maybe I'm just not reading the data file I think I am."

"Is my command actually being executed? Is my initialization script getting executed first?"

I use the Linux "file access time" as a debugging tool.

If you want to know the last time a file was written, ls -l tells you the time. You knew that.

If you want to know the last time a file was read (or was run, if it's an executable), ls -ul tells you the time. Maybe you didn't know that.

Or the last time a particular app is getting invoked. The access time tells you when an executable was run because Linux has to read it to execute it.

Or, at least, it used to work this way. Newer Linux systems no longer do, but you can still get the information you need. I'll show you how.

On newer systems, the access time (the time ls -ul reports) is the last time a file was read after the last time it changed. You can get the same information, it just takes a little more setup work. Here's a script that shows how:

#!/bin/bash -x

PS4='$(date +%H:%M) $ '
: == Create a file at a well-defined time.
rm -f /tmp/foo
touch /tmp/foo
: == File write and access times are the same.
ls -l /tmp/foo; ls -ul /tmp/foo
: == Sleep, so the time changes, and read the file
sleep 60; cat /tmp/foo
: == The access time is now later than the write time.
ls -l /tmp/foo; ls -ul /tmp/foo
: == Do it again.
sleep 60; cat /tmp/foo
: == The access time DOES NOT change, because There was no intervening write.
ls -l /tmp/foo; ls -ul /tmp/foo
: == Now "write" the file.
touch /tmp/foo
: == Sleep so the time changes, and read it.
sleep 60; cat /tmp/foo
: == This time, the time does change.
ls -l /tmp/foo; ls -ul /tmp/foo
The meaning of access time was changed as an efficiency hack, so that inodes aren't re-written as often.

In the script, I'm using ':' as a comment character. I should explain why, but I'll leave that as a separate post. Or, you could run the script to see. :-)

Thursday, July 2, 2009

Using Preferred Applications from the CLI

I can use a command-line interface to invoke (not just "set," but "invoke") my GUI preferences.

System-> Preferences -> Preferred Applications lets me set things like my preferred email application and preferred browser. Works fine in the GUI, but how about from the command line?

The solution is XDG tools, from the Portland Project. Browse a url or edit a file?
xdg-open https://google.com
xdg-open /tmp/foo.txt
Email?
xdg-email