Connect to a headless CrashPlan desktop.

CrashPlan is a nice piece of backup software that allows you to choose any number of backup sources ( Documents, Photos, Music, everything on your computer ), and back them up to any number of backup destinations ( USB drive, CrahPlan’s servers, a friend’s computer, or any computer of yours that can run the CrahPlan desktop software ). This level of flexibility, and initially free offering is what drew me to CrashPlan for my home backup needs. I like it so much, I purchased the Pro plan, and would recommend it to others.

This post will show you an easy way to configure the CrashPlan desktop software on a Linux server that has no graphical interface ( text-only or headless ), so that it can be used as a backup destination for your other CrashPlan instances.

The CrashPlan support site has a document that provides instructions on how to configure a headless Linux client, and I think I found an even easier way to accomplish the same thing.

After you download, install, and start the CrashPlan client for your Linux server you will find that CrashPlan is listening on two ports. The first, port 4242, is where the CrashPlan engine is listening for backup requests, the second, port 4243, is where the CrashPlan graphical interface is expecting to connect to, so that you can configure the engine part of the software.

The problem at this point is that on your text-only Linux server you have no way of running the graphical CrashPlan software to configure the engine side of things. What you want to do is point the graphical interface client on your Windows, Mac, or Linux workstation at your server, and do the configuration over the network.

On your Linux server find the following CrashPlan configuration file ( this is the default ):

/usr/local/crashplan/conf/my.service.xml

and change the following section:

servicehost 127.0.0.1

to:

servicehost 0.0.0.0

and restart the CrashPlan service on your Linux server. What you will now find is that CrashPlan is listening on all interfaces for both its network ports. Modify your server firewall rules to allow connections to both these ports ( TCP 4242 and 4243 ) from your home machine.

On your home machine you are going to tell the CrashPlan desktop software to connect to this remote server for configuration instead of the local machine. First shutdown CrashPlan on your home machine, then locate and edit the following file:

C:\Program Files\CrashPlan\conf\ui.properties

and change this line:

#serviceHost=127.0.0.1

to:

serviceHost=10.0.0.5

where “10.0.0.5″ is the IP address of remote Linux server.

Now startup the CrashPlan desktop on your home machine and you will be connected to the remote instance of CrashPlan on your Linux server.

Using Net::DNS to write your own recursor.

Here’s a bit of code I wrote for work that I thought was kind of neat; it uses a recursive function and Net::DNS to recurse DNS.


#!/usr/bin/perl
use strict;
use warnings;

use Net::DNS;

my $domain = 'schwer.us';
my $sonicrns= 'ns2.sonic.net';
my @root_ns = map $_ . '.root-servers.net', 'a'..'m';

&recurse($domain);

sub recurse($)
{
	my $domain = shift;
	my $rns = $root_ns[int(rand(@root_ns))];
	&_recurse($domain,$rns);
}

sub _recurse($$)
{
	my $domain = shift;
	my $ns     = shift;

	print "Asking $ns about $domain.\n";

	my $res = Net::DNS::Resolver->new('nameservers'=>[$ns]);
	my $que = $res->send("$domain.",'NS');

	if ( $que )
	{
		my @ns = $que->authority;
		# check headers for 'aa' bit
		my $header = $que->header;
		print "answer is ", $header->aa ? "" : "non-", "authoritative\n";

		if ( $header->aa ) # stop recursing when we have an authoritative answer.
		{
			my @authns = $que->answer;
			foreach my $authns ( @authns )
			{
				$authns->print;
			}
		}
		else # keep recursing no authoritative answer yet.
		{
			my $nsname = '';

			# my host is IPv4 only, so I can only ask IPv4 name servers.
			# this finds the first IPv4 name server and asks it.
			foreach my $ns ( @ns )
			{
				$nsname = $ns->nsdname;
				my $r = Net::DNS::Resolver->new('nameservers'=>[$sonicrns]);
				my $q = $r->query($nsname,'A');
				if ( $q )
				{
					my @answer = $q->answer;
					if ( $answer[0]->type eq 'A' )
					{
						last;
					}
				}
				$nsname = ''; # in-case we reach the end of the list and can't find an 'A' record.
			}
			if ( $nsname )
			{
				print "$nsname answers for $domain.\n";;
				&_recurse($domain,$nsname);
			}
			else
			{ 
				print "No IPv4 name servers to query for $domain.\n"; 
			}
		}
	}
	else
	{
		print "Could not find NS records for $domain.\n";
	}
}

Dad’s Meatloaf

Vinegar Peppers :

* 1 tablespoon extra-virgin olive oil.
* 1/4 cp. chicken stock.
* 1/2 onion sliced thin.
* 1/2 red bell pepper seeded and sliced thin.
* 2 garlic cloves, minced.
1/4 cp. drained jarred sliced banana peppers.
* 1/4 cp. white wine vinegar.
* 1 Tbsp. unsalted butter.

Heat chicken stock with bell pepper and onion until soft, about 5 minutes.

Add garlic and banana peppers, cook for a minute.

Add vinegar and bring to a boil, then simmer for 5 minutes.

Remove from heat, mix in butter, season with salt and pepper.

Meatloaf :

* 1 tablespoon extra-virgin olive oil.
* Vinegar peppers.
* 2 teaspoons (about 3 cloves) chopped garlic.
* 1.25 pound ground beef.
* 2 eggs.
* 3/4 cup bread crumbs.
* 1 cup grated Parmesan.
* 1 tablespoon Worcestershire sauce.
* 2 tablespoons chopped basil leaves.
* 1 tablespoon chopped cilantro leaves.
* 1 teaspoon salt.
* 1/2 teaspoon black pepper.
* 1 cup tomato sauce.
* 3 slices of bacon.

Preheat oven to 350 degrees F.

Saute the garlic in the olive oil.

Mix all the ingredients together except for the tomato sauce and bacon.

Pack the meat mixture into an oiled loaf pan

Top with the bacon (lattice style), and then tomato sauce.

Bake for approximately 50 to 60 minutes or until an instant-read thermometer registers 160 degrees F in the middle of the meatloaf.  Remove from the oven and let rest for 5 minutes. Slice and serve.

Areca Tools RPM for CentOS Linux.

We recently started deploying servers with Areca RAID controllers (we had been a long time 3ware purchaser, but recently the cards and the support of them seems to have taken a turn for the worse).

Areca provides a handful of tools for managing their RAID controllers, but leave it to you to deploy and install on your servers how you see fit; that might be fine for a handful of servers, but any more than that and you are going to need some sort of package that is easily installable across your network.

Enter the areca-tools RPM I built for CentOS Linux : areca-tools-1.8-1.el5.sonic.src.rpm .

With this Source RPM you can build the areca-tools RPM for whatever hardware architecture and Red Hat based Linux OS you want. Hopefully this will save you some time if you need to deploy Arecas in the servers you maintain.

Note : if you want to monitor your Areca’s RAID status from mon, check out the raid.monitor I wrote.

How to write a WordPress plugin to notify your customers via Twitter.

WordPress has a page on “Writing a Plugin” that you can refer to for all the gory details; this post is a quick demonstration of how you too can notify people of updates to your Blog via Twitter.

Add your handlers:

add_action('edit_form_advanced','notify_customers_checkbox');
add_action('save_post','notify_customers');

Add some check boxes to the “Write Post” interface:

function notify_customers_checkbox()
{
?>
<fieldset id="notify_customers" class="dbx-box">
<h3 class="dbx-handle">Notify Customers:</h3>
<div class="dbx-content">
<input type="checkbox" name="send_to_twitter" id="send_to_twitter" checked="checked" /> twitter
<input type="checkbox" name="send_to_list" id="send_to_list" checked="checked" /> email
<input type="checkbox" name="send_to_nntp" id="send_to_nntp" checked="checked" /> nntp
</div>
</fieldset>
<?php
}

Check the status of those check boxes:

function notify_customers($post_id)
{
if ( isset ( $_POST['send_to_twitter'] ) )
{ send_to_twitter($post_id); }

if (isset ( $_POST['send_to_list'] ) )
{ send_to_list($post_id); }

if (isset ( $_POST['send_to_nntp'] ) )
{ send_to_nntp($post_id); }
}

Write a method to take your post, clean it up a bit and send it off to Twitter:

function send_to_twitter($post_id)
{
$twitter_user = 'sonicnet_status';
$twitter_pass = '';

$post_url     = get_permalink($post_id);
$post_title    = stripslashes($_POST['post_title']);
$post_title    = html_entity_decode($post_title);
$post_content    = stripslashes($_POST['post_content']);
$post_content    = strip_tags($post_content);
$post_content    = html_entity_decode($post_content);

$twitter_message = "$post_title: $post_content";

// We only care about published posts.
// If it's an old post being updated prepend "Update" to the post.

if ( $_POST['prev_status'] == 'draft' ) //new post.
{
if($_POST['publish'] == 'Publish')
{
$xrl = file_get_contents("http://metamark.net/api/rest/simple?long_url=$post_url");

$twitter_message = substr($twitter_message , 0 , 117);
$twitter_message = "$twitter_message... $xrl";
$twitter_message = urlencode($twitter_message);

$url = 'http://twitter.com/statuses/update.xml';
$curl_handle = curl_init();
curl_setopt($curl_handle, CURLOPT_URL, "$url");
curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_POST, 1);
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, "status=$twitter_message");
curl_setopt($curl_handle, CURLOPT_USERPWD, "$twitter_user:$twitter_pass");
$buffer = curl_exec($curl_handle);
curl_close($curl_handle);
}
}
}

And there you have it; you’ve just told all your Twitter followers about your latest Blog post.

You’ll note we do some other cool stuff to keep our customers in the loop; like send them E-Mail and post to Usenet, but that’s another Blog post.

Augie’s 30th Inglorious Birthday Bash

What :  Augie’s 30th Birthday.

When :  22, November at 12:00pm.

Where :  Third Street Aleworks, 610 3rd Street Santa Rosa, CA

Help me celebrate my 30th birthday by joining me at the Third Street Aleworks in downtown Santa Rosa, CA; I have reserved the upstairs:

http://www.thirdstreetaleworks.com/

We will start around noon with some food and drinks (unfortunately The Aleworks doesn’t do separate checks when reserving the upstairs, so ordering at the bar is preferred).

If you have never been to The Aleworks, let me know and I can help you navigate downtown parking.

I hope to see you all there.

Press Democrat photo for article: “What are you doing?”

Press Democrat photo for article: “What are you doing?”

Originally uploaded by Augie Schwer.

I am quoted in a recent Press Democrat article about Twitter and along with it came a photo that showed up on the front page of the business section.

Original article here:

http://www.pressdemocrat.com/article/20080616/NEWS07/806160307/1036/BUSINESS01&title=What_are_you_doing_#

The follow up I wrote for the Sonic.net Insider blog is here:

http://corp.sonic.net/insider/2008/06/16/what-are-we-doing/

The Ultimate Father’s Day Gift Buying Guide.

A list of things every man should own and the perfect gift buying guide for Dad with Father’s Day just around the corner.

Pocket Knife

Spyderco Kiwi

My favorite thing to say when someone asks me if I have a knife is: “I’m wearing pants aren’t I?“. This is the Spyderco Kiwi; which is what I carry; the perfect little pocket knife with great old time style.

Hip Flask

David Morgan Hip Flask

I gave my Groomsmen engraved Hip Flasks for my wedding and they saw action within minutes, so I can tell you from experience that these little things go over well with the fellas. I suggest a sturdy flask, one that can take a tumble, and isn’t so large that it’s readily noticeable; remember the whole idea of a Hip Flask is to be discrete when you are drinking.

The one pictured above is from David Morgan; it’s classy and not too shiny, but is probably too big to fit comfortably in your jacket pocket.

Lounge Chair

Eames Lounge Chair

Every man needs a chair to relax in after a hard day at work; a chair to sip spirits, a chair to watch something mindless on TV, a chair to put-up-your-feet in and nap in on a Sunday afternoon; a lounge chair dammit!

The Herman Miller Eames Lounge and Ottoman is at the far end of expense and style; something classy is nice, but above all else it must be cozy.

Coffee

Cuisinart Coffeemaker

Every morning my day starts with coffee; that’s why I suggest this little work horse: The Brew Central 12-Cup Programmable Coffeemaker from Cuisinart; it will make a good pot of coffee promptly every morning when you tell it too, and it’s durable, reliable, and easy to clean.

For the weekends I like a pot of Press Pot which takes a bit longer to make, but well worth the time if you have it.

Shave Kit

Cole Haan Pinedale Shave Kit

OK, I don’t know if every man needs one of these, but its simplicity and old-time style say Man to me; maybe it’s because my Dad always traveled with one, or maybe it’s because it’s a large pouch made out of animal skin that you throw into everything that makes you look and smell like a Man.

The Cole Haan Pinedale Shave Kit is a bit pricey, but I’m drawn in by the brown leather (that wears and ages so well) and understated style.

Hat

Brixton Castor

Every man needs a hat; it warms you in the winter, provides shade during the summer, and if worn properly can make you the classiest guy in the room.

My favorite for price and style are the ones made by Brixton. The
Brixton Castor is perfect for the coming Summer months.

Suit

JFK Aaron Shikler painting.

Every man must own at least one suit that fits. There are many occasions in our lives that call for more formal attire; weddings, job interviews, ceremonies of all types and funerals (yours or others). If you can afford it, get something made for you; if not, then make sure you get it altered to fit your body as it is unlikely you and the mannequins have the same proportions.

Available for Usability Testing?

Just got this email; let me know if you are interested.

Hey Augie,
I’m working for Safari Books Online now, and we’re conducting some
usability testing to get a better idea of how techies use/would use
our product.

Would you be interested in stopping by our Sebastopol office on
Thursday for about 45 minutes? We’d really like to pick your brain,
and see if you can suggest any ways to improve our product. You don’t
need to be a subscriber, just a techie!

There is also a $25 gift card, if that helps =)

Sonoma County Transit WiFi

Just got this email:

Augie -

Sonoma County Transit introduced free WiFi service on five buses this past
Wednesday (4-30). The WiFi equipped buses are our newest buses that are
equipped with high-back seats, luggage racks and reading lamps. The WiFi
buses will be deployed on weekday AM and PM express trips serving routes 20,
30, 48 and 60.

The equipment and service is provided by Parvus. Information on the system
can be found at:

http://www.parvus.com/products/ProductPage.aspx?ProductID=151

Thanks,
Bryan Albee

Bryan Albee
Transit Systems Manager
SonomaCountyTransit

707.585.7516
707-585-2927 fax
sctransit.com

PowerDNS MySQL INT limit reached.

The very non-descriptive error below indicates that you have reached the maximum value for the MySQL INT Data Type.

Communicator thread died because of error: Failed to execute mysql_query, perhaps connection died? Err=-1: Duplicate entry ’2147483647′ for key 1

What you need to do if this happens to you on your PowerDNS records table is the following:

mysql> alter table records modify id BIGINT AUTO_INCREMENT;

If it happens to your domains table, then things get a bit more complicated and you should do the following:

mysql> alter table records drop foreign key `records_ibfk_1`;

mysql> alter table records modify domain_id BIGINT ;

mysql> alter table domains modify id BIGINT AUTO_INCREMENT;

mysql> alter table records add constraint `records_ibfk_1` FOREIGN KEY (`domain
_id`) REFERENCES `domains` (`id`) ON DELETE CASCADE;

The above worked for me, your results may vary.

Feed Twitter an RSS feed with Perl.

Here’s a more concise script to feed Twitter an RSS feed; in this case the latest post to the Sonic.net MOTD Blog. The following code grabs the latest entry in an RSS feed, pulls out the URL and as much content as it can, shortens the URL and sends it all to Twitter.

#!/usr/bin/perl

use strict;
use warnings;
use Net::Twitter;
use LWP::Simple;
use XML::RSS::Parser::Lite;
use WWW::Shorten::Metamark;

my $feed = get(‘http://corp.sonic.net/motd/feed/rss’);
my $rp = new XML::RSS::Parser::Lite;

$rp->parse($feed);

my $it = $rp->get(0);

my $long_url = $it->get(‘url’);
my $short_url = makeashorterlink($long_url);
my $message = $it->get(‘description’);

$message =~ s/^.+ — //; # remove dash seperator.
$message =~ s/^\s+//; # Nuke any leading space; every char counts.
$message =~ s/\s+$//; # Nuke any trailing space; every char counts.
$message =~ s/[_]+$//; # Nuke any trailing underscores; happens when message is
short.
$message = substr $message , 0 , 117; # Twitter can only handle 140 chars.
$message .= ‘… ‘; # Append ellipse to denote further content available.
$message .= $short_url; # Append the shortened URL.

my $twit = Net::Twitter->new(username=>”sonicnet”, password=>”password” );
$twit->update($message);

Sonic.net updates via Twitter

Get updates about your favorite ISP from Twitter; just send “follow sonicnet” from your favorite Twitter device. You can check out the sonicnet page to see what you’ll be getting.

The code for this is made possible by the Net::Twitter Perl module.

#!/usr/bin/perl
use strict;
use warnings;
use Net::Twitter;
my $message = "Super Duper";
my $twit = Net::Twitter->new(username=>"sonicnet", password=>"password" );
$twit->update($message);

Pretty easy huh?

Perl , $SIG{CHLD} = ‘IGNORE’ , system() and you.

Note: This has been in my drafts for a while, but I think it’s ready for publishing..

At first blush you probably would not expect the following to print “-1″; as you probably expect “system” to execute and return the return code from “echo”.

$SIG{CHLD} = 'IGNORE';
print system('echo');

This stumped me too, so I did some research.

From the Perl PIC Documentation:

On most Unix platforms, the CHLD (sometimes also known as CLD) signal has special behavior with respect to a value of ‘IGNORE’. Setting $SIG{CHLD} to ‘IGNORE’ on such a platform has the effect of not creating zombie processes when the parent process fails to wait() on its child processes (i.e. child processes are automatically reaped). Calling wait() with $SIG{CHLD} set to ‘IGNORE’ usually returns -1 on such platforms.

And perldoc -f system:

The return value is the exit status of the program as returned by the wait call. … Return value of -1 indicates a failure to start the program or an error of the wait(2) system call (inspect $! for the reason).

And wait(2):

POSIX.1-2001 specifies that if the disposition of SIGCHLD is set to SIG_IGN or the SA_NOCLDWAIT flag is set for SIGCHLD (see sigaction(2)), then children that terminate do not become zombies and a call to wait() or waitpid() will block until all children have terminated, and then fail with errno set to ECHILD. (The original POSIX standard left the behaviour of setting SIGCHLD to SIG_IGN unspecified.) Linux 2.6 conforms to this specification. However, Linux 2.4 (and earlier) does not: if a wait() or waitpid() call is made while SIGCHLD is being ignored, the call behaves just as though SIGCHLD were not being ignored, that is, the call blocks until the next child terminates and then returns the process ID and status of that child.

So on Linux 2.6 kernels if you auto. reap zombies by setting $SIG{CHLD} to ‘IGNORE’, then you can’t trust the return code from ‘system’ as it will always be ‘-1′.

One solution would be to reap your own zombies with one of the popular zombie reaping code snipets.

sub REAPER { 1 until waitpid(-1 , WNOHANG) == -1 };
$SIG{CHLD} = \&REAPER;
print system('echo');

Be careful when using the special Perl variable ‘$?’ because it will have been altered by the call to ‘waitpid’ in your REAPER.

This is because when a child exits a SIG_CHLD is sent to its parent to see this in action try the code below:

sub REAPER
{ print "REAPER\n"; waitpid(-1 , WNOHANG); }
$SIG{CHLD} = \&REAPER;
system('echo');
print "RV: $?\n";