Monday, September 29, 2008

Photos: Neon Kross at Release the Bats, Long Beach, CA

Daniel deLeon of Neon Kross Adrian of Neon Kross John of Neon Kross Drummer Jake of Neon Kross

I spent Friday night at Release the Bats, the long-running Death Rock club in Long Beach (at Que Sera, 7th St. at Cherry Ave.) That night's band was Neon Kross, a delightfully retro New Wave / post-punk band "Still Living in the 80s", as their MySpace page puts it. I've seen some of these guys before; Daniel deLeon, the lead vocals, is also in Rezurex, a more psychobilly / deathrock kind of band that I've caught at Bats before. Some of the other band members are in Pins and Needles, which I don't think I've seen.

Anyway, Neon Kross kicked ass, and I'd recommend seeing them. Pretty damn photogenic too.

Catch the rest of the set on Flickr.

Another Apple irritation

Related to my previous complaint about losing sliding Spaces switching occasionally when switching between internal and external displays on a MacBook Pro, here's another one. I sometimes lose Hot Corners too. I have a hot corner set up to enable screen lock. I need this. I haven't found a way short of rebooting to fix it, either. Grr.

Tuesday, September 23, 2008

Little Apple Mail.app hint

Something I just discovered by accident:

If you select some text in an email, and then hit reply, just the text in the email will be quoted in the reply. Nothing else.

That's a great feature!

Monday, September 22, 2008

Photos: Club Xile, Garden Grove, CA, September 18 2008

Clubgoers at Xile Dancers at Club Xile Being dragged

Alana, Richie and I visited Club Xile, the weekly Wednesday night event in Garden Grove, CA. Is this the only weekly Goth/Industrial night in Orange County? Seems to be. We've attended this club before, but a while ago, and it seems to have evolved a bit. A very young crowd; it's 18 and over, and there seems to be a very large number of 18–21s in there. I think they've hit on an under-served market segment.

Sets from the club's resident DJs were high-energy and definitely got the good-sized crowd moving, although I could fault them a little on the originality and variety. I guess they play what works, though. Later sets by guest DJs on this night tended towards harder Industrial and saw fewer dancers, though this might have been due to exhaustion as well; it was warm in there.

Drinks are not cheap, though not Hollywood prices either. The bar seems well-stocked and reasonably quick on the service. Richie's Long Island Iced Tea set him back a ten but was reasonably good by his account.

As well as the main dancefloor, there was a stage near the DJ setup upon which several young women (and a man or two) performed as go-go dancers for much of the night. This seemed to be somewhat amateur and impromptu but encouraged by the club organizers, who referred to them as the "Ladies of Xile". A similar square stage at the back of the dancefloor saw more dancing from the exhibitionist set.

Speaking of exhibitionism, it's easy to photograph here; people want to be looked at, and welcome the attention.

Catch the rest of my set on Flickr.

Software buying habits, before and after switching to a Mac

I started my serious computer use on a Commodore Amiga back in 1989, and over the years purchased a fair number of programs for it, mostly development tools (the assembler DevPac 2, and Lattice C) and word-processing tools (ProText and some other whose name escapes me). I also bought AREXX and a text editor or two, and a bunch of games of course.

I was introduced to UNIX at college, but I don't think I've ever spent a cent on a UNIX program, despite using it heavily - it's all been either free software or provided with the system.

After graduation, working for a mainly Microsoft software house (Sophos) made me a Windows user by default, as it were. I spent money on Windows software only very rarely. Things were either employer-bought or ripped off. I spent money on some games and one or two shareware utilities and that was it.

After switching to a Mac two and a half years ago, I've bought software package after software package. Let's see:


  • MarsEdit, in which I'm writing this
  • Yojimbo
  • OmniFocus
  • Aperture
  • TextMate
  • OmniGraffle Pro
  • SuperDuper
  • Scrivener
  • Acrobat 8 Professional


… and possibly a few more. A couple of these have been with my employer's money, but most have been out of my own pocket.

What this says to me is that I feel at home in this environment as I did on the Amiga way-back-when, and that the Macintosh and Mac developers are producing products that I am pleased to pay for and support. Programs I actually enjoy using, not just tolerate.

I have a feeling a lot of us are doing the same.

Tuesday, September 16, 2008

Start a MySQL instance on a snapshot

OK, so we have snapshotted past instances of the data filesystem. That's useful to wholly restore a damaged file. What if, however, one only needs a small bit of that data, or wants to simply see what's changed since the snapshot on a table, or wants to run a mysqldump?

This code creates a ZFS cloned filesystem from the snapshot using zfs clone. A ZFS clone is a writable filesystem created from a snapshot. ZFS's copy-on-write semantics mean that data is only taken up by that data which was changed from within the clone.

It then creates a MySQL configuration in /tmp, including a my.cnf and other stuff, and starts up a MySQL instance using those and the cloned filesystem.


#!/bin/sh

SNAPGROUP=$1
SNAPNUM=$2
if [ -z "$SNAPNUM" ]; then
SNAPNUM=`date +%H`
fi

echo "Starting MySQL snapshot for $SNAPGROUP-$SNAPNUM"

BASEDIR=/var/local/mysql/default
BINDIR=$BASEDIR/bin
DATADIR=/mysql/data/4.1.12/$SNAPGROUP-$SNAPNUM/var
LOGDIR=/tmp/mysql-logs-$SNAPGROUP-$SNAPNUM
if [ $SNAPGROUP = "hour" ] ; then
PORT=34$SNAPNUM
else
PORT=35$SNAPNUM
fi
SOCKET=/tmp/mysqld-backup-$SNAPGROUP-$SNAPNUM.sock
PIDFILE=/tmp/mysqld-backup-$SNAPGROUP-$SNAPNUM.pid

# Create clone FS to run MySQL
zfs clone mysql/data/4.1.12@$SNAPGROUP.$SNAPNUM mysql/data/4.1.12/$SNAPGROUP-$SNAPNUM

# Make directory for logs
if [ -d $LOGDIR ] ; then
rm -rf $LOGDIR
fi
mkdir $LOGDIR
chmod 777 $LOGDIR

# Generate my.cnf with correct info
/usr/ccs/bin/m4 -DBASEDIR=$BASEDIR -DBINDIR=$BINDIR \
-DDATADIR=$DATADIR -DLOGDIR=$LOGDIR \
-DSOCKET=$SOCKET -DPORT=$PORT -DPIDFILE=$PIDFILE \
$BASEDIR/var/mybackup.cnf \
> /tmp/mybackup-$SNAPGROUP-$SNAPNUM.cnf
cd $LOGDIR
nohup $BINDIR/mysqld_safe \
--defaults-file=/tmp/mybackup-$SNAPGROUP-$SNAPNUM.cnf
>>/dev/null 2>&1 &


It uses a skeleton my.cnf that is filled in by m4:


[mysqld]
basedir=BASEDIR
datadir=DATADIR
ft_min_word_len=2
ft_stopword_file=DATADIR/fulltextstopwords.cnf
default-character-set=utf8
default-collation=utf8_general_ci
max_connections=10000
query_cache_size=32000000
log-bin=LOGDIR/web-mysql1-bin
server-id=3
read-only
#log=LOGDIR/web-mysql1-query.log
log-slow-queries=LOGDIR/web-mysql1-slow.log
log-error=LOGDIR/web-mysql1.usc.edu.err
port=PORT
socket=SOCKET
pid-file=PIDFILE

[myisamchk]
ft_min_word_len=2
ft_stopword_file=DATADIR/fulltextstopwords.cnf

Expanded version for hourly snapshots

I then expanded that version for hourly snapshots, with this as the result:


#!/usr/bin/bash
# author: Matthew Brown
# date: 2008-09-16

#---------------------------
# Variable Initialization
#---------------------------
cHour=`/usr/bin/date +%H`
#loc1=/var/local/backups/mysql_hourly
loc1=/mysql-backup/`hostname`/hourly
archBase=mysql_var-hour.
archNM=$archBase$cHour
dumpSpot=$loc1/$archNM
tempF=/tmp/mysqldumpStart
tempF1=/tmp/mysqldumpStart1
x=$(((`date +%H`) - 1 | bc))
fqdn=`/bin/hostname`
hostname=`basename $fqdn .usc.edu`

#--------------------------------------
# Record the mysqldump start time
#--------------------------------------
echo "Hourly mysql data backup began `date`"> $tempF &

#--------------------------------------
# Perform the mysqldump
#--------------------------------------
/var/local/mysql/default/bin/mysqldump --opt --force \
--user=root --password='notreally' --all-databases \
> $dumpSpot

#--------------------------------------
# Remove the previous day's hourly backup
#--------------------------------------
rm $dumpSpot.gz

#--------------------------------------
# Compress the backup using gzip
#--------------------------------------
/usr/bin/gzip $dumpSpot

#--------------------------------------
# Record long listing of new hourly backup
#--------------------------------------
ls -ltr $loc1/$archBase* > $tempF1

#--------------------------------------
# Compose and email backup completion report
#--------------------------------------
cat $tempF $tempF1 | mailx -s "$hostname `date +%Y.%m.%d` hour: `date +%H` mysql data dump complete" backup-reports

#--------------------------------------
# cleanup temp files
#--------------------------------------
rm $tempF $tempF1

Monday, September 15, 2008

ZFS snapshots of a running MySQL instance

I run a group of MySQL servers on Solaris 10 with their data on a ZFS filesystem. I snapshot this data hourly, and this is the basic script I use to do it. I build upon this script to do other things after the snapshotting.

The script is called mysql_DataSnapshot, and is called with two parameters, SNAPGROUP and SNAPNUM. These are used to form a snapshot name. The intent is that SNAPGROUP is something like "hourly" or "daily", while SNAPNUM is an identifier within that group – the hour number for hourly snapshots, the day number for daily snapshots, or suchlike.

I make no claim to great code quality, but publish this in the hope that it might help someone else trying to do this.


#!/usr/bin/bash
# author: Matt Brown
# date: June 2, 2008
# Creates a snapshot of a MySQL instance's filesystem.

#---------------------------
# Variable Initialization
#---------------------------

# The script takes two arguments: the snapshot group
# and the snapshot number. These are encoded into
# the snapshot name as filesystem@group.number, e.g.
# mysql/data/4.1.12@hour.12
SNAPGROUP=$1
SNAPNUM=$2

filesystem=mysql/data/4.1.12
snapname=$filesystem@$SNAPGROUP.$SNAPNUM

#--------------------------------------
# Remove any pre-existing snapshot
#--------------------------------------
zfs destroy -R $snapname

#--------------------------------------
# Perform the mysqldump
#--------------------------------------
/var/local/mysql/default/bin/mysql --user=root \
--password='notreally' <<EOF
FLUSH TABLES WITH READ LOCK;
\! zfs snapshot $snapname
UNLOCK TABLES;
EOF

#--------------------------------------
# List the snapshot
#--------------------------------------
zfs list $snapname