Why does that QR Code go to justinsomnia.org?

Back in 2007 I stumbled something called a QR Code. It was a neat two-dimensional barcode that encodes textual information visually—with URLs being a promising application for the emerging smartphone market (thanks to the release of the iPhone that year). So I did what any self-respecting personal blogger would do: I QR-encoded my own URL. And posted it to my blog.

QR-Code for http://justinsomnia.org/

At some point between then and now, my QR code image got lodged in the second position of Google Images’ search results for “qr code”. As a result, it became one of the most requested pages on my site, regularly clocking in several hundred requests a day. But what happened next defies rationale explanation.

Google Images results page for 'qr code' highlighting a result that points to justinsomnia.org
Google Images results, with my QR Code highlighted

Graph of monthly requests for http://justinsomnia.org/2007/12/qr-code/ from December 2007 to February 2011
Monthly requests for QR Code from Dec 2007 to Feb 2011

Continue reading…

How to update your blog from the middle of the ocean

We are currently at 15°14’54.77″N 75°15’12.63″W, somewhere between Jamaica and Colombia, en route to Cartagena, Colombia. We should be arriving there tomorrow afternoon. I am posting this (and anything else that begins with GPS coordinates) using a Wideye Sabre 1 BGAN Terminal (or in layman’s terms: a satellite modem).

When we started planning this trip, I had resigned myself to a month without access to the internet. It sounded like a badge of courage when people asked me, “So, does the container ship have wireless?” and I answered: “Nope.” The last time I didn’t have access to the internet for 28 days straight was probably before I had access to the internet at all.

I’ll admit, I am weak. I did some cursory looking into satellite phones, Iridium and such. But they were just blindingly expensive. And I didn’t want to make calls, I just wanted an IP address! Eventually I stumbled upon Inmarsat’s BGAN, which stands for Broadband Global Area Network. Unlike the various satellite phone options, many of which only guaranteed coverage on land, BGAN covers the whole planet, continents and oceans, with the exception of the poles. It was almost too good to be true.

Inmarsat BGAN satellite coverage map
Inmarsat BGAN satellite coverage map

Continue reading…

Ubuntu on a Lenovo ThinkPad X100e

Stephanie’s brand new ThinkPad X100e arrived today, so I got to have some fun tonight and set up Ubuntu on it for her.

Lenovo ThinkPad X100e

Installation via memory key

This was the first time I’d installed Ubuntu via memory key. Means I might not need my portable CD-ROM drive anymore…

  1. Downloaded the latest Ubuntu AMD64 Desktop ISO using BitTorrent
  2. Ran usb-creator to copy the ISO to my 2GB USB memory key (based on these instructions: Installation From USB Stick)
  3. Got the “DBus error” like the instructions anticipated, so ran the following command to format my memory key:
    sudo mkfs -t vfat /dev/sdb1
  4. Then I reran usb-creator
  5. Plugged the memory key into the X100e, booted it up, and installed Ubuntu

Getting wireless to work

Of course, bane of Linux, wireless didn’t work out of the box. This tends to be expected with brand new hardware, and it took me a while to piece together the right steps to get it working.

  1. Basically run exactly these commands (even sudo su):
    sudo apt-get install build-essential
    wget http://launchpadlibrarian.net/34090404/rtl8192se_linux_2.6.0010.1012.2009_64bit.tar.gz
    sudo tar -xvzf rtl8192se_linux_2.6.0010.1012.2009_64bit.tar.gz
    cd rtl8192se_linux_2.6.0010.1020.2009_64bit
    sudo su
    make
    make install
  2. Then reboot and you have wireless

Note: If you run the Update Manager and it contains a new Linux kernel, you’ll need to rerun make install in ~/rtl8192se_linux_2.6.0010.1020.2009_64bit to reinstall the wireless drivers. So don’t get rid of the rtl8192se… directory. Hopefully this will cease to be a problem in the next release of Ubuntu.

Getting the TrackPoint scroll button to work

Apparently xorg.conf is a thing of the past, which kind of obsoletes my previous TrackPoint “scroll button” instructions. Oh well. This is how you do it now.

  1. Install and run gpointing-device-settings
    sudo apt-get install gpointing-device-settings
    gpointing-device-settings
  2. Select TPPS/2 IBM TrackPoint on the left
  3. Check “Use wheel emulation”
  4. Select button #2

Getting the headphone jack to work

I didn’t realize this was a problem at first, but thanks to all the comments, folks got to the bottom of the issue. This is what worked for me.

  1. Edit /etc/modprobe.d/alsa-base.conf
    sudo gedit /etc/modprobe.d/alsa-base.conf
  2. Add the following two lines at the end of the file:
    options snd-hda-intel model=lenovo-101e
    options snd-hda-intel position_fix=1 enable=yes
  3. Restart the computer

Ubuntu crashing randomly? Run Memtest86+!

Shortly after I upgraded Stephanie’s desktop computer to Ubuntu’s Intrepid Ibex (8.10), it started acting up. Most noticeably when she scrolled Google Maps or Firefox too quickly, the display would get all garbled. I figured something in the upgrade broke support for her video card, but it happened infrequently enough that she just ignored it.

Then she started having problems where programs would just randomly crash. The symptoms were always kind of funky, like if Firefox crashed (not unusual with Flash video everywhere), we’d try to open up the System Monitor—but even that wouldn’t open. It would act like it was going to open, but then nothing would happen. Later on, I discovered that the program was segfaulting when we tried to open it:

Feb  8 21:29:55 soleil kernel: [ 4439.299147] gedit[5829]: segfault at 18 ip b70f8408 sp 00000000 error 6 in libpcre.so.3.12.1[b70e7000+28000]
Feb  8 21:30:17 soleil kernel: [ 4461.417410] gedit[7173]: segfault at bf645f9c ip b704834d sp bfa45e00 error 4 in libpcre.so.3.12.1[b7036000+28000]
Feb  8 21:30:37 soleil kernel: [ 4481.458719] gnome-system-mo[7180]: segfault at 18 ip b6c6a408 sp 00000000 error 6 in libpcre.so.3.12.1[b6c59000+28000]
Feb  8 21:30:56 soleil kernel: [ 4500.786623] gnome-system-mo[7190]: segfault at 18 ip b6c3d408 sp 00000000 error 6 in libpcre.so.3.12.1[b6c2c000+28000]
Feb  8 21:31:27 soleil kernel: [ 4531.479833] gnome-system-mo[7225]: segfault at 18 ip b6bfd408 sp 00000000 error 6 in libpcre.so.3.12.1[b6bec000+28000]
Feb  8 21:32:13 soleil kernel: [ 4577.436491] gnome-system-mo[7243]: segfault at 18 ip b6c20408 sp 00000000 error 6 in libpcre.so.3.12.1[b6c0f000+28000]

It started getting so bad that all of Gnome would crash after a while, dropping down to text-only screen of various kernel diagnostic and error info. And I honestly had no clue what was going on. So I started Googling around the other weekend, and I stumbled upon this aptly named Ubuntu support page, Debugging System Crash. The very first line said:

If your system crashes at random intervals, perform a MemoryTest first before filing any bug reports or support requests

The MemoryTest page explained how to run Memtest86+. So I did that. When GRUB started loading, I pressed Esc:

Grub loading screenshot

And then I selected memtest86+:

Selecting memtest86+ screenshot

At first it looked normal:

memtest86+ running

AND THEN it started barfing out all these red errors!

memtest86+ barfing out tons of errors

The errors started accumulating so fast they were just a blur:

memtest86+ accumulating a blur of errors

The verdict seemed clear. In all my history of computer ownership I’ve never witnessed memory go bad—until now. So we ordered 2 gigs of shiny new memory (only $28!), which arrived tonight, I installed, and now she’s back in business.

fancy DDR2 memory

Random Custom Fields

The latest version is 1.0, released February 24, 2009, compatible with WordPress v2.7 (and probably 2.6)

WordPress logoThis is an esoteric WordPress plugin (and widget) that will randomly extract one or more custom fields from your posts and display them in a format of your choosing.

For example if you’ve stored geographic coordinates (longitude and latitude) for your posts in a custom field, you can use this plugin to randomly generate a link to Google Maps. Perhaps you could even generate a random embedded Google Map centered on that spot. I know that some people use Custom Fields to store images with special meanings. They could use this plugin to randomly display an image linking back to the post it came from, similar to my Random Image Plugin.

As always, please let me know if you have any problems or questions. I’m happy to help.

Screenshot

This is not a sexy plugin, but it just might save the day. Here’s a screenshot of the admin interface.

Random Custom Fields screenshot

Instructions

  1. Download and unzip random-custom-fields-1.0.zip (v1.0)
  2. Upload the file random-custom-fields.php to your plugins directory:
    /path/to/wordpress/wp-content/plugins
  3. Activate the plugin (don’t forget!)
  4. If your theme is widget-enabled, goto Design > Widgets and add “Random Custom Fields” to your sidebar
  5. If your theme is not widget-enabled, edit the index.php or sidebar.php template file in your theme’s directory:
    /path/to/wordpress/wp-content/themes/name-of-theme
    and add the following line of code where you want a random custom fields to appear:
    <?php random_custom_fields(); ?>
  6. Configure the plugin from within WordPress under Settings > Random Custom Fields

Options

The <?php random_custom_fields(); ?> function can take 9 optional parameters in between its parentheses. If you specify any parameters this way, all settings made through the configuration interface will be ignored. Note: this behavior could be useful if you wanted to have several different random custom fields each with different settings appearing throughout your site.

<?php random_custom_fields(custom_field_name,
                           include_posts,
                           include_pages,
                           sort_randomly,
                           count,
                           value_separator,
                           html_template,
                           html_between_templates,
                           category_filter); ?>
  1. custom_field_name is a required string that determines which custom field name to display.
  2. include_posts is a boolean (default is true) that determines whether to pull custom fields from posts.
  3. include_pages is a boolean (default is false) that determines whether to pull custom fields from pages.
  4. sort_randomly is a boolean (default is true) that determines whether to pull custom fields from posts in random order, or in date descending order.
  5. count is an integer (default is 1) that determines how many custom fields to display.
  6. value_separator is a string (default is newline) that allows you to break up the custom field value into multiple pieces for use in the html_template.
  7. html_template is a string (default is %0) that determines how the plugin should display the custom field. There are several variables that the plugin can output by default, including %title, %permalink, and %excerpt, all from post of the custom field. The variable %0 will be replaced with the entire custom field value. If you’ve entered a custom value_separator (default is a newline) the variables %1, %2, %3, etc will be replaced with each piece of the custom field value divided by the value_separator delimiter.
  8. html_between_templates is a string (default is <br /><br />) that gets printed between custom fields if the count parameter is greater than 1.
  9. category_filter is a comma-separated list of category or tag ids (default is blank) that limits the custom fields posts within certain categories or tags.

Ubuntu Home Server FAQ

Basically this is the stuff I can’t remember how to do when I’m setting up Ubuntu as a backup server. Tested with Ubuntu Server 8.04.1 (Hardy Heron).

How do I turn off the dang bell (aka PC speaker beep)?

sudo rmmod pcspkr
sudo vi /etc/modprobe.d/blacklist

Then add:

blacklist pcspkr

How do I make arrow keys work in vi?

sudo apt-get install vim

How do I configure Ubuntu to have a static IP address?

sudo vi /etc/network/interfaces

Then replace:

auto eth0
iface eth0 inet dhcp

with:

auto eth0
iface eth0 inet static
address 192.168.1.100
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
gateway 192.168.1.1

Note: This assumes your router’s (aka gateway’s) IP address is 192.168.1.1 and you want to assign a static IP of 192.168.1.100.

Finally run:

sudo /etc/init.d/networking restart

How do I install an SSH server?

sudo apt-get install openssh-server

How do I find out information about my processor (CPU)?

cat /proc/cpuinfo

How do I find out my external USB drive’s device location?

sudo fdisk -l

How do I manually mount an external USB drive?

sudo mkdir /media/usb0
sudo mount /dev/sdb1 /media/usb0

Note: Your USB drive may have been assigned a different device location than /dev/sdb1. Use sudo fdisk -l to find out.

How do I format an external USB drive?

sudo mkfs.ext3 /dev/sdb1

Note: Be very careful with this command. Make sure you have the correct device location.

Broken blog = man obsessed

Databases are supposed to be these monolithic paragons of correctness and uniformity. So it’s a little unsettling to discover a database that returns grossly incorrect results. At least I wouldn’t expect WordPress to put version 5 of MySQL through its paces.

Here’s the scenario. Dreamhost, my webhost, is running MySQL Server v5.0.24a, released in August 2006. On my laptop I’m running MySQL Server v5.0.51a, released in January 2008. The difference between the two is a year and a half of bugfixes and performance improvements.

On each I’ve got a copy of the same database table, wp_posts, from my WordPress 2.5.1 install for Justinsomnia. And on each system I’ve got a copy of the giant SQL select statement generated by WordPress that returns the first 8 blog posts that should appear on my homepage. The unusual thing about this particular query is that it contains an insanely long NOT IN () list to filter out my neatlinks from the main column.

SELECT SQL_CALC_FOUND_ROWS  wp_posts.*
FROM wp_posts
WHERE 1=1
AND wp_posts.ID NOT IN ('876', '877', '878', '879', '880'...'5456', '5458', '5460', '5461', '5462', '5463')
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish')
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0, 8

The problem is that running the same SQL statement on each server returns different results—and I wanted to figure out why.

So I prefixed the query with EXPLAIN, to see what each version of MySQL would tell me about how they were dealing with the same query. I expected the results to be the same. They turned out to be quite different.

MySQL 5.0.24a:
+----+-------------+----------+-------+--------------------------------------+---------+---------+------+------+----------------------------------------------+
| id | select_type | table    | type  | possible_keys                        | key     | key_len | ref  | rows | Extra                                        |
+----+-------------+----------+-------+--------------------------------------+---------+---------+------+------+----------------------------------------------+
|  1 | SIMPLE      | wp_posts | range | PRIMARY,post_status,type_status_date | PRIMARY | 4       | NULL |  611 | Using where; Using temporary; Using filesort |
+----+-------------+----------+-------+--------------------------------------+---------+---------+------+------+----------------------------------------------+

MySQL 5.0.51a:
+----+-------------+----------+------+--------------------------------------+------------------+---------+-------------+------+-------------+
| id | select_type | table    | type | possible_keys                        | key              | key_len | ref         | rows | Extra       |
+----+-------------+----------+------+--------------------------------------+------------------+---------+-------------+------+-------------+
|  1 | SIMPLE      | wp_posts | ref  | PRIMARY,post_status,type_status_date | type_status_date | 25      | const,const | 5350 | Using where |
+----+-------------+----------+------+--------------------------------------+------------------+---------+-------------+------+-------------+

As you scroll to the right, you can see that v5.0.24a chose the PRIMARY key to find the most recent posts, while v5.0.51a opted for type_status_date. I’m not quite sure what that means, except that v5.0.24a obviously made the wrong choice. Which gave me an idea for an interim solution (while I wait for Dreamhost to upgrade MySQL): index hints.

If I could force MySQL to ignore the PRIMARY key, maybe it would “fix” my blog. So I added IGNORE INDEX (PRIMARY) to the query that selects posts, and voila, my blog homepage started working again! Here’s the diff of the code change I made. Luckily I have WordPress “installed” via Subversion, so any changes I make to core files get carried over with each upgrade.

Index: wp-includes/query.php
===================================================================
--- wp-includes/query.php	(revision 7987)
+++ wp-includes/query.php	(working copy)
@@ -1424,7 +1424,7 @@
 		if ( !empty($limits) )
 			$found_rows = 'SQL_CALC_FOUND_ROWS';

-		$request = " SELECT $found_rows $distinct $fields FROM $wpdb->posts $join WHERE 1=1 $where $groupby $orderby $limits";
+		$request = " SELECT $found_rows $distinct $fields FROM $wpdb->posts IGNORE INDEX (PRIMARY) $join WHERE 1=1 $where $groupby $orderby $limits";
 		$this->request = apply_filters('posts_request', $request);

 		$this->posts = $wpdb->get_results($this->request);

Hopefully I haven’t inadvertently broken some other aspect of my blog. If anyone sees anything out of order, please leave a comment, mmmk?

Update: for Nate, here’s the EXPLAIN on 5.0.24a with the IGNORE INDEX:

+----+-------------+----------+------+------------------------------+------------------+---------+-------------+------+----------------------------------------------+
| id | select_type | table    | type | possible_keys                | key              | key_len | ref         | rows | Extra                                        |
+----+-------------+----------+------+------------------------------+------------------+---------+-------------+------+----------------------------------------------+
|  1 | SIMPLE      | wp_posts | ref  | post_status,type_status_date | type_status_date | 25      | const,const | 5351 | Using where; Using temporary; Using filesort |
+----+-------------+----------+------+------------------------------+------------------+---------+-------------+------+----------------------------------------------+

The WordPress SQL Executioner

WordPress logoIf I had a dime for every time someone said “WordPress Suicide is great, but I only want to delete posts that are more than a year old,” I’d probably have 50¢. Which is about when I start to think about solving the problem with a new plugin.

The programmer/database jockey in me knows the request above is insanely easy. Just start up the MySQL command line client, connect to the WordPress database and fire off the following query:

delete from wp_posts
where post_date < date_sub(curdate(), interval 1 year)

Of course knowing SQL takes experience, but the first barrier for most people is just getting command line access to their WordPress database (especially on shared hosts). I figured if it was easier for the average WordPress user to gain direct access to their database from within the admin interface, it’d be a whole lot easier for me to help them, by giving them custom one-off SQL queries to run. And oh by the way, this would be pretty awesome for the power user.

So that’s what I did, I built a stripped-down PHPMyAdmin in the form of a WordPress plugin. WPMyAdmin if you will, though I opted to call it the WordPress SQL Executioner. Actually it’s more of a web-based version of the mysql command line client. It performs both selects and describes for analysis, and inserts, updates, and alters for modification. In fact you can send it just about any SQL command MySQL accepts. Here’s a screenshot to give you an idea of what I’m talking about:

Screenshot of the WordPress SQL Executioner

Simply enter your SQL query and click “Execute SQL”. If it’s a select, describe, show, or explain, an HTML table will be returned with your results. If it’s any other command that modifies data or structure, you’ll get a message about the number of rows affected. You’ll have one chance to confirm that you want to execute an insert, update, delete, or alter, but after that, your fate is in your own hands.

The tables listed above the SQL box are shortcut references to all the tables in your database. This makes it possible to write a generic SQL query with variables in place of the actual table names so that it’ll work on any WordPress install, regardless of the table prefix (it’s usually wp_). Of course the actual table names with prefixes are accepted. For example, the query above could be rewritten as:

delete from $posts
where post_date < date_sub(curdate(), interval 1 year)

Finally one handy bonus feature, if you click on any of the table names in the list, it will automatically describe the table for you.

Instructions

  1. Download wp-sql-executioner-1.0.zip (v1.0)
  2. Unzip the file and upload wp-sql-executioner.php to your plugins directory:
    /path/to/wordpress/wp-content/plugins
  3. Activate the plugin (don’t forget!)
  4. Goto Manage > SQL Executioner and have fun!

As always, questions, comments, and suggestions are always welcome.

Continue reading...

monthchunks

license

Justinsomnia is licensed under a Creative Commons Attribution 3.0 License.

Please see my Attribution Policy for more information.