<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>BluHelix Studios</title>
	<atom:link href="http://www2.bluhelix.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www2.bluhelix.com:81</link>
	<description>The Official BluHelix Home Page</description>
	<lastBuildDate>Sat, 31 Jan 2009 06:42:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>This week at BluHelix Studios</title>
		<link>http://www2.bluhelix.com:81/2009/01/this-week-at-bluhelix-studios/</link>
		<comments>http://www2.bluhelix.com:81/2009/01/this-week-at-bluhelix-studios/#comments</comments>
		<pubDate>Sat, 31 Jan 2009 05:47:25 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Studio Announcement]]></category>

		<guid isPermaLink="false">http://www.bluhelix.com/?p=280</guid>
		<description><![CDATA[With the main site now off the hokey forum integration I finally got around to upgrading it. The forum is now running on phpBB3 (hurray!). While I was at it I also upgraded the photo gallery application to Gallery 2.3. Unfortunately, there are still some hiccups to tend to (plugins page is a big white [...]]]></description>
			<content:encoded><![CDATA[<p>With the main site now off the hokey forum integration I finally got around to upgrading it.  The forum is now running on phpBB3 (hurray!).  While I was at it I also upgraded the photo gallery application to Gallery 2.3.  Unfortunately, there are still some hiccups to tend to (plugins page is a big white page ugh!).  I also tweaked the blog theme a little.  Cheers.</p>
<p><strong>Update:</strong> Found the fix for Gallery 2.3 at <a href="http://gallery.menalto.com/node/83597">http://gallery.menalto.com/node/83597</a>.  Evidently the plugins repository is bugged and deleting the cache allows one to access the page again.</p>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2009/01/this-week-at-bluhelix-studios/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Forget the includes, let PHP autoload it</title>
		<link>http://www2.bluhelix.com:81/2009/01/forget-the-includes-let-php-autoload-it/</link>
		<comments>http://www2.bluhelix.com:81/2009/01/forget-the-includes-let-php-autoload-it/#comments</comments>
		<pubDate>Tue, 20 Jan 2009 07:04:01 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Interest]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.bluhelix.com/?p=249</guid>
		<description><![CDATA[If you&#8217;re a PHP developer who breaks up their classes into separate files, you&#8217;re probably aware of the annoyance of having to setup the proper includes at the beginning of every script.  There is also careful management of class dependencies to be considered, whereby one class will have to include those classes it uses itself [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re a PHP developer who breaks up their classes into separate files, you&#8217;re probably aware of the annoyance of having to setup the proper includes at the beginning of every script.  There is also careful management of class dependencies to be considered, whereby one class will have to include those classes it uses itself to guarantee they exist when needed.</p>
<p>Starting in PHP5 we were given a better way.  PHP5 introduces a new magic function called __autoload().  If this function is defined in the PHP script, it is called whenever an attempt is made to use a class that has not been defined yet.  After __autoload() is called PHP will attempt to use the class again, giving the developer one last chance to get the class setup in between.</p>
<p>__autoload() has one parameter, the name of the class or interface (in a string) that the script attempted to use.  A simple implementation that includes a class classname saved as classname.php from the include path would be
<code>__autoload($classname)
{
    if (is_readable($classname.'php'))
    {
        include $classname.'php';
        if (!class_exists($classname, false) &amp;&amp; !interface_exists($classname, false))
            trigger_error('Could not load '.$classname, E_USER_ERROR);
    }
}</code></p>
<p>Note I used include instead of include_once.  This is because __autoload() will only be called if the class has not already been defined, i.e. the include file has not been included.  Feel free to use include_once however, to be sure.</p>
<p>Also note the false parameter I passed to class_exists().  This parameter disables an autoload check for that class &#8211; it wouldn&#8217;t make sense to autoload the class again if the first autoload failed.  With the default true parameter, class_exists will attempt to autoload the class if it doesn&#8217;t exist.</p>
<p>__autoload() is a great way to manage a library of classes because you can write your own implementation that knows how to load up your classes when they are needed.  Instead of including everything at the top of your scripts, just include the autoloader and it&#8217;ll take care of the rest.  __autoload() also provides an incentive to write all of your library code as classes (and interfaces) because functions cannot be autoloaded.</p>
<p>Now for some bad news.  __autoload() is a bad idea!  Why? Because if you were to use it and then add a 3rd party application to your project that also used it you&#8217;d get a nasty PHP error stating that __autoload cannot be declared twice.  What a bummer!  Fortunately in PHP5.1.x the developers solved this problem by giving us the spl_autoload* functions.  These behave the same as __autoload() but constitute a stack were your implementation can exist simultaneously with the one belonging to the 3rd party application you just added.</p>
<p>Simply write your own function, call it anything you like, and register it using
<code>spl_autoload_register('my_autoload_function');</code></p>
<p>Even better, we can also set the autoloader to a method in a class using an array form.  Static methods can be used like so
<code>spl_autoload_register(array('My_Static_Class', 'myStaticMethod'));</code></p>
<p>Dynamic methods can also be used
<code>spl_autoload_register(array(&amp;$class, 'myDynamicMethod'));</code></p>
<p>Two important things to keep in mind when using spl_autoload* are</p>
<ol>
<li>spl_autoload* functions cannot be used in combination with __autoload() &#8211; it&#8217;s one or the other</li>
<li>Your implementation of an spl_autoload* autoloader should not error if the class cannot be found, since its possible a second autoloader can find it.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2009/01/forget-the-includes-let-php-autoload-it/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ContentNegotiator updates</title>
		<link>http://www2.bluhelix.com:81/2009/01/contentnegotiator-updates/</link>
		<comments>http://www2.bluhelix.com:81/2009/01/contentnegotiator-updates/#comments</comments>
		<pubDate>Wed, 14 Jan 2009 07:34:18 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Studio Announcement]]></category>

		<guid isPermaLink="false">http://www.bluhelix.com/?p=242</guid>
		<description><![CDATA[I&#8217;ve revisited a class I wrote last year and made a few updates. You can find the new version on my Snippets page. Updates on 1/13/2009 ContentNegotiator is now a singleton.  You may only instantiate one instance of the class. Constructor no longer kicks off output buffering.  I decided this was a &#8220;side-effect&#8221; and should [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve revisited a class I wrote last year and made a few updates.  You can find the new version on my Snippets page.</p>
<p><strong>Updates on 1/13/2009</strong></p>
<ul>
<li>ContentNegotiator is now a singleton.  You may only instantiate one instance of the class.</li>
<li>Constructor no longer kicks off output buffering.  I decided this was a &#8220;side-effect&#8221; and should be moved to a separate method.</li>
<li>prolog() method no longer emits content-type headers.  The prolog() method now echoes only the XML prolog and DOCTYPE.</li>
<li>sendHeaders() added to emit content-type headers to the browser.</li>
<li>negotiate() added to begin output buffering for source code negotiation.</li>
<li>close() method added to flush output buffering.  I found some issues with relying on PHP to close buffering at the end of the page execution.  It is better to close the buffer manually at the end of the page.</li>
</ul>
<p><strong>Updates on 1/14/2009</strong></p>
<ul>
<li>Broke up the constructor a little bit more.</li>
<li>Chooses a document type better.  It now falls down the big if statement before content type is selected and again if it needs to be changed. This fixes a bug where it sometimes picked a slightly different document type then it guessed it would.</li>
<li>The $version and $flavor properties now reflect the actual document type chosen.  ContentNegotiator does not use these after it picks the document type, but at least they&#8217;re there in case someone wants to dump them.</li>
<li>Implemented a way to specify the fallback document type.  If you pass the first parameter as an array, it will pick the first index if the browser accepts it and fallback on the second.  Using this it is now possible to send IE XHTML 1.1 even though IE does not accept the XHTML content type.<br />
Use: <em>$contneg-&gt;getInstance(array(&#8216;XHTML 1.1&#8242;, &#8216;XHTML 1.1&#8242;));</em></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2009/01/contentnegotiator-updates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Same BluHelix, now on WordPress</title>
		<link>http://www2.bluhelix.com:81/2009/01/same-bluhelix-now-on-wordpress/</link>
		<comments>http://www2.bluhelix.com:81/2009/01/same-bluhelix-now-on-wordpress/#comments</comments>
		<pubDate>Fri, 09 Jan 2009 07:09:27 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Studio Announcement]]></category>

		<guid isPermaLink="false">http://unknown8063.homeip.net:88/www/?p=236</guid>
		<description><![CDATA[I&#8217;m beginning to wrap up the migration to WordPress. There are still a few style sheet modifications I need to get around to so don&#8217;t be surprised if things keep changing periodically for the next few weeks. With the migration complete I have moved the forum back to its original location of http://forums.bluhelix.com/. Recall that [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m beginning to wrap up the migration to WordPress.  There are still a few style sheet modifications I need to get around to so don&#8217;t be surprised if things keep changing periodically for the next few weeks.</p>
<p>With the migration complete I have moved the forum back to its original location of <a href="http://forums.bluhelix.com">http://forums.bluhelix.com/</a>.  Recall that it was a sub folder for over a year due to the session sharing between the main site and forum.  I am also planning to upgrade the forum after I complete the main site.</p>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2009/01/same-bluhelix-now-on-wordpress/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A Multiplatform Backup Solution with rSync: Part 2</title>
		<link>http://www2.bluhelix.com:81/2008/12/a-multiplatform-backup-solution-with-rsync-part-2/</link>
		<comments>http://www2.bluhelix.com:81/2008/12/a-multiplatform-backup-solution-with-rsync-part-2/#comments</comments>
		<pubDate>Sun, 28 Dec 2008 21:33:33 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Inside BluHelix]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.bluhelix.com/?p=208</guid>
		<description><![CDATA[Hello, this is part 2 of my rSync backup solution article. Please see part 1 if you have not read it yet. Overview The primary weakness of the rSync bash script covered in part 1 when backing up a Windows computer is that it is unable to transfer any file that might be open by [...]]]></description>
			<content:encoded><![CDATA[<p>Hello, this is part 2 of my rSync backup solution article.  Please see part 1 if you have not read it yet.</p>
<h3>Overview</h3>
<p>The primary weakness of the rSync bash script covered in part 1 when backing up a Windows computer is that it is unable to transfer any file that might be open by the user or operating system.  Microsoft includes a backup application (NTBackup) beginning in Windows XP Service Pack 1 and Windows 2003 that gets around this problem by creating its backup from a <a href="http://en.wikipedia.org/wiki/Volume_shadow_copy">volume shadow copy</a>.  The Volume Shadow Copy creates a snapshot of a specific volume at a specific point in time.  This allows one to backup every file in a volume without the possibility of any being open or partially written to by an application.</p>
<p>Using the volume shadow copy requires a bit of black magic.  We&#8217;ll need to obtain vshadow.exe from one of Microsoft&#8217;s freely available SDK&#8217;s.  Very few programs understand the URI for a volume shadow copy, including rSync, so we&#8217;ll also need an <a href="http://blogs.msdn.com/adioltean/archive/2006/09/18/761515.aspx">application capable of mapping a volume shadow copy to a standard Windows drive letter</a>.  The solution is an small program called <a href="http://blogs.msdn.com/adioltean/archive/2005/10/04/477164.aspx">dosdev.exe</a>, which is a wrapper around <a href="http://msdn.microsoft.com/en-us/library/aa363904.aspx">DefineDosDevice( )</a> Win32 API.</p>
<h3>Setup</h3>
<p>For our setup we will have two machines.  The <strong>Mirror</strong> (192.168.1.2) will be the rSync backup server running a *nix operating system.  The Mirror will create snapshots of the <strong>Target</strong> (192.168.1.3) which is running either Windows XP or Windows Vista.  I will be sure to note when the two Windows operating systems differ in our setup.</p>
<h4>Required software for the Mirror</h4>
<ul>
<li>OpenSSH</li>
<li>rSync</li>
<li>Expect</li>
</ul>
<h4>Required software for the Target</h4>
<ul>
<li>cwRsync</li>
<li>CopSSH</li>
<li>vshadow.exe</li>
<li>dosdev.exe</li>
</ul>
<p>The software needed on the Mirror is pretty minimal, assuming you already setup the snapshot-based backup covered in part 1.  The one new thing we&#8217;ll need is <a href="http://en.wikipedia.org/wiki/Expect">Expect</a> so we can write a short Expect Script.</p>
<p>For Windows, we&#8217;ll need a Windows based rSync.  I picked cwRsync because it is easy to install and runs from Cygwin, which we&#8217;ll need.  There is no need to install Cygwin, however, as cwRsync comes with all the required Cygwin binaries in the installer.  You can find cwRsync at their site: <a href="http://www.itefix.no/i2/node/10650">http://www.itefix.no/i2/node/10650</a></p>
<p>Install cwRsync to the folder of your choice.  Next, download <a href="http://www.itefix.no/i2/node/27">CopSSH</a>.  CopSSH is also a straight forward to install and setup SSH server for Windows.  The program is Cygwin based, and again, includes all the Cygwin binaries needed to do its job.  The trick here is, we want to install CopSSH to the same location as cwRsync so we avoid having two instances of Cygwin running simultaneously.</p>
<p>Next, we&#8217;ll need vshadow.exe.  For Windows XP and 2003 users, you can download <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=0B4F56E4-0CCC-4626-826A-ED2C4C95C871&amp;displaylang=en">Microsoft&#8217;s Volume Shadow Copy Service SDK</a>.  Vista user&#8217;s need to download the <a href="http://msdn.microsoft.com/en-us/windows/bb980924.aspx">Windows Vista SDK Update</a>.  It is <strong>very</strong> important you obtain the correct version of vshadow.exe.  For instance, the Windows XP and 2003 versions are <strong>different</strong> and will be found in different directories after the SDK is installed.  If you encounter errors when running vshadow.exe, then do verify you grabbed the correct file.  I suggest copying vshadow.exe and placing it in either the Cygwin bin folder or your System32 folder in Windows.  You may uninstall the SDK if you prefer &#8211; we only need vshadow.exe.</p>
<p>Finally, we need dosdev.exe.  This program is very obscure.  To get the exe from Microsoft, download <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=cebf3c7c-7ca5-408f-88b7-f9c79b7306c0&amp;DisplayLang=en">MPSRPT_CLUSTER.EXE</a>.  If you have a program like 7zip you can extract dosdev.exe directly from the installer.  Otherwise you will need to install the report application and copy dosdev.exe from it.  Again, I suggest copying dosdev.exe and placing it in either the Cygwin bin folder or your System32 folder in Windows.  DO NOT EXECUTE the report&#8230;</p>
<p>Once everything is installed, activate a CopSSH user.  This can be done easily by launching the activate user wizard from the CopSSH start menu entry.  In order to execute vshadow.exe you need to activate a user with Administrator privledges.  In Vista, this probably means the hidden Administrator account.  Vista users, please follow this <a href="http://www.howtogeek.com/howto/windows-vista/enable-the-hidden-administrator-account-on-windows-vista/">How to guide</a> to enable the hidden Administrator account and assign it a password.  If you prefer, you may then <a href="http://forums.techarena.in/vista-help/748249.htm#post2854275">hide the account from the login screen</a>.</p>
<h3>Scripts</h3>
<p>For this setup we&#8217;ll need (sadly) eight files: four on the Mirror and four more on the Target machine.  Place all the Mirror files in the same directory and I have them creating the snapshot in <strong>/snapshot</strong>.  For the Target, I left all four files in the Administrator&#8217;s home dir at <strong>C:\Program Files\cwRsync\home\Administrator</strong>.  I plopped a copy of vshadow.exe and dosdev.exe in <strong>C:\Program Files\cwRsync\bin</strong> so that I could execute them like the Cygwin command line programs.  Again, <strong>C:\Windows\System32</strong> would also work.  Replace all instances of &#8220;password123&#8243; with your Administrator&#8217;s password.  However, the rSync daemon password need not be the same as your Windows authentication password.</p>
<h4>General idea</h4>
<ol>
<li>backup.sh is initiated manually or from a scheduled cron entry</li>
<li>backup.sh cleans up extra files in case the previous execution failed to complete</li>
<li>backup.sh uses an expect script to log into Target via a password authenticated SSH session and begins vshadow.exe as a background process.</li>
<li>backup.sh waits on a VB script that is started remotely to sleep until the rSyncd pid file is detected</li>
<li>vshadow.exe executes a CMD script that maps a volume shadow copy with dosdev.exe and then begins a rSync daemon</li>
<li>rSync daemon creates a pid file and listens for a connection</li>
<li>Remote VB script detects the rSyncd pid file and terminates, allowing the bash script to continue</li>
<li>backup.sh begins the rSync transfer process, which connects to the daemon running on the remote machine</li>
<li>After the transfer is complete, backup.sh kills the daemon process on the remote machine</li>
<li>With the rSync daemon terminated, the CMD script continues and unmaps the drive letter used for the volume shadow copy.</li>
<li>vshadow.exe completes and destroys the volume shadow copy.</li>
<li>backup.sh cleans up extra files and terminates.</li>
</ol>
<h4>Mirror</h4>
<ul>
<li>backup.sh</li>
<li>exclude_users</li>
<li>rsync.secret</li>
<li>sshlogin.exp</li>
</ul>
<h4>Target</h4>
<ul>
<li>rsyncd.secrets</li>
<li>sleep-rsyncd.vbs</li>
<li>vsrsync.cmd</li>
<li>rsyncd.conf</li>
</ul>
<ul>
<li>The files backup.sh and exclude_users are recognizably close to what we used in part 1.   If you are a Vista user do note that you will need to exclude <a href="http://www.svrops.com/svrops/articles/jpoints.htm">certain junctions and soft links</a> that Microsoft included to maintain XP-like paths or rSync will error and/or backup the same files more than once.  The junctions might be surprising to some Windows users since Vista OS keeps them hidden from the user during normal use.</li>
<li>There are some differences between my backup.sh on XP and Vista; however, it turns out the Vista version will run on XP so I will only provide my Vista script in this guide to keep things simpler.</li>
<li>Notice that we call vshadow.exe and taskkill using an expect script rather than the usual public key authentication.  Public key authentication in Cygwin/SSH bypasses Windows authentication (because no Windows password was provided to authenticate) and in Cygwin 1.5.x, the version I used in my setup, the context switch used to support public key authentication causes a slight difference in the environment that prevents vshadow.exe from running successfully.  The win32 app taskkill also fails on Vista when used with public key authentication (it completed successfully on XP, however).</li>
<li>For some reason the PID printed to the rsyncd pid file in Vista was inaccurate.  In XP it was correct and I used the contents of the pid file to kill the process.</li>
<li>Also take note that we&#8217;re using a rSync clinet/daemon model instead of tunneling rSync over SSH.  This means we&#8217;ll need a password file to avoid an interactive password prompt and our transfer is sent over the clear instead of being encrypted.  Advanced users may consider <a href="http://www.netbits.us/docs/stunnel_rsync.html">tunneling rSync over STunnel</a> to achieve encryption.</li>
<li>We set the modify window parameter to 2 seconds to the <a href="http://support.microsoft.com/kb/127830">2 second timestamp resolution of FAT32 file systems</a>.</li>
<li>Finally, while Windows paths are not case sensitive, *nix and by extension, Cygwin, paths are.  On my XP machine the Windows directory is all capitals, so be sure to verify the casing in the paths I entered below match your system.</li>
</ul>
<p><strong>backup.sh</strong>
<code>#!/bin/bash
unset PATH

# USER VARIABLES
BACKUPDIR=/snapshots                                # Folder on the backup server where the backups shall be located
KEY=/root/rsync/rsync-key                           # SSH key
TARGET_HOST=192.168.1.3                             # The address of the production server
TARGET_USER=Administrator                           # The user of the production server
EXCLUDES_USERS=/root/backup/exclude_users           # File containing the excluded directories
DAYS=30                                             # The number of days after which old backups will be deleted

# PATH VARIABLES
CSCRIPT=/cygdrive/c/Windows/System32/cscript.exe    # Remote location of cscript exe
TASKKILL=/cygdrive/c/Windows/System32/taskkill.exe  # Remote location of taskkill.exe
CAT=/bin/cat                                        # Remote location of cat bin
SED=/bin/sed                                        # Remote location of sed bin

CP=/bin/cp;                                         # Location of the cp bin
FIND=/usr/bin/find;                                 # Location of the find bin
ECHO=/bin/echo;                                     # Location of the echo bin
MK=/bin/mkdir;                                      # Location of the mk bin
SSH=/usr/bin/ssh;                                   # Location of the ssh bin
DATE=/bin/date;                                     # Location of the date bin
RM=/bin/rm;                                         # Location of the rm bin
GREP=/bin/grep;                                     # Location of the grep bin
RSYNC=/usr/bin/rsync;                               # Location of the rsync bin
TOUCH=/bin/touch;                                   # Location of the touch bin

##                                                      ##
##      --       DO NOT EDIT BELOW THIS HERE     --     ##
##                                                      ##

# CREATING NECESSARY FOLDERS
$MK $BACKUPDIR
CURRENT=$BACKUPDIR/current
OLD=$BACKUPDIR/old
$MK $CURRENT
$MK $OLD
# CREATING CURRENT DATE / TIME
NOW=`$DATE '+%Y-%m'-%d_%H:%M`
NOW=$OLD/$NOW
$MK $NOW

# INITIALIZE VOLUME SHADOW COPY AND RSYNC DAEMON
$SSH -i $KEY $TARGET_USER@$TARGET_HOST "rm rsyncd.pid"

./sshlogin.exp $TARGET_USER@$TARGET_HOST                                 \
  "vshadow.exe -script=vss-setvar.cmd -exec=vsrsync.cmd C\:" &#038;

# SLEEP UNTIL RSYNCD PID FILE IS FOUND
$SSH -i $KEY $TARGET_USER@$TARGET_HOST "$CSCRIPT sleep-rsyncd.vbs"

# RUN RSYNC INTO CURRENT
$RSYNC                                                                   \
        -apvz --delete --delete-excluded                                 \
        --exclude-from="$EXCLUDES_USERS"                                 \
        --password-file=rsync.secret                                     \
        --modify-window=2                                                \
        $TARGET_USER@$TARGET_HOST::C/Users/                              \
    $CURRENT ;

# TERMINATE RSYNC DAEMON AND VOLUME SHADOW COPY
./sshlogin.exp $TARGET_USER@$TARGET_HOST "$TASKKILL -f -im rsync.exe"
$SSH -i $KEY $TARGET_USER@$TARGET_HOST "rm rsyncd.pid vss-setvar.cmd"

# UPDATE THE MTIME TO REFELCT THE SNAPSHOT TIME
$TOUCH $BACKUPDIR/current

# MAKE HARDLINK COPY
$CP -al $CURRENT/* $NOW

# REMOVE OLD BACKUPS
for FILE in "$( $FIND $OLD -maxdepth 1 -type d -mtime +$DAYS )"
do
  $RM -Rf $FILE
  # $ECHO $FILE
done
exit 0</code></p>
<p><strong>sshlogin</strong>
<code>#!/usr/bin/expect -f

# set Variables

# set password [lindex $argv 0]
set host [lindex $argv 0]
set scriptname [lindex $argv 1]
set timeout -1
# now connect to remote UNIX box (ipaddr) with given script to execute
spawn ssh -p 22 $host $scriptname
match_max 100000

expect {
       -re ".*Are.*.*yes.*no.*" {
       send "yes\n"
        expect {
          "&gt;" { }
          "$" { }
        }
       exp_continue
       #look for the password prompt
       }

       "assword:" {
       send -- "password123\n"
        expect {
          "&gt;" { }
          "$" { }
        }
       #the expect command will now return
       }
       
       default {
        send_user "Login failed\n"
        exit
       }
}

sleep 2
send_user "Finished\n"
exit</code></p>
<p><strong>rsync.secret</strong>
<code>password123</code></p>
<ul>
<li>For the Target machine we&#8217;ll need a CMD and VB Script, as well as a configuration file for the rSync daemon.</li>
<li>Volume shadow copies in XP and Vista are temporary and only exist as long as the process that created it exists.  In our case the process that creates the volume shadow copy is vshadow.exe (Windows 2003 users can create a persistent volume shadow copy).  Fortunately, vshadow.exe allows us to send it a CMD script to execute &#8211; hence the purpose of vsrsync.cmd below.  vsrsync.cmd executes after the volume shadow copy is created but before it is destroyed.  During this time we need to use dosdev to map the volume shadow copy to a standard Windows drive letter that rSync can read from.  Next, it will create the rSync daemon using a configuration file and secrets file.  And finally, after the remote script kills the rSync daemon process, the CMD script will unmap the volume shadow copy drive letter.</li>
<li>Because we need to initiate the rSync transfer after the volume shadow copy is created but before it is destroyed, we need a small VB Script that halts the remote script from executing until it detects the daemon is ready to begin the transfer.  It performs this check by watching for the rSyncd pid file.</li>
</ul>
<p><strong>rsyncd.secrets</strong>
<code>Administrator:password123</code></p>
<p><strong>sleep-rsyncd.vbs</strong>
<code>Const Flag = "C:\Program Files\cwRsync\home\Administrator\rsyncd.pid"

While DoesFileExist(Flag)=0
   wscript.sleep 10000
Wend

function DoesFileExist(FilePath)
Dim fso
   Set fso = CreateObject("Scripting.FileSystemObject")
   if not fso.FileExists(FilePath) then
      DoesFileExist = 0
   else
      DoesFileExist = 1
   end if
   Set fso = Nothing
end function</code></p>
<p><strong>vsrsync.cmd</strong>
<code>@ECHO OFF
call vss-setvar.cmd

SET PATH=%PATH%;"C:\Program Files\cwRsync\bin"

dosdev X: %SHADOW_DEVICE_1%
rsync --daemon --config=rsyncd.conf --no-detach
dosdev -r -d X:</code></p>
<p><strong>rsyncd.conf</strong>
<code>use chroot = false
strict modes = false
pid file = rsyncd.pid
[C]
path = /cygdrive/X/
read only = yes
ignore nonreadable = yes
hosts allow = 192.168.1.2
auth users = Administrator
secrets file = rsyncd.secrets</code></p>
<p>I hope this guide provided some help to anyone wanting to setup something similar.  My setup is largely based on the one covered at <a href="http://www.goodjobsucking.com/?p=62">http://www.goodjobsucking.com/?p=62</a></p>
<h3>Additional notes</h3>
<ul>
<li>If you have files with special characters in the file name, you may need to upgrade your Cygwin DLL to the Unicode aware version.
<ul>
<li><a href="http://phaq.phunsites.net/2006/10/28/interoperability-problems-samba-windows-rsync-and-unicode/">http://phaq.phunsites.net/2006/10/28/interoperability-problems-samba-windows-rsync-and-unicode/</a></li>
<li><a href="http://www.okisoft.co.jp/esc/utf8-cygwin/">http://www.okisoft.co.jp/esc/utf8-cygwin/</a></li>
</ul>
</li>
<li>There are a lot of moving parts in the above script.  If something hangs or you just need to abort and try again you may need to reboot the Windows machine to ensure all the pieces are ready for another trial.  In my experience, however, killing the rSync process from Task Manager was frequently enough to bring the entire script back to a state where I could try another test run.</li>
<li>cwRsync will simply abort execution if the pid file already exists.  My script has an extra delete before vshadow.exe is called to try and avoid this problem.</li>
<li>vshadow.exe will fail on XP and Vista if another instance of it is already running on the same volume.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2008/12/a-multiplatform-backup-solution-with-rsync-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Multiplatform Backup Solution with rSync: Part 1</title>
		<link>http://www2.bluhelix.com:81/2008/12/a-multiplatform-backup-solution-with-rsync-part-1/</link>
		<comments>http://www2.bluhelix.com:81/2008/12/a-multiplatform-backup-solution-with-rsync-part-1/#comments</comments>
		<pubDate>Sun, 21 Dec 2008 04:16:17 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Inside BluHelix]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.bluhelix.com/?p=160</guid>
		<description><![CDATA[A long time ago I used to be very good at making regular backups of my system. It was a very manual process &#8211; I didn&#8217;t use any software. I simply kept my files in a few places and periodically synced the folders up with a second computer. It worked well but I have a [...]]]></description>
			<content:encoded><![CDATA[<p>A long time ago I used to be very good at making regular backups of my system.  It was a very manual process &#8211; I didn&#8217;t use any software.  I simply kept my files in a few places and periodically synced the folders up with a second computer.  It worked well but I have a lot more than a few megabytes of data now, and more than one computer with data to backup.</p>
<p>For my personal computer, I have used file sync tools like <a href="http://www.2brightsparks.com/downloads.html">SyncBack</a> to maintain a mirror of my documents on an external hard drive.  However, with a web server and other computers in my network a more centralized approach became very appealing.</p>
<p>Having a spare computer lying around and enough money to invest in a pair of hard drives I set out to give an old PC a new purpose in life &#8211; to become my network&#8217;s dedicated backup server.  I didn&#8217;t want to have to maintain scheduling policies on each machine (what a pain) so I also wanted my server to be able to pull backups directly from each computer in my network.  Additionally, I wanted to keep the option of setting up the backup server in a remote location to further protect my data &#8211; so Samba was something I wanted to avoid, if possible.</p>
<p>At first I was drawn to a project called <a href="http://lifehacker.com/362062/create-your-own-cross+platform-backup-server">RESTORE</a> which is an easy to get rolling multiplatform backup system built on Xubuntu.  I had difficulty getting it to backup a Windows system, however.  SFTP to a Windows machine seemed to be broken and Windows share connections was not reliable.  And again, I preferred to stay away from Windows shares anyhow.</p>
<p>So I turned my attention to an old tool in the *nix world known as rSync.  My friend at <a href="http://benford.bluhelix.com/">Benford Does Stuff</a> pointed me to the tool.  He setup a backup server that used rSync to mirror a web server we used to maintain at our University.  After sending me to a pair of HowTo guides I was well on my way to scripting my own incremental snapshot backup of my web server.</p>
<p><strong>You may find the guides below</strong></p>
<ul>
<li> <a href="http://www.howtoforge.com/mirroring_with_rsync">Mirror Your Web Site With rsync</a></li>
<li><a href="http://www.howtoforge.com/rsync_incremental_snapshot_backups">Create Incremental Snapshot-style Backups With rSync And SSH</a></li>
</ul>
<p>The above solution works great and I am using exactly that to snapshot my web server running Ubuntu Server 8.04.</p>
<p>With some minor tweaking the above script will snapshot a Windows-based computer decently.  In particular, however, the script falls short when attempting to backup files that are currently open by the user or operating system.  Open files on a Windows system are locked and cannot be read by other applications.  There is a resolution but instructions and examples are rare, and I spent a considerable amount of time getting it working right in my setup.  In my next article I will detail the modifications I made to Stephan Jau&#8217;s incremental snapshot script to mirror my windows systems.</p>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2008/12/a-multiplatform-backup-solution-with-rsync-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>More Memory!</title>
		<link>http://www2.bluhelix.com:81/2008/11/more-memory/</link>
		<comments>http://www2.bluhelix.com:81/2008/11/more-memory/#comments</comments>
		<pubDate>Tue, 11 Nov 2008 04:30:21 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Inside BluHelix]]></category>

		<guid isPermaLink="false">http://blog.bluhelix.com/?p=158</guid>
		<description><![CDATA[The last of the scheduled hardware upgrades for a while has just completed. The total memory on the server has been extended to an even 2.0 GB. Quite a change from 3 years ago when we ran the server on a windows machine with 92 MB of RAM]]></description>
			<content:encoded><![CDATA[<p>The last of the scheduled hardware upgrades for a while has just completed.  The total memory on the server has been extended to an even 2.0 GB.</p>
<p>Quite a change from 3 years ago when we ran the server on a windows machine with 92 MB of RAM <img src='http://www2.bluhelix.com:81/wordpress/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2008/11/more-memory/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hamachi Web Status Indicator Classes</title>
		<link>http://www2.bluhelix.com:81/2008/10/hamachi-web-status-indicator-classes/</link>
		<comments>http://www2.bluhelix.com:81/2008/10/hamachi-web-status-indicator-classes/#comments</comments>
		<pubDate>Wed, 08 Oct 2008 03:36:24 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Studio Announcement]]></category>

		<guid isPermaLink="false">http://blog.bluhelix.com/?p=156</guid>
		<description><![CDATA[It&#8217;s been about a year since I last released something, so I am going to throw these little utility classes up. A long time ago I downloaded some PHP script that demonstrated parsing LogMeIn&#8217;s Hamachi web status indicator to build a little Hamachi list for a web site. I cannot for the life of me [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been about a year since I last released something, so I am going to throw these little utility classes up.</p>
<p>A long time ago I downloaded some PHP script that demonstrated parsing LogMeIn&#8217;s Hamachi web status indicator to build a little Hamachi list for a web site.  I cannot for the life of me find the little script &#8211; I suspect it was just a forum post I found.  Anyway, over the years I rewrote the damn thing three times over, trying to get it into a more generalized form.  Thus I introduce my two Hamachi status classes.</p>
<p>HamachiClient &#8211; represents an individual Hamachi client.  Basically, just instantiate one of these buggers with a 5.x.x.x IP and then ask it what its state is.  Pretty simple I hope.</p>
<p>HamachiList &#8211; can contain multiple HamachiClient classes.  You can instantiate this class without any parameters and add the IP addresses later. or you can feed it one array of IP addresses and aliases in the beginning.  Then either ask it for the state of each client, or have it return the complete array.  I also included a method to output an HTML list that can be formatted with CSS.</p>
<p>Note: I also got annoyed with the fact that only clients version 1.0.x can enable the web status indicator.  The obvious implications are that Linux and Mac versions of Hamachi are left in the cold.  I included the possibility of pinging these clients if the web indicator doesn&#8217;t work.  That&#8217;s an advanced parameter and you&#8217;ll have to look in the code to figure out what to do <img src='http://www2.bluhelix.com:81/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Please visit the snippets section to download&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2008/10/hamachi-web-status-indicator-classes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Upgraded</title>
		<link>http://www2.bluhelix.com:81/2008/09/upgraded/</link>
		<comments>http://www2.bluhelix.com:81/2008/09/upgraded/#comments</comments>
		<pubDate>Mon, 22 Sep 2008 14:21:08 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Inside BluHelix]]></category>

		<guid isPermaLink="false">http://blog.bluhelix.com/?p=154</guid>
		<description><![CDATA[Very covert-like, this server was completely rebuild on 9/20 without any posts announcing it! Alright, so news has been incredibly dry around here for some time. Just take a look around and everything is about boring servers. Sorry folks, it will probably be a bit before anything exciting happens. However, the server upgrade is nice. [...]]]></description>
			<content:encoded><![CDATA[<p>Very covert-like, this server was completely rebuild on 9/20 without any posts announcing it!  Alright, so news has been incredibly dry around here for some time.  Just take a look around and everything is about boring servers.  Sorry folks, it will probably be a bit before anything exciting happens.</p>
<p>However, the server upgrade is <em>nice</em>.  It now runs on a hyper threaded P4 clocking at 2.8 GHz.  That&#8217;s twice as fast as the previous CPU in clock speed alone.  I also threw in two extra sticks of RAM since the new motherboard has two slots more than the previous system.  We&#8217;re only at 1.5 GB RAM at this point but I&#8217;m looking into upgrades.  Incidentally, the new motherboard only has SATA connectors so I had to toss out the old hard drives and add a single large-ish one.  So the server got a bit of unplanned capacity in the upgrade as well.</p>
<p>We are in the process of gearing our second linux server.  More (boring) information to come.</p>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2008/09/upgraded/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Moving</title>
		<link>http://www2.bluhelix.com:81/2008/08/moving/</link>
		<comments>http://www2.bluhelix.com:81/2008/08/moving/#comments</comments>
		<pubDate>Fri, 29 Aug 2008 00:40:21 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Studio Announcement]]></category>

		<guid isPermaLink="false">http://blog.bluhelix.com/?p=152</guid>
		<description><![CDATA[All our servers will be shutting down on Saturday, August 30th. I will try to get them back up on Sunday, but it might take until Monday to be back online.]]></description>
			<content:encoded><![CDATA[<p>All our servers will be shutting down on Saturday, August 30th.  I will try to get them back up on Sunday, but it might take until Monday to be back online.</p>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2008/08/moving/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
