<?xml version="1.0"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Jonathan Perkin</title>
    <link>http://www.perkin.org.uk/</link>
    <atom:link href="http://www.perkin.org.uk/rss.xml" rel="self" type="application/rss+xml" />
    <description>Jonathan Perkin</description>
    <language>en-gb</language>
    <pubDate>Wed, 22 Feb 2012 16:16:04 +0000</pubDate>
    <lastBuildDate>Wed, 22 Feb 2012 16:16:04 +0000</lastBuildDate>

    
    <item>
      <title>New blog design</title>
      <link>http://www.perkin.org.uk/blog/2012/02/new-blog/</link>
      <pubDate>Mon, 20 Feb 2012 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2012/02/new-blog</guid>
      <description>&lt;p&gt;I am a minimalist at heart, and I love command line interfaces and text files.&lt;/p&gt;

&lt;p&gt;However, I&amp;#8217;m also pragmatic, and so for a long time my blog has been powered by Wordpress, which made it relatively easy to manage content and design. I just didn&amp;#8217;t want the hassle of maintaining something myself.&lt;/p&gt;

&lt;p&gt;Somewhere along the way recently I stumbled across &lt;a href='https://github.com/mojombo/jekyll'&gt;Jekyll&lt;/a&gt;, and the idea of generating a static site from templates.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;d seen a few sites I liked the look of, and I loved the idea of simplifying my site (and editing posts in vim!), and so the end result is the site you see now. The theme is based on &lt;a href='http://skim.la/'&gt;skim.la&lt;/a&gt;&amp;#8217;s site.&lt;/p&gt;

&lt;p&gt;I pondered implementing something like &lt;a href='http://disqus.com/'&gt;disqus&lt;/a&gt; for comments, but honestly I get so few proper responses, compared to the hundreds and hundreds of spam attempts, that it&amp;#8217;s not worth it - if you want to comment on a post, just use twitter (I&amp;#8217;ll probably implement a little button to do that at some point).&lt;/p&gt;

&lt;p&gt;Also, I got rid of categories, simpler to just have tags.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s likely I&amp;#8217;ve messed up conversion of my old blog posts, as I did them all manually. If you spot anything obviously broken, please let me know. One of the great things of the Jekyll approach is that you can simply manage your site via github, and so if you prefer you can comment on breakages &lt;a href='https://github.com/jperkin/www.perkin.org.uk'&gt;here&lt;/a&gt;!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Set up anonymous FTP upload on Oracle Linux</title>
      <link>http://www.perkin.org.uk/blog/2012/01/set-up-anonymous-ftp-upload-on-oracle-linux/</link>
      <pubDate>Wed, 11 Jan 2012 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2012/01/set-up-anonymous-ftp-upload-on-oracle-linux</guid>
      <description>&lt;p&gt;Just because this took a little longer than I expected, here&amp;#8217;s a quick howto for setting up an anonymous FTP drop-off on Oracle Linux, which I use as a simple way to transfer files out of my Virtual Machines.&lt;/p&gt;

&lt;h2 id='install_vsftpd'&gt;Install vsftpd&lt;/h2&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo yum -y install vsftpd
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configure_iptables'&gt;Configure iptables&lt;/h2&gt;

&lt;p&gt;As FTP is a more complicated protocol than most, there is a special netfilter module required in order to correctly keep track of connections.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; You will perhaps want to change the insert number here.
&lt;span class='gp'&gt;$&lt;/span&gt; sudo iptables -I INPUT 4 -m state --state NEW -p tcp --dport 21 -j ACCEPT
&lt;span class='gp'&gt;$&lt;/span&gt; sudo /etc/init.d/iptables save
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Add &lt;code&gt;nf_conntrack_ftp&lt;/code&gt; to &lt;code&gt;IPTABLES_MODULES&lt;/code&gt;&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo vi /etc/sysconfig/iptables-config
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then load the module rather than reboot&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo modprobe nf_conntrack_ftp
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='create_incoming'&gt;Create /incoming&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;/incoming&lt;/code&gt; area and ensure it has the correct file permissions and SELinux context. This is the bit which had me stumped for a little while, as I didn&amp;#8217;t know about &lt;code&gt;allow_ftpd_anon_write&lt;/code&gt;, and while I normally just disable SELinux, I do also like to know how things should work (and be able to write about them!):&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo mkdir /var/ftp/incoming
&lt;span class='gp'&gt;$&lt;/span&gt; sudo chown ftp:ftp /var/ftp/incoming

&lt;span class='gp'&gt;#&lt;/span&gt; This allows anonymous users to upload, but not see what&lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;s in the directory
&lt;span class='gp'&gt;$&lt;/span&gt; sudo chmod 750 /var/ftp/incoming

&lt;span class='gp'&gt;$&lt;/span&gt; sudo chcon -u system_u -t public_content_rw_t /var/ftp/incoming
&lt;span class='gp'&gt;$&lt;/span&gt; sudo setsebool &lt;span class='nv'&gt;allow_ftpd_anon_write&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configure_vsftpd'&gt;Configure vsftpd&lt;/h2&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo vi /etc/vsftpd/vsftpd.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;anon_upload_enable=YES
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='startup'&gt;Startup&lt;/h2&gt;

&lt;p&gt;Finally, enable and start vsftpd:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo chkconfig vsftpd on
&lt;span class='gp'&gt;$&lt;/span&gt; sudo /etc/init.d/vsftpd start
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And that&amp;#8217;s it, you should now be able to FTP as anonymous and upload files into &lt;code&gt;/incoming&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Kickstart Oracle Linux in VirtualBox</title>
      <link>http://www.perkin.org.uk/blog/2012/01/kickstart-oracle-linux-in-virtualbox/</link>
      <pubDate>Mon, 09 Jan 2012 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2012/01/kickstart-oracle-linux-in-virtualbox</guid>
      <description>&lt;p&gt;In my previous post I configured an Ubuntu laptop as a Kickstart install server for a physical machine I wanted to build.&lt;/p&gt;

&lt;p&gt;Now that everything is configured for automated installs, it makes sense to use the same infrastructure to install virtual machines too. Everything can be done from the command line, and new virtual machines can be provisioned very quickly.&lt;/p&gt;

&lt;p&gt;Again, I will use Oracle Linux 6.2 as an example.&lt;/p&gt;

&lt;h2 id='create_virtual_machine'&gt;Create Virtual Machine&lt;/h2&gt;

&lt;p&gt;These commands create a new virtual machine, including disk, and configures it for network booting. If you don&amp;#8217;t already have VirtualBox installed:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo apt-get install virtualbox
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Set the name of the virtual machine as it appears in VirtualBox, this variable is then used throughout:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;VM&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;Oracle Linux 6.2&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Create the VM:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage createvm --name &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt; --ostype &lt;span class='s2'&gt;&amp;quot;Oracle_64&amp;quot;&lt;/span&gt; --register
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Create the hard disk (32GB expanding) and attach it via SATA. Note that I store my VMs in &lt;code&gt;${HOME}/VirtualBox&lt;/code&gt; rather than the default &lt;code&gt;${HOME}/VirtualBox VMs&lt;/code&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage createhd --filename &lt;span class='s2'&gt;&amp;quot;VirtualBox/${VM}/${VM}.vdi&amp;quot;&lt;/span&gt; --size 32768

&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage storagectl &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt; --name &lt;span class='s2'&gt;&amp;quot;SATA Controller&amp;quot;&lt;/span&gt; --add sata &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='go'&gt;    --controller IntelAHCI&lt;/span&gt;

&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage storageattach &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt; --storagectl &lt;span class='s2'&gt;&amp;quot;SATA Controller&amp;quot;&lt;/span&gt; --port 0 &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='go'&gt;    --device 0 --type hdd --medium &amp;quot;VirtualBox/${VM}/${VM}.vdi&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Default RAM is 128MB, Oracle Linux installer requires at least 512MB however. Once installed we can drop back down to 256MB or so:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt; --memory 512
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Configure boot order. Put disk first, as on the first boot there is nothing on it so it falls through to PXE for install, then after the install the disk is bootable.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt; --boot1 disk --boot2 net --boot3 none --boot4 none
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Change NIC type from the default e1000, as a vanilla VirtualBox install does not include the firmware necessary to network boot from that device – it is available in the &amp;#8220;VirtualBox Extension Pack&amp;#8221; add-on. Switch to a plain PCNet Fast III which does include PXE firmware.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt; --nictype1 Am79C973
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;VirtualBox does have the ability to serve TFTP directly from the file system by placing files inside &lt;code&gt;${HOME}/.VirtualBox/TFTP/&lt;/code&gt; but I prefer to just use the network as it&amp;#8217;s already configured.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt; --nattftpserver1 10.0.2.2
&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt; --nattftpfile1 pxelinux.0
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configure_pxelinuxkickstart'&gt;Configure pxelinux/kickstart&lt;/h2&gt;

&lt;p&gt;We just need a couple of tweaks to the configs from the last blog entry, as the network addresses are different inside VirtualBox, and we also may want a different kickstart configuration.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo vi /var/lib/tftpboot/pxelinux.cfg/default
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I just amended the existing entry to point to 10.0.2.2 which is the address of the machine running VirtualBox, and a different ks-vm.cfg kickstart configuration file, but you could also create a new label if you wanted to regularly switch between different configurations:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;LABEL ol6.2
    KERNEL /ol6.2/vmlinuz
    APPEND initrd=/ol6.2/initrd.img ks=http://10.0.2.2/ks-vm.cfg
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;For virtual machines I use a slightly different configuration compared to previously. I&amp;#8217;ve only shown the changes below, not the full file:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo cp /usr/share/nginx/www/ks.cfg /usr/share/nginx/www/ks-vm.cfg
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;br /&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;# Update network configuration for DHCP instead of static
network --bootproto=dhcp
url --url=http://10.0.2.2/ol6.2

# Don&amp;#39;t specify disks, just use default layout
bootloader --location=mbr --driveorder=sda
clearpart --all --initlabel

# Just add &amp;#39;screen&amp;#39; to the default set of @base and @core packages.
%packages
screen
%end
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='start_virtual_machine'&gt;Start Virtual Machine&lt;/h2&gt;

&lt;p&gt;All that&amp;#8217;s left to do is to boot up the VM, and everything else should run automatically.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VirtualBox --startvm &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;All done!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Kickstart Oracle Linux from Ubuntu</title>
      <link>http://www.perkin.org.uk/blog/2012/01/kickstart-oracle-linux-from-ubuntu/</link>
      <pubDate>Mon, 09 Jan 2012 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2012/01/kickstart-oracle-linux-from-ubuntu</guid>
      <description>&lt;p&gt;As my new job involves working on Oracle Linux, I figured I should migrate my home server to it, which would also mean I could move it to a proper RAID10 configuration rather than relying on multiple RAID1′s.&lt;/p&gt;

&lt;p&gt;My laptop runs Ubuntu, and I wanted to install the server from it using PXE and Kickstart, so here&amp;#8217;s how I did it.&lt;/p&gt;

&lt;h2 id='configure_dhcpd'&gt;Configure dhcpd&lt;/h2&gt;

&lt;p&gt;DHCP is required for two things, to give the server its network configuration, and to point it at the pxe boot loader we want to use.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo apt-get install isc-dhcp-server
&lt;span class='gp'&gt;$&lt;/span&gt; sudo vi /etc/dhcp/dhcpd.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here&amp;#8217;s the configuration I used, which says to configure 192.168.2.0/24 with a dynamic DHCP range between 192.168.2.100 – 192.168.2.200, and to boot machines using pxelinux.0 which is relative to the TFTP root directory (configured in the next section):&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;subnet 192.168.2.0 netmask 255.255.255.0 {
    range 192.168.2.100 192.168.2.200;
    filename &amp;quot;pxelinux.0&amp;quot;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The isc-dhcp-server install automatically tries to start the server, but will fail as it isn&amp;#8217;t configured, so we restart it now that there is a working configuration installed&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo /etc/init.d/isc-dhcp-server restart
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configure_tftpd'&gt;Configure tftpd&lt;/h2&gt;

&lt;p&gt;TFTP is a simple protocol used to transfer files over the network, and due to its simplicity it is the primary way to network boot, as it can be easily embedded into firmware.&lt;/p&gt;

&lt;p&gt;All we need to do is install the TFTP daemon and syslinux which includes the pxe boot loader, then put the pxelinux file into the tftproot area:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo apt-get install syslinux tftpd-hpa
&lt;span class='gp'&gt;$&lt;/span&gt; sudo cp /usr/lib/syslinux/pxelinux.0 /var/lib/tftpboot
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configure_oracle_linux_dvd'&gt;Configure Oracle Linux DVD&lt;/h2&gt;

&lt;p&gt;To save space on the laptop we can just mount the DVD read-only and install from that:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo mkdir /media/ol6.2
&lt;span class='gp'&gt;$&lt;/span&gt; sudo mount -o loop,ro /path/to/OracleLinux-R6-U2-Server-x86_64-dvd.iso /media/ol6.2
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;However, we do need to copy the kernel and initrd image from the DVD into the tftproot as they are required for booting:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo mkdir /var/lib/tftpboot/ol6.2 /var/lib/tftpboot/pxelinux.cfg
&lt;span class='gp'&gt;$&lt;/span&gt; sudo cp -a /mnt/images/pxeboot/&lt;span class='o'&gt;{&lt;/span&gt;initrd.img,vmlinuz&lt;span class='o'&gt;}&lt;/span&gt; /var/lib/tftpboot/ol6.2/
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configure_pxelinux'&gt;Configure pxelinux&lt;/h2&gt;

&lt;p&gt;All that&amp;#8217;s left for the PXE stage is to configure the boot loader, and tell it what kernel and initrd we want to use:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo vi /var/lib/tftpboot/pxelinux.cfg/default
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This configuration has just one entry which is booted after a short wait, but pxelinux has many more options, including the ability to boot from local disk.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;DEFAULT	ol6.2
PROMPT 1
TIMEOUT 5

LABEL ol6.2
    KERNEL /ol6.2/vmlinuz
    APPEND initrd=/ol6.2/initrd.img ks=http://192.168.2.1/ks.cfg
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Note the ks argument which specifies the kickstart file we will use, that and the web server required to serve it will be set up next.&lt;/p&gt;

&lt;h2 id='configure_nginx'&gt;Configure nginx&lt;/h2&gt;

&lt;p&gt;I chose nginx as it is small and simple to configure, but any web server will do.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo apt-get install nginx
&lt;span class='gp'&gt;$&lt;/span&gt; sudo vi /etc/nginx/sites-available/default
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The install will be performed over HTTP, so we need to make the DVD we mounted earlier available. This entry in the &lt;code&gt;server { }&lt;/code&gt; section makes the DVD available via http://192.168.2.1/ol6.2/:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;server {
[...]
    location /ol6.2 {
        root /media;
        autoindex on;
        allow all;
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then start nginx (unlike isc-dhcp-server this isn&amp;#8217;t done automatically):&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;$ sudo /etc/init.d/nginx start
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configure_kickstart'&gt;Configure kickstart&lt;/h2&gt;

&lt;p&gt;Finally, we create a kickstart configuration which specifies exactly how our target machine is to be installed, and this allows a completely unattended installation.&lt;/p&gt;

&lt;p&gt;Ideally I should create a specific area for holding files like this, but as a quick hack I simply put it into the default nginx web root (and thus available as http://192.168.2.1/ks.cfg as configured earlier in the pxelinux.cfg/default file:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;sudo vi /usr/share/nginx/www/ks.cfg
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here is my ks.cfg file in full. The only thing missing is a rootpw line to automatically set a root password, however for maximum security I am happy to forego a completely unattended installation and instead have the installer prompt me to type it in during the install.&lt;/p&gt;

&lt;p&gt;Some notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UK keyboard language and timezone selected.&lt;/li&gt;

&lt;li&gt;Automatically reboot when the installer is finished.&lt;/li&gt;

&lt;li&gt;Point to the Oracle Linux DVD using the url directive.&lt;/li&gt;

&lt;li&gt;I have 4 disks configured with RAID1 for /boot, and RAID10 for swap and /.&lt;/li&gt;

&lt;li&gt;Disks are referred to by path, to ensure correct ordering.&lt;/li&gt;

&lt;li&gt;A small set of packages are installed, containing just the functionality I require.&lt;/li&gt;

&lt;li&gt;A small %post section is used to perform any fixes I want for the first boot.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;#
# Miscellaneous options.
#
install
keyboard uk
lang en_GB.UTF-8
reboot
selinux --enforcing
timezone Europe/London

#
# User setup.  I&amp;#39;d create my local user here and configure sudoers, but
# kickstart doesn&amp;#39;t yet support creating a user with uid/gid of 1000 (the
# gid is always 500, even if you add the named group first).
#
authconfig --enableshadow --passalgo=sha512

#
# Networking.  The &amp;#39;network&amp;#39; line needs to be on a single line
# for kickstart to work - it is only split here for the blog.
#
firewall --service=ssh
network --bootproto=static \
        --hostname=gromit.adsl.perkin.org.uk \
        --ip=192.168.2.10 \
        --netmask=255.255.255.0 \
        --gateway=192.168.2.1 \
        --nameserver=193.178.223.141,208.72.84.24 \
        --ipv6=auto
url --url=http://192.168.2.1/ol6.2

#
# Disk configuration.
#
bootloader --location=mbr --driveorder=sda,sdb,sdc,sdd
clearpart --all --initlabel
#
# /boot (RAID1 necessary as booting from RAID10 isn&amp;#39;t supported)
#
part raid.00 --asprimary --size=1024 --ondisk=/dev/disk/by-path/pci-*-0*0
part raid.01 --asprimary --size=1024 --ondisk=/dev/disk/by-path/pci-*-1*0
part raid.02 --asprimary --size=1024 --ondisk=/dev/disk/by-path/pci-*-2*0
part raid.03 --asprimary --size=1024 --ondisk=/dev/disk/by-path/pci-*-3*0
raid /boot --level=1 --device=md0 --fstype=ext4 raid.00 raid.01 raid.02 raid.03
#
# swap, RAID10 of size RAM+2GB, give or take..
#
part raid.10 --asprimary --size=6144 --ondisk=/dev/disk/by-path/pci-*-0*0
part raid.11 --asprimary --size=6144 --ondisk=/dev/disk/by-path/pci-*-1*0
part raid.12 --asprimary --size=6144 --ondisk=/dev/disk/by-path/pci-*-2*0
part raid.13 --asprimary --size=6144 --ondisk=/dev/disk/by-path/pci-*-3*0
raid swap --level=10 --device=md1 --fstype=swap raid.10 raid.11 raid.12 raid.13
#
# /, RAID10 of remainder (have to specify an arbitrary --size even with --grow)
#
part raid.20 --asprimary --size=1024 --grow --ondisk=/dev/disk/by-path/pci-*-0*0
part raid.21 --asprimary --size=1024 --grow --ondisk=/dev/disk/by-path/pci-*-1*0
part raid.22 --asprimary --size=1024 --grow --ondisk=/dev/disk/by-path/pci-*-2*0
part raid.23 --asprimary --size=1024 --grow --ondisk=/dev/disk/by-path/pci-*-3*0
raid / --level=10 --device=md2 --fstype=ext4 raid.20 raid.21 raid.22 raid.23

#
# Packages.  @base and @core are pre-selected.
#
%packages
@cifs-file-server
@console-internet --optional
@development
@legacy-unix --optional
@mail-server
@network-server --optional
@network-tools
@nfs-file-server
@web-server
screen
%end

#
# Post-install fix-ups.
#
%post
#
# The &amp;#39;network&amp;#39; directive doesn&amp;#39;t support DNS search paths, so set those
# manually, and disable Network Manager.
#
printf &amp;quot;/^NM_CONTROLLED/s/yes/no/\nw\nq\n&amp;quot; \
  | ed /etc/sysconfig/network-scripts/ifcfg-eth0
printf &amp;quot;/^#/s/.*/search adsl.perkin.org.uk perkin.org.uk/\nw\nq\n&amp;quot; \
  | ed /etc/resolv.conf
#
# Disable unwanted services
#
chkconfig --del cups
%end
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;All done.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Last day at MySQL</title>
      <link>http://www.perkin.org.uk/blog/2011/12/last-day-at-mysql/</link>
      <pubDate>Thu, 22 Dec 2011 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2011/12/last-day-at-mysql</guid>
      <description>&lt;p&gt;Today is my final day working on MySQL. It has been an amazing 4.5 years, and I&amp;#8217;ve loved working on the technical challenges involved in producing a piece of software which runs on so many different platforms, as well as working with so many talented individuals. I have learned a lot, which is just how I like it.&lt;/p&gt;

&lt;p&gt;Times have changed since I first joined MySQL AB, of course. But despite going through two acquisitions, the day to day work hasn&amp;#8217;t changed much at all. I still get to work from home, which is something I am passionate about and feel many companies are missing out on massively by still being stuck in an outdated 20th century mindset. Oracle have continued to invest in MySQL, providing additional headcount and extra hardware. And the vast majority of people I started working with back in 2007 are still with the company (don&amp;#8217;t believe the FUD, folks) and working harder than ever.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m most proud of the work we have done internally to ensure our MySQL releases are in excellent shape. When I first joined, our internal &amp;#8216;PushBuild&amp;#8217; system was very limited, only able to handle a small number of pushes with reduced testing across a few platforms, and the builds produced were completely different to those that were released.&lt;/p&gt;

&lt;p&gt;Nowadays, thanks to the investment made by Sun and Oracle, we have a large server farm producing thousands of builds and hundreds of gigabytes of data every day across all our supported platforms. Those which are based on MySQL 5.5 or newer have additional package verification tests, using chroots and virtual machines, to ensure that the RPM/MSI/etc packages can be installed, run, and uninstalled, all automatically and on every push by developers. We run additional nightly and weekly tests which extend the default set of test suites. Our 5.5+ releases are produced directly in PushBuild. And we are looking to extend this to all MySQL products, not just the Server.&lt;/p&gt;

&lt;p&gt;If the above sounds fun, keep an eye out for job posts, as the Release Engineering team is looking to expand, and they are an amazing group of people to work with.&lt;/p&gt;

&lt;p&gt;I certainly found it fun, which is why I&amp;#8217;m going to continue in that line of work, and stay within Oracle, but move to the Linux group. To be honest, databases have never been a passion of mine, however I am rather fond of Operating Systems, and so I am really looking forward to continuing to work on continuous integration and testing, but with Oracle Linux and Oracle VM instead of MySQL. Plus, it will be nice to go back to a purely technical role – I have learned over the last year or so that management isn&amp;#8217;t really my thing :)&lt;/p&gt;

&lt;p&gt;To all my colleagues, past and present, thank you for the wonderful ride. I have many, many good memories, and hopefully we will keep in touch.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Installing OpenBSD with softraid</title>
      <link>http://www.perkin.org.uk/blog/2011/12/installing-openbsd-with-softraid/</link>
      <pubDate>Thu, 15 Dec 2011 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2011/12/installing-openbsd-with-softraid</guid>
      <description>&lt;p&gt;This is more of a log for me than anything else, but perhaps someone will find this useful.&lt;/p&gt;

&lt;p&gt;OpenBSD includes a software RAID implementation which supports booting in newer snapshots, and I was itching to install the latest version and use it as my file server, which has 4 750GB disks. There is a small bit of preparation work to do prior to installing, which is the bulk of this entry, most of which is based on &lt;a href='http://www.undeadly.org/cgi?action=article&amp;amp;sid=20111002154251'&gt;this undeadly.org article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Grab latest amd64 &lt;a href='http://mirror.bytemark.co.uk/OpenBSD/snapshots/amd64/install50.iso'&gt;snapshot&lt;/a&gt;, boot it, drop into (S)hell mode and set up the disks:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

&lt;span class='nb'&gt;cd&lt;/span&gt; /dev
sh MAKEDEV sd1 sd2 sd3 sd4 sd5
&lt;span class='k'&gt;for &lt;/span&gt;disk in 0 1 2 3
&lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='c'&gt;# Clear beginning of disks..&lt;/span&gt;
  dd &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/dev/zero &lt;span class='nv'&gt;of&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/dev/rsd&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;disk&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;c &lt;span class='nv'&gt;bs&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;1m &lt;span class='nv'&gt;count&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;10

  &lt;span class='c'&gt;# ..and initialise new partition table&lt;/span&gt;
  fdisk -iy sd&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;disk&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;

  &lt;span class='c'&gt;#&lt;/span&gt;
  &lt;span class='c'&gt;# Create BSD disklabel:&lt;/span&gt;
  &lt;span class='c'&gt;#&lt;/span&gt;
  &lt;span class='c'&gt;# - 128m partitions at start to hold kernels for booting&lt;/span&gt;
  &lt;span class='c'&gt;# - 4g spare raid on each disk for testing&lt;/span&gt;
  &lt;span class='c'&gt;# - rest raid for main OS and data&lt;/span&gt;
  &lt;span class='c'&gt;#   - OS and /home on first two mirrored disks&lt;/span&gt;
  &lt;span class='c'&gt;#   - /store on second two mirrored disks&lt;/span&gt;
  &lt;span class='c'&gt;#&lt;/span&gt;
  print &lt;span class='s2'&gt;&amp;quot;a a\n\n128m\n\na d\n\n4g\nraid\na e\n\n\nraid\nw\nq\n&amp;quot;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
    | disklabel -E sd&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;disk&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;

  &lt;span class='c'&gt;# Clear beginning of raid partitions&lt;/span&gt;
  dd &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/dev/zero &lt;span class='nv'&gt;of&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/dev/rsd&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;disk&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;d &lt;span class='nv'&gt;bs&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;1m &lt;span class='nv'&gt;count&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;10
  dd &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/dev/zero &lt;span class='nv'&gt;of&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/dev/rsd&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;disk&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;e &lt;span class='nv'&gt;bs&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;1m &lt;span class='nv'&gt;count&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;10
&lt;span class='k'&gt;done&lt;/span&gt;

&lt;span class='c'&gt;# Create RAID1 mirrors&lt;/span&gt;
bioctl -c 1 -l sd0e,sd1e softraid0
bioctl -c 1 -l sd2e,sd3e softraid0

&lt;span class='c'&gt;# Exit shell and start the (I)nstall&lt;/span&gt;
&lt;span class='nb'&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As for the install, go with the sensible defaults, other than:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;change keyboard layout to &amp;#8216;uk&amp;#8217;&lt;/li&gt;

&lt;li&gt;manually configure network, enable rtsol&lt;/li&gt;

&lt;li&gt;start ntpd&lt;/li&gt;

&lt;li&gt;do not expect to run X&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When it comes to disk selection, choose sd4 as the root disk, and use the following layout:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;# partition  size  mount
  sd4a       1G    /
  sd4b       8G    swap
  sd4d       1G    /tmp
  sd4e       8G    /var
  sd4f       16G   /usr
  sd4h       rest  /home
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;then initialise sd5 with:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;# partition  size  mount
  sd5a       2G    /altroot
  sd5d       8G    /scratch
  sd5e       rest  /store
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Install the full OS, set the correct timezone, then before rebooting initialize the boot partitions and copy the kernels to them. Doing this on all of them means we can boot from any disk.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

&lt;span class='k'&gt;for &lt;/span&gt;disk in 0 1 2 3
&lt;span class='k'&gt;do&lt;/span&gt;
&lt;span class='k'&gt;  &lt;/span&gt;newfs sd&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;disk&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;a
  mount /dev/sd&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;disk&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;a /mnt2
  cp /mnt/bsd* /mnt2
  umount /mnt2
&lt;span class='k'&gt;done&lt;/span&gt;
eject cd0a
reboot
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Job done.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Create VirtualBox VM from the command line</title>
      <link>http://www.perkin.org.uk/blog/2011/09/create-virtualbox-vm-from-the-command-line/</link>
      <pubDate>Wed, 21 Sep 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2011/09/create-virtualbox-vm-from-the-command-line</guid>
      <description>&lt;p&gt;As something of a follow-up post to the previous entry, here&amp;#8217;s a quick recipe for creating a Virtual Machine using the VirtualBox command line tools:&lt;/p&gt;

&lt;p&gt;We&amp;#8217;re using Windows Server 2008 64bit as an example, modify to taste.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;VM&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;Windows-2008-64bit&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Create a 32GB &amp;#8216;dynamic&amp;#8217; disk.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage createhd --filename &lt;span class='nv'&gt;$VM&lt;/span&gt;.vdi --size 32768
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can get a list of the OS types VirtualBox recognises using:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage list ostypes
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then copy the most appropriate one into here.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage createvm --name &lt;span class='nv'&gt;$VM&lt;/span&gt; --ostype &lt;span class='s2'&gt;&amp;quot;Windows2008_64&amp;quot;&lt;/span&gt; --register
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Add a SATA controller with the dynamic disk attached.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage storagectl &lt;span class='nv'&gt;$VM&lt;/span&gt; --name &lt;span class='s2'&gt;&amp;quot;SATA Controller&amp;quot;&lt;/span&gt; --add sata &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='gp'&gt;&amp;gt;&lt;/span&gt;  --controller IntelAHCI
&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage storageattach &lt;span class='nv'&gt;$VM&lt;/span&gt; --storagectl &lt;span class='s2'&gt;&amp;quot;SATA Controller&amp;quot;&lt;/span&gt; --port 0 &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='gp'&gt;&amp;gt;&lt;/span&gt;  --device 0 --type hdd --medium &lt;span class='nv'&gt;$VM&lt;/span&gt;.vdi
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Add an IDE controller with a DVD drive attached, and the install ISO inserted into the drive:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage storagectl &lt;span class='nv'&gt;$VM&lt;/span&gt; --name &lt;span class='s2'&gt;&amp;quot;IDE Controller&amp;quot;&lt;/span&gt; --add ide
&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage storageattach &lt;span class='nv'&gt;$VM&lt;/span&gt; --storagectl &lt;span class='s2'&gt;&amp;quot;IDE Controller&amp;quot;&lt;/span&gt; --port 0 &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='gp'&gt;&amp;gt;&lt;/span&gt;  --device 0 --type dvddrive --medium /path/to/windows_server_2008.iso
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Misc system settings.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='nv'&gt;$VM&lt;/span&gt; --ioapic on
&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='nv'&gt;$VM&lt;/span&gt; --boot1 dvd --boot2 disk --boot3 none --boot4 none
&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='nv'&gt;$VM&lt;/span&gt; --memory 1024 --vram 128
&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='nv'&gt;$VM&lt;/span&gt; --nic1 bridged --bridgeadapter1 e1000g0
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Configuration is all done, boot it up! If you&amp;#8217;ve done this one a remote machine, you can RDP to the console via &lt;code&gt;vboxhost:3389&lt;/code&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxHeadless -s &lt;span class='nv'&gt;$VM&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Once you have configured the operating system, you can shutdown and eject the DVD.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage storageattach &lt;span class='nv'&gt;$VM&lt;/span&gt; --storagectl &lt;span class='s2'&gt;&amp;quot;IDE Controller&amp;quot;&lt;/span&gt; --port 0 &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='gp'&gt;&amp;gt;&lt;/span&gt;  --device 0 --type dvddrive --medium none
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Finally, it&amp;#8217;s a good idea to take regular snapshots so that you can always revert back to a known-good state rather than having to completely re-install.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage snapshot &lt;span class='nv'&gt;$VM&lt;/span&gt; take &amp;lt;name of snapshot&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And, if you need to revert back to a particular snapshot:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage snapshot &lt;span class='nv'&gt;$VM&lt;/span&gt; restore &amp;lt;name of snapshot&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Creating chroots for fun and MySQL testing</title>
      <link>http://www.perkin.org.uk/blog/2011/09/creating-chroots-for-fun-and-mysql-testing/</link>
      <pubDate>Wed, 14 Sep 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2011/09/creating-chroots-for-fun-and-mysql-testing</guid>
      <description>&lt;p&gt;Virtualisation is all the rage today, however there are still a few cases where good old-fashioned Unix chroot is still applicable, and testing MySQL across multiple platforms and architectures is one of those cases.&lt;/p&gt;

&lt;p&gt;At Oracle we do full automated package verification testing of our MySQL server binaries prior to release, which attempts to install the package, start the server, run some functionality testing, then uninstall. It is of course highly desirable that the testing environment this is performed in is as close to a clean install of the target operating system as possible, to avoid problems such as our packages depending upon some local changes or packages we may have installed which won&amp;#8217;t be available on a customer system.&lt;/p&gt;

&lt;p&gt;Given the large number of platforms and architectures that MySQL supports, going the virtualisation route would mean having to use many different products: VirtualBox for x86, zones for SPARC, qemu for ia64/PA-RISC/others (if it even supports them), and this gets complicated quickly and is not very maintainable. Thus I chose to use chroot as much as possible. In addition, it&amp;#8217;s much faster and less intensive on resources to use a chroot than boot up an entire OS image each time.&lt;/p&gt;

&lt;p&gt;I built all images directly from the original installation images (DVD, ISO, RPM, etc), to ensure that there was no contamination from our build environment or local install scripts in the image – they should be as close to what a normal user or customer will be running in their setup. From the install image, the packages are installed to a temporary directory, some final modifications are made, then the directory is tarred up ready to be extracted by the test framework and used.&lt;/p&gt;

&lt;p&gt;Here are some operating system specific examples, which set up an extracted chroot image into &lt;code&gt;${CHROOTDIR}&lt;/code&gt;. There may be additional steps required to get a fully functioning chroot, such as copying device files (&lt;code&gt;/dev/zero&lt;/code&gt; and &lt;code&gt;/dev/null&lt;/code&gt; are usually the minimum requirements) and adding users.&lt;/p&gt;

&lt;h2 id='freebsd'&gt;FreeBSD&lt;/h2&gt;

&lt;p&gt;FreeBSD 7 and 8 come as a number of sets in tar format, and for our purposes we only need to extract the base set. You may wish to add more sets if you want to use your chroot for building packages:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;
&lt;span class='nv'&gt;mdunit&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(&lt;/span&gt;mdconfig -a -t vnode -o &lt;span class='nb'&gt;readonly&lt;/span&gt; -f /path/to/dvd1/of/freebsd.iso&lt;span class='k'&gt;)&lt;/span&gt;
mount_cd9660 /dev/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;mdunit&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; /mnt
cat /mnt/*/base/base.?? | tar -xpzf - -C &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
umount /mnt
mdconfig -d -u &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;mdunit&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='hpux'&gt;HP-UX&lt;/h2&gt;

&lt;p&gt;HP-UX has since been EOL&amp;#8217;d for MySQL, however this information might still prove useful. The HP-UX installation media contains per-directory packages, with the contents representing how they are laid out on the destination file system with each file gzip compressed.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;
&lt;span class='nb'&gt;cd&lt;/span&gt; /path/to/extracted/hpux-dvd1
&lt;span class='k'&gt;for &lt;/span&gt;pkg in &lt;span class='nv'&gt;$LIST_OF_PKGS&lt;/span&gt;
&lt;span class='k'&gt;do&lt;/span&gt;
&lt;span class='k'&gt;  for &lt;/span&gt;subpkg in &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;pkg&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/*
  &lt;span class='k'&gt;do&lt;/span&gt;
&lt;span class='k'&gt;    if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; ! -d &lt;span class='s2'&gt;&amp;quot;${subpkg}&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;      continue&lt;/span&gt;
&lt;span class='k'&gt;    fi&lt;/span&gt;
&lt;span class='k'&gt;    for &lt;/span&gt;d in &lt;span class='k'&gt;$(&lt;/span&gt;find &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;subpkg&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; -type d&lt;span class='k'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;do&lt;/span&gt;
&lt;span class='k'&gt;      &lt;/span&gt;mkdir -p &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/&lt;span class='k'&gt;$(&lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;d&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
        | sed -e &lt;span class='s2'&gt;&amp;quot;s#${subpkg}/##g&amp;quot;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
              -e &lt;span class='s2'&gt;&amp;quot;s#usr/newconfig/##g&amp;quot;&lt;/span&gt;&lt;span class='k'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;done&lt;/span&gt;
&lt;span class='k'&gt;    for &lt;/span&gt;f in &lt;span class='k'&gt;$(&lt;/span&gt;find &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;subpkg&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; -type f&lt;span class='k'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;do&lt;/span&gt;
&lt;span class='k'&gt;      &lt;/span&gt;gzip -dc &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;f&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; &amp;gt;&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/&lt;span class='k'&gt;$(&lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;f&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
        | sed -e &lt;span class='s2'&gt;&amp;quot;s#${subpkg}/##g&amp;quot;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
              -e &lt;span class='s2'&gt;&amp;quot;s#usr/newconfig/##g&amp;quot;&lt;/span&gt;&lt;span class='k'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;done&lt;/span&gt;
&lt;span class='k'&gt;  done&lt;/span&gt;
&lt;span class='k'&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Once this is done you&amp;#8217;ll need to fix up permissions in bin and lib directories (make files executable), as well as create a bunch of symlinks for e.g. &lt;code&gt;/bin&lt;/code&gt; and &lt;code&gt;/lib&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id='osx'&gt;OSX&lt;/h2&gt;

&lt;p&gt;For OSX we don&amp;#8217;t actually use a chroot tarball but instead create a sparse disk image. Currently the size of the &amp;#8220;chroot&amp;#8221; is very large as there&amp;#8217;s no easy way to strip down an OSX install, so mounting a disk image is faster than unpacking a chroot, plus it preserves various HFS-specific attributes.&lt;/p&gt;

&lt;p&gt;You will likely need at least the BSD, BaseSystem, and Essentials packages.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;# Create a sparse image to hold the chroot (which isn&amp;#39;t really a directory)&lt;/span&gt;
hdiutil create -fs HFS+ -size 8g -type SPARSE -volname osx-chroot &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
hdiutil attach -mountpoint &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.sparseimage
&lt;span class='c'&gt;# Either attach a DVD image or the real thing&lt;/span&gt;
hdiutil attach -mountpoint /Volumes/osx-install /path/to/dvd
&lt;span class='c'&gt;# Install packages&lt;/span&gt;
&lt;span class='k'&gt;for &lt;/span&gt;pkg in BSD BaseSystem Essentials
&lt;span class='k'&gt;do&lt;/span&gt;
&lt;span class='k'&gt;  &lt;/span&gt;installer -verbose &lt;span class='se'&gt;\&lt;/span&gt;
   -pkg /Volumes/osx-install/System/Installation/Packages/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;pkg&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.pkg &lt;span class='se'&gt;\&lt;/span&gt;
   -target &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
&lt;span class='k'&gt;done&lt;/span&gt;
&lt;span class='c'&gt;# Unmount&lt;/span&gt;
hdiutil detach &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
hdiutil detach /Volumes/osx-install
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='red_hat__oracle_linux__suse'&gt;Red Hat / Oracle Linux / SuSE&lt;/h2&gt;

&lt;p&gt;For RPM-based distributions we use rpm to directly install packages into the chroot. The list of RPMs we install varies quite a lot from release to release, usually by having to increase the number:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RH3: 81&lt;/li&gt;

&lt;li&gt;RH4: 85&lt;/li&gt;

&lt;li&gt;RH5: 114&lt;/li&gt;

&lt;li&gt;RH6: 203&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;for the same functionality.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;# Kludge for &amp;#39;setup&amp;#39; RPM to install&lt;/span&gt;
mkdir -p &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/var/lock/rpm
&lt;span class='c'&gt;# If installing from an ISO:&lt;/span&gt;
mount -o loop /path/to/iso /mnt
&lt;span class='c'&gt;# Path varies from release to release&lt;/span&gt;
&lt;span class='nb'&gt;cd&lt;/span&gt; /mnt/path/to/RPMs
rpm --root&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; -Uvh &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;LIST_OF_RPMS&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='solaris'&gt;Solaris&lt;/h2&gt;

&lt;p&gt;Similar to RPM, we use the native package manager to install packages directly into the chroot directory:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;# Avoid prompts&lt;/span&gt;
sed -e &lt;span class='s2'&gt;&amp;quot;s/ask$/nocheck/&amp;quot;&lt;/span&gt; /var/sadm/install/admin/default &amp;gt; /tmp/admin-&lt;span class='nv'&gt;$$&lt;/span&gt;
pkgadd -a /tmp/admin-&lt;span class='nv'&gt;$$&lt;/span&gt; -R &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; -d . &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;LIST_OF_PKGS&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
rm /tmp/admin-&lt;span class='nv'&gt;$$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='windows'&gt;Windows&lt;/h2&gt;

&lt;p&gt;Ok, so of course we can&amp;#8217;t use chroot images for Windows, as it doesn&amp;#8217;t have &lt;code&gt;chroot(2)&lt;/code&gt;. So here we use VirtualBox and its snapshot ability to load a clean snapshot of a basic Windows install, do the tests, then shut down the virtual machine, restore the snapshot, and boot up again.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Graphing memory usage during an MTR run</title>
      <link>http://www.perkin.org.uk/blog/2011/06/graphing-memory-usage-during-an-mtr-run/</link>
      <pubDate>Thu, 30 Jun 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2011/06/graphing-memory-usage-during-an-mtr-run</guid>
      <description>&lt;p&gt;In order to optimally size the amount of RAM to allocate to a set of new machines for running MTR, I ran a few tests to check the memory usage of an MTR run for mysql-trunk and cluster-7.1. As using a RAM disk considerably speeds things up, I set the vardir to be on &lt;code&gt;/ramdisk&lt;/code&gt; and logged the usage of that too.&lt;/p&gt;

&lt;p&gt;The tests were performed on an 8-core E5450 @ 3.00GHz with 24GB RAM, with 8GB allocated to &lt;code&gt;/ramdisk&lt;/code&gt;. Each branch ran the &lt;code&gt;default.daily&lt;/code&gt; collection, which generally contains the most testing we do per-run. Between each run I rebooted the machine to clear the buffer cache and &lt;code&gt;/ramdisk&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I used something like the script below, which saved the per-second usage of &lt;code&gt;/ramdisk&lt;/code&gt;, the total RAM used, and the RAM used minus buffers.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/bash&lt;/span&gt;

&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;mysql-trunk&amp;quot;&lt;/span&gt;
&lt;span class='nv'&gt;BUILDDIR&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;mysql-5.6.3-m5-linux2.6-x86_64&amp;quot;&lt;/span&gt;
&lt;span class='nv'&gt;TESTDIR&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;${HOME}/mtr-test/${BRANCH}&amp;quot;&lt;/span&gt;

stats&lt;span class='o'&gt;()&lt;/span&gt;
&lt;span class='o'&gt;{&lt;/span&gt;
  &lt;span class='nv'&gt;i&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;1
  rm -f &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TESTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/stats-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
  &lt;span class='k'&gt;while&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; -f &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TESTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/running &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;do&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nv'&gt;rd&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(&lt;/span&gt;df -k /ramdisk | awk &lt;span class='s1'&gt;&amp;#39;/^\// {print $3}&amp;#39;&lt;/span&gt;&lt;span class='k'&gt;)&lt;/span&gt;
    &lt;span class='nv'&gt;mem&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(&lt;/span&gt;free | awk &lt;span class='s1'&gt;&amp;#39;/^Mem/ {print $3}&amp;#39;&lt;/span&gt;&lt;span class='k'&gt;)&lt;/span&gt;
    &lt;span class='nv'&gt;mem1&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(&lt;/span&gt;free | awk &lt;span class='s1'&gt;&amp;#39;/cache:/ {print $3}&amp;#39;&lt;/span&gt;&lt;span class='k'&gt;)&lt;/span&gt;
    &lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;${i} ${rd} ${mem} ${mem1}&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt;&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TESTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/stats-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
    &lt;span class='nv'&gt;i&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$((&lt;/span&gt;i+1&lt;span class='k'&gt;))&lt;/span&gt;
    sleep 1
  &lt;span class='k'&gt;done&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;

&lt;span class='nb'&gt;export &lt;/span&gt;&lt;span class='nv'&gt;TMPDIR&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;${TESTDIR}/tmp&amp;quot;&lt;/span&gt;
rm -rf &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TMPDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
mkdir -p &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TMPDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;

&amp;gt;&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TESTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/running
stats &amp;amp;

&lt;span class='o'&gt;(&lt;/span&gt;
  &lt;span class='nb'&gt;cd&lt;/span&gt; &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TESTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BUILDDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/mysql-test

  perl mysql-test-run.pl ... --parallel&lt;span class='o'&gt;=&lt;/span&gt;8 --vardir&lt;span class='o'&gt;=&lt;/span&gt;/ramdisk/mtr-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/...
  mv /ramdisk/mtr-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/* &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TMPDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/
  ...
&lt;span class='o'&gt;)&lt;/span&gt;

sync
rm -f &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TESTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/running
&lt;span class='nb'&gt;wait&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;First I graphed a straight run of the two branches, using the following gnuplot script:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='gnuplot'&gt;&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;terminal&lt;/span&gt; &lt;span class='n'&gt;png&lt;/span&gt; &lt;span class='n'&gt;enhanced&lt;/span&gt; &lt;span class='n'&gt;font&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Times,11&amp;quot;&lt;/span&gt; &lt;span class='n'&gt;size&lt;/span&gt; &lt;span class='mi'&gt;640&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='mi'&gt;768&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;output&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;mtr-ram.png&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;title&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;MTR memory usage (8-core Xeon, 24GB, 8GB RAM disk)&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;xlabel&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Time (minutes)&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;ylabel&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Memory usage (GB)&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;yrange&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='mi'&gt;16&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;xtics&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;key&lt;/span&gt; &lt;span class='n'&gt;top&lt;/span&gt; &lt;span class='n'&gt;box&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;grid&lt;/span&gt;
&lt;span class='k'&gt;plot&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;stats-mysql-trunk&amp;quot;&lt;/span&gt; &lt;span class='nb'&gt;every&lt;/span&gt; &lt;span class='mi'&gt;60&lt;/span&gt; &lt;span class='nb'&gt;using&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;60&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; \
        &lt;span class='nb'&gt;title&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;mysql-trunk /ramdisk usage&amp;#39;&lt;/span&gt; &lt;span class='nb'&gt;with&lt;/span&gt; &lt;span class='n'&gt;lines&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; \
     &lt;span class='s'&gt;&amp;quot;stats-mysql-trunk&amp;quot;&lt;/span&gt; &lt;span class='nb'&gt;every&lt;/span&gt; &lt;span class='mi'&gt;60&lt;/span&gt; &lt;span class='nb'&gt;using&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;60&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; \
        &lt;span class='nb'&gt;title&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;mysql-trunk RAM (inc buf)&amp;#39;&lt;/span&gt; &lt;span class='nb'&gt;with&lt;/span&gt; &lt;span class='n'&gt;lines&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; \
     &lt;span class='s'&gt;&amp;quot;stats-mysql-trunk&amp;quot;&lt;/span&gt; &lt;span class='nb'&gt;every&lt;/span&gt; &lt;span class='mi'&gt;60&lt;/span&gt; &lt;span class='nb'&gt;using&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;60&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;4&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; \
        &lt;span class='nb'&gt;title&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;mysql-trunk RAM (exc buf)&amp;#39;&lt;/span&gt; &lt;span class='nb'&gt;with&lt;/span&gt; &lt;span class='n'&gt;lines&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; \
     &lt;span class='s'&gt;&amp;quot;stats-mysql-cluster-7.1&amp;quot;&lt;/span&gt; &lt;span class='nb'&gt;every&lt;/span&gt; &lt;span class='mi'&gt;60&lt;/span&gt; &lt;span class='nb'&gt;using&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;60&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; \
        &lt;span class='nb'&gt;title&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;cluster-7.1 /ramdisk usage&amp;#39;&lt;/span&gt; &lt;span class='nb'&gt;with&lt;/span&gt; &lt;span class='n'&gt;lines&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; \
     &lt;span class='s'&gt;&amp;quot;stats-mysql-cluster-7.1&amp;quot;&lt;/span&gt; &lt;span class='nb'&gt;every&lt;/span&gt; &lt;span class='mi'&gt;60&lt;/span&gt; &lt;span class='nb'&gt;using&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;60&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; \
        &lt;span class='nb'&gt;title&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;cluster-7.1 RAM (inc buf)&amp;#39;&lt;/span&gt; &lt;span class='nb'&gt;with&lt;/span&gt; &lt;span class='n'&gt;lines&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; \
     &lt;span class='s'&gt;&amp;quot;stats-mysql-cluster-7.1&amp;quot;&lt;/span&gt; &lt;span class='nb'&gt;every&lt;/span&gt; &lt;span class='mi'&gt;60&lt;/span&gt; &lt;span class='nb'&gt;using&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;60&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;4&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; \
        &lt;span class='nb'&gt;title&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;cluster-7.1 RAM (exc buf)&amp;#39;&lt;/span&gt; &lt;span class='nb'&gt;with&lt;/span&gt; &lt;span class='n'&gt;lines&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img alt='MTR memory usage' src='/files/images/mtr-ram.png' /&gt;&lt;/p&gt;

&lt;p&gt;I then performed a valgrind run on mysql-trunk using similar scripts. As valgrind takes considerably longer (and uses more RAM) I kept it separate as the combined graph isn&amp;#8217;t very clear:&lt;/p&gt;

&lt;p&gt;&lt;img alt='MTR+valgrind memory usage' src='/files/images/mtr-ram-valgrind.png' /&gt;&lt;/p&gt;

&lt;p&gt;So, based on these results, the host machine (16GB RAM + 8GB RAM disk) is probably a sensible guide for now, and allows for some future growth.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Fix input box keybindings in Firefox</title>
      <link>http://www.perkin.org.uk/blog/2011/06/fix-input-box-keybindings-in-firefox/</link>
      <pubDate>Wed, 29 Jun 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2011/06/fix-input-box-keybindings-in-firefox</guid>
      <description>&lt;p&gt;Those of us used to command line editing will no doubt have been frustrated many times in Firefox when editing text in an input box and subconciously hitting &lt;code&gt;ctrl-w&lt;/code&gt; to &lt;code&gt;delete-word&lt;/code&gt;, only to have the tab close and your work deleted.&lt;/p&gt;

&lt;p&gt;Thankfully there is a workaround to this. It used to be a case of adding the following to &lt;code&gt;.gtkrc&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;gtk-key-theme-name = &amp;quot;Emacs&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;However these days it&amp;#8217;s a gconf setting:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;$ gconftool-2 --set /desktop/gnome/interface/gtk_key_theme Emacs --type string
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This will bind &lt;code&gt;ctrl-w&lt;/code&gt; to &lt;code&gt;delete-word&lt;/code&gt; when in an input box, but retain the close tab binding elsewhere, a nice implementation of &lt;a href='http://en.wikipedia.org/wiki/DWIM'&gt;DWIM&lt;/a&gt;. See &lt;a href='http://kb.mozillazine.org/Emacs_Keybindings_%28Firefox%29'&gt;this page&lt;/a&gt; for more information.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>How to lose weight</title>
      <link>http://www.perkin.org.uk/blog/2011/06/how-to-lose-weight/</link>
      <pubDate>Fri, 24 Jun 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2011/06/how-to-lose-weight</guid>
      <description>&lt;p&gt;This year I set myself a target to get back to my pre-marital weight. Back in 2001 I was 90kg, but over the past decade I&amp;#8217;d steadily gone up and for quite a few years had hovered around 100kg.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m a bit of a perfectionist, and like shiny graphs, so from Jan 1st this year I weighed myself every day on the Wii Fit, and kept a record of my progress. This morning I was finally under 90kg. Here&amp;#8217;s how things have gone thus far:&lt;/p&gt;

&lt;p&gt;&lt;img alt='My weight loss between 1st January 2011 and 24th June 2011' src='/files/images/weight-jun11.png' /&gt;&lt;/p&gt;

&lt;p&gt;And for the geeks, my gnuplot script, assuming an input file named &lt;code&gt;weight.txt&lt;/code&gt; containing lines of the format &lt;code&gt;&amp;quot;%Y-%m-%d &amp;lt;weight&amp;gt;&amp;quot;&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='gnuplot'&gt;&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;terminal&lt;/span&gt; &lt;span class='n'&gt;png&lt;/span&gt; &lt;span class='n'&gt;size&lt;/span&gt; &lt;span class='mi'&gt;640&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;400&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;output&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;weight-jun11.png&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;xdata&lt;/span&gt; &lt;span class='n'&gt;time&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;timefmt&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;%Y-%m-%d&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;format&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;%b&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;xlabel&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;Date&amp;#39;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;ytics&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;ylabel&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;Weight (kg)&amp;#39;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;multiplot&lt;/span&gt;
&lt;span class='k'&gt;plot&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;weight.txt&amp;#39;&lt;/span&gt; &lt;span class='nb'&gt;using&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='nb'&gt;title&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;Weight&amp;#39;&lt;/span&gt; &lt;span class='nb'&gt;with&lt;/span&gt; &lt;span class='n'&gt;lines&lt;/span&gt; &lt;span class='n'&gt;linecolor&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='my_three_step_plan_for_losing_weight'&gt;My three step plan for losing weight&lt;/h2&gt;

&lt;p&gt;The interwebs are awash with a million different ways to lose weight, and there are thousands of companies who will gladly accept large chunks of your cash in order to provide you with their expert opinion on how to do it. This is my three-step plan, and you can have it for free:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Eat less.&lt;/li&gt;

&lt;li&gt;Eat less!&lt;/li&gt;

&lt;li&gt;Profit!!!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Really, that&amp;#8217;s it. It&amp;#8217;s not rocket science, after all. If you eat less stuff (especially saturated fat and sugar), there is less excess for your body to store as fat, and thus over time you weigh less as your body starts to use up the excess you have stored.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s some things I did to achieve this.&lt;/p&gt;

&lt;h3 id='eat_less'&gt;Eat less&lt;/h3&gt;

&lt;p&gt;The basic aim. For me this was mainly about reducing my portion size.&lt;/p&gt;

&lt;p&gt;Previously, I&amp;#8217;d eat a massive bowl of cereal in the morning. which I thought was a good thing as everyone always says to ensure you have a good breakfast. However I was eating more than my body needed and as a consequence it was likely storing up the excess.&lt;/p&gt;

&lt;p&gt;Also at meal times I&amp;#8217;d usually serve myself a full plate, and always feel that I needed to finish it. I liked feeling full. However, again, this likely just meant I was eating more than I needed, and I found that just by serving less food I was still satisfying my hunger but with less excess.&lt;/p&gt;

&lt;p&gt;After a relatively short period of time I found that by avoiding these large meals, I needed less to feel full – as if my stomach had shrunk and gotten used to the reduced size. This was a great positive feedback loop, as it massively helped avoid the temptation to snack between meals.&lt;/p&gt;

&lt;h3 id='cut_down_on_sugarfat'&gt;Cut down on sugar/fat&lt;/h3&gt;

&lt;p&gt;I realise this can be hard for some people, I found it relatively easy but as you can see on the graph above there are some upward trends, which were mainly when I went to visit my parents, who have a cupboard full of chocolates, crisps, cakes, sweets, etc, and I find it really hard not to have at least one or two fake Lidl snickers bars per day!&lt;/p&gt;

&lt;p&gt;However, also note that after an upward trend, I lost the weight again pretty quickly, so don&amp;#8217;t worry too much about a few days of eating junk, I actually noticed how bad I felt afterwards after getting used to a reduced sugar/fat intake, and that provided good incentive to cut down again.&lt;/p&gt;

&lt;p&gt;Some practical things I did:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Stopped putting sugar in tea/coffee. I&amp;#8217;ve since regressed, but it was helpful to do this for a while, and definitely helped wean my body off desiring sugar.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Avoided snacking on crisps, chocolate, biscuits, etc. When you work from home this can be difficult, but I found it helped to ensure they weren&amp;#8217;t in the house to begin with, and that we were stocked up on bananas, apples, and other less sugary/fatty snacks.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Used a fine cheese grater when making sandwiches, beans on toast, etc. Previously I&amp;#8217;d put a good few slabs of cheese in, when I didn&amp;#8217;t really need that quantity. The fine grater ensured I still got the taste, but with less quantity.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Bought reduced fat mayonnaise, margarine, etc. These actually taste pretty good these days, and in a sandwich with lots of fresh cucumber, tomato, salad etc you don&amp;#8217;t notice the difference&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these things helped to lose weight and, in a similar manner to the &amp;#8216;eating less&amp;#8217; part, trained my body to not require them as much as it used to – and actually, to noticeably feel worse if ever I regressed, which made getting back on track very easy.&lt;/p&gt;

&lt;h3 id='weigh_myself_daily'&gt;Weigh myself daily&lt;/h3&gt;

&lt;p&gt;It seems this is generally not recommended, and advice is that you should weigh yourself weekly (at the same time each week). Logically this doesn&amp;#8217;t make sense to me, as a geek it&amp;#8217;s obvious that the more data points you have, the better. Your body weight can fluctuate quite a lot from day to day especially with regards to how much liquid you have drunk, and if you are only weighing yourself once per week you could get caught out by a daily spike.&lt;/p&gt;

&lt;p&gt;Aside from the geek factor of a better graph resolution, I also prefer daily weighing as it provides me, as a perfectionist, with incentives both ways. If I weigh less compared to the previous day, I feel good that I am achieving my aim, and am encouraged to continue. If I weigh more, it&amp;#8217;s a warning that I may have eaten too much, and I am then motivated to be more careful that day.&lt;/p&gt;

&lt;p&gt;Weighing daily also helps to just keep your mind reminded of the task, plus if you&amp;#8217;re on the Wii Fit already you might be tempted to do some exercise :)&lt;/p&gt;

&lt;h2 id='next_steps'&gt;Next steps&lt;/h2&gt;

&lt;p&gt;I&amp;#8217;m not content to stay here, the next plan is to get closer to my ideal BMI weight which is around 80kg. This is likely to be much harder, as there is less excess fat for me to get rid of now. However, one thing I haven&amp;#8217;t done so far is increase the amount of exercise I do, and there is definitely room for improvement there!&lt;/p&gt;

&lt;p&gt;Hopefully I can provide another update later this year and perhaps be around 85kg.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>How to fix stdio buffering</title>
      <link>http://www.perkin.org.uk/blog/2011/06/how-to-fix-stdio-buffering/</link>
      <pubDate>Thu, 23 Jun 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2011/06/how-to-fix-stdio-buffering</guid>
      <description>&lt;p&gt;It&amp;#8217;s a common problem. You write some shell command like:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; tail -f /var/log/foo | egrep -v &lt;span class='s1'&gt;&amp;#39;some|stuff&amp;#39;&lt;/span&gt; | sed | awk
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and wonder why nothing is printed, even though you know some text has matched. The problem is that stdio is being buffered, and there&amp;#8217;s a very good write-up of the problem here so I won&amp;#8217;t repeat the technical background.&lt;/p&gt;

&lt;p&gt;What I will provide though is how to fix it for common cases.&lt;/p&gt;

&lt;h2 id='stdbuf'&gt;stdbuf&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;stdbuf&lt;/code&gt; is part of GNU coreutils, and is essentially an &lt;code&gt;LD_PRELOAD&lt;/code&gt; hack which calls &lt;code&gt;setvbuf()&lt;/code&gt; for an application. Thus it is a generic solution to the problem and can be used to fix most applications. Usage looks like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; tail -f /var/log/foo | stdbuf -o0 app ...
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;which will disable output buffering for app, assuming it does not do something itself to reverse the &lt;code&gt;setvbuf()&lt;/code&gt; call. An example of a misbehaving application is &lt;code&gt;mawk&lt;/code&gt;, below.&lt;/p&gt;

&lt;h2 id='awk'&gt;awk&lt;/h2&gt;

&lt;p&gt;GNU &lt;code&gt;awk&lt;/code&gt; needs no modifications, that is it does not buffer when there is no controlling tty.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mawk&lt;/code&gt; however (the default &lt;code&gt;awk&lt;/code&gt; in Debian/Ubuntu and possibly others) buffers output, and also does not seem to work with &lt;code&gt;stdbuf&lt;/code&gt;. It does however provide a &lt;code&gt;-Winteractive&lt;/code&gt; option which will turn off buffering.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; tail -f /var/log/foo | gawk
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; tail -f /var/log/foo | mawk -Winteractive
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='sed'&gt;sed&lt;/h2&gt;

&lt;p&gt;GNU &lt;code&gt;sed&lt;/code&gt; provides the &lt;code&gt;-u&lt;/code&gt; option which calls &lt;code&gt;fflush()&lt;/code&gt;, thereby providing unbuffered output. You can also use &lt;code&gt;stdbuf&lt;/code&gt; as above.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; tail -f /var/log/foo | sed -u
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; tail -f /var/log/foo | stdbuf -o0 sed
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='grep'&gt;grep&lt;/h2&gt;

&lt;p&gt;Similar to &lt;code&gt;sed&lt;/code&gt;, GNU &lt;code&gt;grep&lt;/code&gt; provides a specific option, &lt;code&gt;--line-buffered&lt;/code&gt;, to disable buffering, or again you can use &lt;code&gt;stdbuf&lt;/code&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; tail -f /var/log/foo | grep --line-buffered
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; tail -f /var/log/foo | stdbuf -o0 grep
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Serving multiple DNS search domains in IOS DHCP</title>
      <link>http://www.perkin.org.uk/blog/2011/06/serving-multiple-dns-search-domains-in-ios-dhcp/</link>
      <pubDate>Mon, 13 Jun 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2011/06/serving-multiple-dns-search-domains-in-ios-dhcp</guid>
      <description>&lt;p&gt;I have a Cisco router at home which I also use as a DHCP server, and it works pretty well. Today I wanted to fix a long-standing issue on my network, in that I want multiple DNS search domains.&lt;/p&gt;

&lt;p&gt;First off, the domain-name DHCP option doesn&amp;#8217;t support multiple entries so we can&amp;#8217;t use that.&lt;/p&gt;

&lt;p&gt;So, off to try raw DHCP option codes. You can find the list of options here:&lt;/p&gt;

&lt;p&gt;&lt;a href='http://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xml'&gt;http://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xml&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;thus 119 is the one I want.&lt;/p&gt;

&lt;p&gt;Trying a simple:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;ip dhcp pool host.net.example.com
   option 119 ascii net.example.com,example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;didn&amp;#8217;t work at all. A quick prod of lazyweb (in this case Simon on IRC) suggested using hex input instead. In order to do that we need to convert the ASCII string into Cisco&amp;#8217;s hex sequence, which is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Split domain name by dot&lt;/li&gt;

&lt;li&gt;Prepend each string by its length (in hex)&lt;/li&gt;

&lt;li&gt;NUL terminate each domain&lt;/li&gt;

&lt;li&gt;Dot-seperate the final string in 16bit chunks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To do this I wrote a quick Python script:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='python'&gt;&lt;span class='c'&gt;#!/usr/bin/python&lt;/span&gt;

&lt;span class='kn'&gt;import&lt;/span&gt; &lt;span class='nn'&gt;sys&lt;/span&gt;

&lt;span class='n'&gt;hexlist&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[]&lt;/span&gt;
&lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;domain&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='n'&gt;sys&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;argv&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;:]:&lt;/span&gt;
    &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;part&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='n'&gt;domain&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
        &lt;span class='n'&gt;hexlist&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;append&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;%02x&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;%&lt;/span&gt; &lt;span class='nb'&gt;len&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;part&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
        &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='n'&gt;part&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
            &lt;span class='n'&gt;hexlist&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;append&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;encode&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;hex&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
    &lt;span class='n'&gt;hexlist&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;append&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;00&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='k'&gt;print&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;join&lt;/span&gt;&lt;span class='p'&gt;([(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;.&lt;/span&gt;&lt;span class='si'&gt;%s&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;%&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='ow'&gt;and&lt;/span&gt; &lt;span class='ow'&gt;not&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='o'&gt;%&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; \
               &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='nb'&gt;enumerate&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;hexlist&lt;/span&gt;&lt;span class='p'&gt;)])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;which can be used like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; ./cisco.py net.example.com example.com
&lt;span class='go'&gt;036e.6574.0765.7861.6d70.6c65.0363.6f6d.0007.6578.616d.706c.6503.636f.6d00&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then back to IOS and:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;ip dhcp pool host.net.example.com
   option 119 hex 036e.6574.0765.7861.6d70.6c65.0363.6f6d.0007.6578.616d.706c.6503.636f.6d00
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;seems to do what we want, though IOS appears to append a dot to each domain when serving via DHCP.&lt;/p&gt;

&lt;p&gt;One last note, if you use this in addition to domain-name then the option 119 list will be appended to the domain-name name in the search list, so you&amp;#8217;d actually want something like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;ip dhcp pool host.net.example.com
   domain-name net.example.com
   option 119 hex 0765.7861.6d70.6c65.0363.6f6d.00
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;to generate a resolv.conf containing:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;domain net.example.com
search net.example.com example.com.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Fix Firefox URL double click behaviour</title>
      <link>http://www.perkin.org.uk/blog/2011/06/fix-firefox-url-double-click-behaviour/</link>
      <pubDate>Mon, 13 Jun 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2011/06/fix-firefox-url-double-click-behaviour</guid>
      <description>&lt;p&gt;One of the best things I find with OS X is the consistent and sane handling of keyboard and mouse bindings. Since having to move back to Linux for work I am constantly frustrated that different applications all have their own idea of what shortcuts to use.&lt;/p&gt;

&lt;p&gt;One of the biggest annoyances was the mouse click behaviour in the browser URL bar. OS X behaviour is one click to position cursor, two clicks to select a word, three clicks to select all. I rely on this behaviour a lot as I frequently copy/paste parts of URLs.&lt;/p&gt;

&lt;p&gt;Thankfully that&amp;#8217;s one that can be fixed easily. Simply navigate to &lt;a href='about:config'&gt;about:config&lt;/a&gt; and double click on the &lt;code&gt;browser.urlbar.doubleClickSelectsAll&lt;/code&gt; key to set it to false.&lt;/p&gt;

&lt;p&gt;One annoyance down, lots more to go..&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>SSH via HTTP proxy in OSX</title>
      <link>http://www.perkin.org.uk/blog/2011/04/ssh-via-http-proxy-in-osx/</link>
      <pubDate>Wed, 20 Apr 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2011/04/ssh-via-http-proxy-in-osx</guid>
      <description>&lt;p&gt;If you happen to be stuck behind a corporate firewall with only HTTP proxies for external access, you might still be able to SSH out through them using the built-in &lt;code&gt;nc&lt;/code&gt; on OSX.&lt;/p&gt;

&lt;p&gt;First, hope that the proxies haven&amp;#8217;t disabled the &lt;code&gt;CONNECT&lt;/code&gt; method, then simply add a section to your &lt;code&gt;.ssh/config&lt;/code&gt; like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;Host foobar.example.com
    ProxyCommand          nc -X connect -x proxyhost:proxyport %h %p
    ServerAliveInterval   10
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This will tunnel the connection through the HTTP proxy to the remote server. The &lt;code&gt;ServerAliveInterval&lt;/code&gt; setting is required as most proxies will drop the connection after a period of inactivity.&lt;/p&gt;

&lt;p&gt;To avoid issues with trying to connect to the host when not behind the corporate firewall, replace the above with a fake entry for the proxy method like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;Host foobar-proxy.example.com
    HostName              foobar.example.com
    ProxyCommand          nc -X connect -x proxyhost:proxyport %h %p
    ServerAliveInterval   10
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then use&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; ssh foobar-proxy.example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;when inside the firewall, and&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; ssh foobar.example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;when outside.&lt;/p&gt;

&lt;p&gt;Simples, no external software required.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>How to build MySQL releases</title>
      <link>http://www.perkin.org.uk/blog/2010/11/how-to-build-mysql-releases/</link>
      <pubDate>Tue, 09 Nov 2010 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2010/11/how-to-build-mysql-releases</guid>
      <description>&lt;p&gt;One of the major benefits from the &lt;a href='http://forge.mysql.com/wiki/CMake'&gt;CMake work&lt;/a&gt; available in MySQL 5.5 is that in the MySQL Release Engineering team we have been able to make it easy for users and developers to build MySQL exactly as we do for the official releases. For too long there has been a disconnect between the binaries produced as part of a regular &amp;#8217;&lt;code&gt;./configure; make&lt;/code&gt;&amp;#8217; build and what we ship to users and customers.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;re still not exactly where we want to be, there are still some parts which need to be integrated into the server tree, but for now it&amp;#8217;s relatively straightforward to build exactly as we do.&lt;/p&gt;

&lt;p&gt;Here are the instructions, using the &lt;code&gt;mysql-5.5.6-rc.tar.gz&lt;/code&gt; source tarball as an example.&lt;/p&gt;

&lt;h2 id='targz'&gt;tar.gz&lt;/h2&gt;

&lt;p&gt;These are the generic instructions to build a tarball release. Note that we make use of CMake&amp;#8217;s out-of-srcdir support to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ensure the source directory is kept pristine&lt;/li&gt;

&lt;li&gt;allow us to easily build both debug and release binaries, and package them together&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

tar -zxf mysql-5.5.6-rc.tar.gz

&lt;span class='c'&gt;# Build debug binaries first, they are picked up in the final &amp;#39;make package&amp;#39;&lt;/span&gt;
mkdir debug
&lt;span class='o'&gt;(&lt;/span&gt;
  &lt;span class='nb'&gt;cd &lt;/span&gt;debug
  cmake ../mysql-5.5.6-rc -DBUILD_CONFIG&lt;span class='o'&gt;=&lt;/span&gt;mysql_release -DCMAKE_BUILD_TYPE&lt;span class='o'&gt;=&lt;/span&gt;Debug
  make &lt;span class='nv'&gt;VERBOSE&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;1
&lt;span class='o'&gt;)&lt;/span&gt;

&lt;span class='c'&gt;# Build release binaries and create final package&lt;/span&gt;
mkdir release
&lt;span class='o'&gt;(&lt;/span&gt;
  &lt;span class='nb'&gt;cd &lt;/span&gt;release
  cmake ../mysql-5.5.6-rc -DBUILD_CONFIG&lt;span class='o'&gt;=&lt;/span&gt;mysql_release
  make &lt;span class='nv'&gt;VERBOSE&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;1 package
&lt;span class='o'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Assuming everything goes ok, you should end up with a tarball in the &lt;code&gt;release/&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Some platforms require extra flags to be specified on the CMake command line to ensure the correct compiler etc is used. Here are some that we use.&lt;/p&gt;

&lt;h3 id='avoid_libstdc_dependancy'&gt;Avoid libstdc++ dependancy&lt;/h3&gt;

&lt;p&gt;In order to create &amp;#8216;generic&amp;#8217; binaries, on GCC platforms we compile using &lt;code&gt;CXX=gcc&lt;/code&gt;. This avoids &lt;code&gt;libstdc++&lt;/code&gt; being pulled in, and means that the server will run across a larger range of releases as you do not rely on having the exact version of &lt;code&gt;libstdc++&lt;/code&gt; installed by your system package manager.&lt;/p&gt;

&lt;p&gt;Paste this before running cmake.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; CXXFLAGS is required to trick CMake into believing it is a C++ compiler
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;CXX&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;gcc; &lt;span class='nv'&gt;CXXFLAGS&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;-fno-exceptions&amp;quot;&lt;/span&gt;; &lt;span class='nb'&gt;export &lt;/span&gt;CXX CXXFLAGS
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='specify_target_architecture'&gt;Specify target architecture&lt;/h3&gt;

&lt;p&gt;On systems which support multiple targets, you can specify exactly which one you want, rather than relying on the OS default. These strings are meant to be added to the cmake command lines above.&lt;/p&gt;

&lt;h4 id='osx'&gt;OSX&lt;/h4&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; -DCMAKE_OSX_ARCHITECTURES&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;i386&amp;quot;&lt;/span&gt;    &lt;span class='c'&gt;# 32bit&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; -DCMAKE_OSX_ARCHITECTURES&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;x86_64&amp;quot;&lt;/span&gt;  &lt;span class='c'&gt;# 64bit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h4 id='gccsun_studio'&gt;GCC/Sun Studio&lt;/h4&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; -DCMAKE_C_FLAGS&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;-m32&amp;quot;&lt;/span&gt; -DCMAKE_CXX_FLAGS&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;-m32&amp;quot;&lt;/span&gt;  &lt;span class='c'&gt;# 32bit&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; -DCMAKE_C_FLAGS&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;-m64&amp;quot;&lt;/span&gt; -DCMAKE_CXX_FLAGS&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;-m64&amp;quot;&lt;/span&gt;  &lt;span class='c'&gt;# 64bit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h4 id='hpux'&gt;HP/UX&lt;/h4&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; -DCMAKE_C_FLAGS&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;+DD64&amp;quot;&lt;/span&gt; -DCMAKE_CXX_FLAGS&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;+DD64&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='rpm'&gt;RPM&lt;/h2&gt;

&lt;p&gt;We&amp;#8217;ve spent a lot of time improving the RPM builds too. Previously some of the configuration was only available in the commercial RPM builds, but now we have merged them into the community version.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

mkdir -p rpm/&lt;span class='o'&gt;{&lt;/span&gt;BUILD,RPMS,SOURCES,SPECS,SRPMS&lt;span class='o'&gt;}&lt;/span&gt; tmp

&lt;span class='c'&gt;# Create spec file.&lt;/span&gt;
&lt;span class='c'&gt;# XXX: We should probably just include this in the source tarball.&lt;/span&gt;
tar -zxf mysql-5.5.6-rc.tar.gz
&lt;span class='o'&gt;(&lt;/span&gt;
  mkdir bld; &lt;span class='nb'&gt;cd &lt;/span&gt;bld
  cmake ../mysql-5.5.6-rc
&lt;span class='o'&gt;)&lt;/span&gt;

cp bld/support-files/*.spec rpm/SPECS
cp mysql-5.5.6-rc.tar.gz rpm/SOURCES

rpmbuild -v --define&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;_topdir $PWD/rpm&amp;quot;&lt;/span&gt; --define&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;_tmppath $PWD/tmp&amp;quot;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
 -ba rpm/SPECS/mysql.5.5.6-rc.spec
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You should end up with nice shiny RPMs in &lt;code&gt;rpm/RPMS&lt;/code&gt;. One thing to note is that the RPM spec no longer runs the test suite as part of the build, so you will need to run that separately. On the plus side, you get your RPMs much quicker.&lt;/p&gt;

&lt;p&gt;Another nice thing about the improved RPM spec is that you can now build targetted distribution RPMs, as we do. These have extra dependancy information in them tailored to the target distribution. Currently the spec file supports the distributions we build on, but we will accept patches for others.&lt;/p&gt;

&lt;p&gt;To enable this, use:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; rpmbuild -v --define&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;distro_specific 1&amp;quot;&lt;/span&gt; ...
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='windows'&gt;Windows&lt;/h2&gt;

&lt;p&gt;Our Windows builds have relied on CMake since MySQL 5.0, but the procedure has still changed to ensure that you can build as we do. These instructions use &lt;code&gt;cmd.exe&lt;/code&gt; but you can use the Visual Studio front end if you prefer.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bat'&gt;unzip mysql&lt;span class='m'&gt;-5&lt;/span&gt;.&lt;span class='m'&gt;5&lt;/span&gt;.&lt;span class='m'&gt;6&lt;/span&gt;-rc.zip

&lt;span class='c'&gt;rem There is no separate &amp;#39;debug&amp;#39; directory on Windows, as the CMake&lt;/span&gt;
&lt;span class='c'&gt;rem infrastructure doesn&amp;#39;t yet know to pull files in from there on Windows.&lt;/span&gt;
&lt;span class='k'&gt;md&lt;/span&gt; release
&lt;span class='k'&gt;cd&lt;/span&gt; release

&lt;span class='c'&gt;rem Choose your target architecture, 32bit&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nv'&gt;VSTARGET&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;Visual Studio &lt;span class='m'&gt;9&lt;/span&gt; &lt;span class='m'&gt;2008&lt;/span&gt;
&lt;span class='c'&gt;rem or 64bit&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nv'&gt;VSTARGET&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;Visual Studio &lt;span class='m'&gt;9&lt;/span&gt; &lt;span class='m'&gt;2008&lt;/span&gt; Win&lt;span class='m'&gt;64&lt;/span&gt;

cmake ..\mysql&lt;span class='m'&gt;-5&lt;/span&gt;.&lt;span class='m'&gt;5&lt;/span&gt;.&lt;span class='m'&gt;6&lt;/span&gt;-rc -DBUILD_CONFIG&lt;span class='o'&gt;=&lt;/span&gt;mysql_release \
 -DCMAKE_BUILD_TYPE&lt;span class='o'&gt;=&lt;/span&gt;Debug -G &lt;span class='s2'&gt;&amp;quot;%VSTARGET%&amp;quot;&lt;/span&gt;

devenv MySql.sln &lt;span class='n'&gt;/build&lt;/span&gt; Debug

cmake ..\mysql&lt;span class='m'&gt;-5&lt;/span&gt;.&lt;span class='m'&gt;5&lt;/span&gt;.&lt;span class='m'&gt;6&lt;/span&gt;-rc -DBUILD_CONFIG&lt;span class='o'&gt;=&lt;/span&gt;mysql_release \
 -DCMAKE_BUILD_TYPE&lt;span class='o'&gt;=&lt;/span&gt;RelWithDebInfo -G &lt;span class='s2'&gt;&amp;quot;%VSTARGET%&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can now choose which type of package to create. 5.5 includes new code to create minimal MSI packages, these should work ok, and only differ from the official MySQL MSI packages in that they do not include the instance config wizard.&lt;/p&gt;

&lt;p&gt;To create the MSI packages you will need to install &lt;a href='http://wix.codeplex.com/'&gt;WiX&lt;/a&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bat'&gt;&lt;span class='c'&gt;rem Standard zip package&lt;/span&gt;
devenv MySql.sln &lt;span class='n'&gt;/build&lt;/span&gt; RelWithDebInfo &lt;span class='n'&gt;/project&lt;/span&gt; package

&lt;span class='c'&gt;rem Full MSI package&lt;/span&gt;
devenv MySql.sln &lt;span class='n'&gt;/build&lt;/span&gt; RelWithDebInfo &lt;span class='n'&gt;/project&lt;/span&gt; msi

&lt;span class='c'&gt;rem &amp;#39;Essentials&amp;#39; MSI package&lt;/span&gt;
devenv MySql.sln &lt;span class='n'&gt;/build&lt;/span&gt; RelWithDebInfo &lt;span class='n'&gt;/project&lt;/span&gt; msi_essentials
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Assuming everything goes ok, you should have some packages in the &lt;code&gt;release\&lt;/code&gt; directory.&lt;/p&gt;

&lt;h2 id='work_still_to_be_done'&gt;Work still to be done&lt;/h2&gt;

&lt;p&gt;We still have a number of scripts only available internally, for example those we use to create SVR4, DMG and DEPOT packages. However, we are looking to integrate these into the MySQL Server source tree so that all users can benefit from them.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>'apt-get' and 5,000 packages for Solaris10/x86</title>
      <link>http://www.perkin.org.uk/blog/2010/04/apt-get-and-5000-packages-for-solaris10x86/</link>
      <pubDate>Thu, 29 Apr 2010 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2010/04/apt-get-and-5000-packages-for-solaris10x86</guid>
      <description>&lt;p&gt;Here&amp;#8217;s how:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; Install pkg_* tools and the &lt;span class='s1'&gt;&amp;#39;pkgin&amp;#39;&lt;/span&gt; package manager
&lt;span class='gp'&gt;$&lt;/span&gt; pkgadd -d http://www.netbsd.org/~sketch/TNFpkgsrc-x86.pkg all

&lt;span class='gp'&gt;#&lt;/span&gt; Add tools to PATH
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/opt/pkg/sbin:/opt/pkg/bin:&lt;span class='nv'&gt;$PATH&lt;/span&gt;

&lt;span class='gp'&gt;#&lt;/span&gt; Update package repository &lt;span class='o'&gt;(&lt;/span&gt;akin to &lt;span class='s1'&gt;&amp;#39;apt-get update&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin up

&lt;span class='gp'&gt;#&lt;/span&gt; Search &lt;span class='k'&gt;for &lt;/span&gt;a particular package &lt;span class='o'&gt;(&lt;/span&gt;you can use regexp&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin search ^ap.*python 

&lt;span class='gp'&gt;#&lt;/span&gt; Install it
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin install ap22-py25-python

&lt;span class='gp'&gt;#&lt;/span&gt; Update all packages &lt;span class='o'&gt;(&lt;/span&gt;akin to &lt;span class='s1'&gt;&amp;#39;apt-get dist-upgrade&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin full-upgrade

&lt;span class='gp'&gt;#&lt;/span&gt; How many packages are available?
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin avail | wc -l
&lt;span class='go'&gt;   4970&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Ok, so the headline might be slightly mis-leading, this isn&amp;#8217;t really apt-get but a tool which is very similar. This is work which builds upon my &lt;a href='/blog/2009/09/pkgsrc-on-solaris/'&gt;previous post&lt;/a&gt; using pkgsrc to build binary packages on Solaris.&lt;/p&gt;

&lt;p&gt;See &lt;a href='http://imil.net/pkgin/'&gt;http://imil.net/pkgin/&lt;/a&gt; for more information on pkgin.&lt;/p&gt;

&lt;p&gt;Hopefully this will prove really useful to people still using Solaris 10 and unable to use the new pkg(5) stuff in OpenSolaris.&lt;/p&gt;

&lt;p&gt;Please try it out and provide any feedback to &lt;a href='mailto:pkgsrc-users@netbsd.org'&gt;pkgsrc-users@netbsd.org&lt;/a&gt;. I&amp;#8217;m hoping to keep the packages updated for the 2009Q3 branch.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>ZFS+NFS vs OSX</title>
      <link>http://www.perkin.org.uk/blog/2009/09/zfs%2Bnfs-vs-osx/</link>
      <pubDate>Wed, 16 Sep 2009 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2009/09/zfs+nfs-vs-osx</guid>
      <description>&lt;p&gt;gromit is my Solaris 10 server, chorlton is my OSX desktop. Explain this:&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;root@gromit#&lt;/span&gt; zfs &lt;span class='nb'&gt;set &lt;/span&gt;&lt;span class='nv'&gt;sharenfs&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;anon=shared,sec=none&amp;#39;&lt;/span&gt; gromit/store
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;root@gromit#&lt;/span&gt; zfs get sharenfs gromit/store
&lt;span class='go'&gt;NAME          PROPERTY  VALUE                 SOURCE&lt;/span&gt;
&lt;span class='go'&gt;gromit/store  sharenfs  anon=shared,sec=none  local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;user@chorlton$&lt;/span&gt; ls /net/gromit/store
&lt;span class='go'&gt;ls: cannot open directory /net/gromit/store/: Operation not permitted&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;root@gromit#&lt;/span&gt; zfs &lt;span class='nb'&gt;set &lt;/span&gt;&lt;span class='nv'&gt;sharenfs&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;anon=shared&amp;#39;&lt;/span&gt; gromit/store
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;user@chorlton$&lt;/span&gt; ls /net/gromit/store
&lt;span class='go'&gt;file1  file2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;user@chorlton$&lt;/span&gt; touch /net/gromit/store/file3
&lt;span class='go'&gt;touch: /net/gromit/store/file3: Permission denied&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;root@gromit#&lt;/span&gt; zfs &lt;span class='nb'&gt;set &lt;/span&gt;&lt;span class='nv'&gt;sharenfs&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;anon=shared,sec=none&amp;#39;&lt;/span&gt; gromit/store
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;user@chorlton$&lt;/span&gt; touch /net/gromit/store/file3
&lt;span class='gp'&gt;user@chorlton$&lt;/span&gt; &lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='nv'&gt;$?&lt;/span&gt;
&lt;span class='go'&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>pkgsrc on Solaris</title>
      <link>http://www.perkin.org.uk/blog/2009/09/pkgsrc-on-solaris/</link>
      <pubDate>Sat, 12 Sep 2009 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2009/09/pkgsrc-on-solaris</guid>
      <description>&lt;p&gt;For many years, building and installing third-party software on Solaris has been a huge pain. For people who do not use &lt;a href='http://www.pkgsrc.org/'&gt;pkgsrc&lt;/a&gt;, that is.&lt;/p&gt;

&lt;p&gt;Originating from the &lt;a href='http://www.netbsd.org/'&gt;NetBSD&lt;/a&gt; project, pkgsrc is a source-based cross-platform package manager. If you&amp;#8217;ve used FreeBSD ports, then it is very similar as it derives from the same codebase, so the basic premise is that you:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /usr/pkgsrc/www/apache22
&lt;span class='gp'&gt;$&lt;/span&gt; make package
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and pkgsrc will download the source for Apache 2.2, compile it and all dependancies, install it on the local system and create a package which can be installed on other similar systems.&lt;/p&gt;

&lt;p&gt;However, we&amp;#8217;ve taken ports further and applied the NetBSD philosophy of portability, meaning that it not only works on NetBSD, but across all *BSD as well as Linux, OSX, HP/UX, AIX, IRIX, QNX, Windows (via Interix), and of course Solaris.&lt;/p&gt;

&lt;p&gt;So while apt-get might be awesome, it only really works on Linux. FreeBSD might have way more ports than us, but only runs on FreeBSD and OSX. pkgsrc provides a consistent interface across all the platforms listed above, and in some cases provides a superior package manager than the system provides.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s how I use pkgsrc on Solaris, in this specific case Solaris 10/x86. Paths are specific to my setup, you can of course change them.&lt;/p&gt;

&lt;h2 id='create_a_chrootzone_environment'&gt;Create a chroot/zone environment&lt;/h2&gt;

&lt;p&gt;I use the zones feature of Solaris 10 to ensure that all packages are built in a sandbox. This has a number of benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The running system is unaffected by the builds, in that they are not writing to the same file system. This is good when you have misbehaving packages.&lt;/li&gt;

&lt;li&gt;You can separate the build and install phases, so that you can verify all the packages have been built and are correct before starting any install/upgrade procedure&lt;/li&gt;

&lt;li&gt;It&amp;#8217;s easier to catch package mistakes, e.g. unpackaged files.&lt;/li&gt;

&lt;li&gt;It avoids pollution from the host environment which may produce bad packages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For creating a zone, I wrote the following &lt;a href='/files/solaris-pkgsrc/create-zone'&gt;&lt;code&gt;create-zone&lt;/code&gt;&lt;/a&gt; script:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

&lt;span class='nv'&gt;DOMAIN&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;adsl.perkin.org.uk&amp;quot;&lt;/span&gt;
&lt;span class='nv'&gt;MASQDOMAIN&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;perkin.org.uk&amp;quot;&lt;/span&gt;
&lt;span class='nv'&gt;PHYSIF&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;e1000g0&amp;quot;&lt;/span&gt;
&lt;span class='nv'&gt;RPOOL&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;gromit&amp;quot;&lt;/span&gt;

&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='nv'&gt;$# &lt;/span&gt;-eq 1 &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nv'&gt;name&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='nv'&gt;$1&lt;/span&gt;; &lt;span class='nb'&gt;shift&lt;/span&gt;
&lt;span class='nb'&gt;    &lt;/span&gt;&lt;span class='nv'&gt;ipaddr&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='sb'&gt;`&lt;/span&gt;getent hosts &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;name&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; | awk &lt;span class='s1'&gt;&amp;#39;{print $1}&amp;#39;&lt;/span&gt;&lt;span class='sb'&gt;`&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; -z &lt;span class='s2'&gt;&amp;quot;${ipaddr}&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;        &lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;ERROR: Could not determine IP address of $name&amp;quot;&lt;/span&gt;
        &lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Either add to hosts database or provide on command line&amp;quot;&lt;/span&gt;
        &lt;span class='nb'&gt;echo&lt;/span&gt;
&lt;span class='nb'&gt;        echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;usage: $0 &amp;lt;name&amp;gt; [ &amp;lt;ipaddr&amp;gt; ]&amp;quot;&lt;/span&gt;
        &lt;span class='nb'&gt;exit &lt;/span&gt;2
    &lt;span class='k'&gt;fi&lt;/span&gt;
&lt;span class='k'&gt;elif&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='nv'&gt;$# &lt;/span&gt;-eq 2 &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nv'&gt;name&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='nv'&gt;$1&lt;/span&gt;; &lt;span class='nb'&gt;shift&lt;/span&gt;
&lt;span class='nb'&gt;    &lt;/span&gt;&lt;span class='nv'&gt;ipaddr&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='nv'&gt;$1&lt;/span&gt;; &lt;span class='nb'&gt;shift&lt;/span&gt;
&lt;span class='k'&gt;else&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;usage: $0 &amp;lt;name&amp;gt; [ &amp;lt;ipaddr&amp;gt; ]&amp;quot;&lt;/span&gt;
    &lt;span class='nb'&gt;exit &lt;/span&gt;2
&lt;span class='k'&gt;fi&lt;/span&gt;

zfs list &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;RPOOL&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/zones/&lt;span class='nv'&gt;$name&lt;/span&gt; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1
&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='nv'&gt;$?&lt;/span&gt; -eq 0 &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;${RPOOL}/zones/$name already exists, not continuing&amp;quot;&lt;/span&gt;
    &lt;span class='nb'&gt;exit &lt;/span&gt;1
&lt;span class='k'&gt;fi&lt;/span&gt;

&lt;span class='c'&gt;# Inherited directories are read-only&lt;/span&gt;
cat &amp;gt;/tmp/zonecfg.&lt;span class='nv'&gt;$$&lt;/span&gt; &lt;span class='s'&gt;&amp;lt;&amp;lt; EOF&lt;/span&gt;
&lt;span class='s'&gt;    create&lt;/span&gt;
&lt;span class='s'&gt;    set zonepath=/zones/$name&lt;/span&gt;
&lt;span class='s'&gt;    set autoboot=true&lt;/span&gt;
&lt;span class='s'&gt;    add net&lt;/span&gt;
&lt;span class='s'&gt;        set address=$ipaddr/24&lt;/span&gt;
&lt;span class='s'&gt;        set physical=${PHYSIF}&lt;/span&gt;
&lt;span class='s'&gt;    end&lt;/span&gt;
&lt;span class='s'&gt;    verify&lt;/span&gt;
&lt;span class='s'&gt;    commit&lt;/span&gt;
&lt;span class='s'&gt;    exit&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;

zonecfg -z &lt;span class='nv'&gt;$name&lt;/span&gt; -f /tmp/zonecfg.&lt;span class='nv'&gt;$$&lt;/span&gt;
rm /tmp/zonecfg.&lt;span class='nv'&gt;$$&lt;/span&gt;

zoneadm -z &lt;span class='nv'&gt;$name&lt;/span&gt; install

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Automatically configure new zone with most of the settings from the current&lt;/span&gt;
&lt;span class='c'&gt;# global, grabbing the encrypted root password directly.  Note that the&lt;/span&gt;
&lt;span class='c'&gt;# service_profile keyword doesn&amp;#39;t seem to be used here, so we configure the&lt;/span&gt;
&lt;span class='c'&gt;# limited_net profile manually and optionally install a custom site.xml which&lt;/span&gt;
&lt;span class='c'&gt;# is parsed and activated during first boot.&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
cat &lt;span class='s'&gt;&amp;lt;&amp;lt; EOF &amp;gt;/zones/$name/root/etc/sysidcfg&lt;/span&gt;
&lt;span class='s'&gt;network_interface=PRIMARY&lt;/span&gt;
&lt;span class='s'&gt;{&lt;/span&gt;
&lt;span class='s'&gt;    hostname=$name.${DOMAIN}&lt;/span&gt;
&lt;span class='s'&gt;}&lt;/span&gt;
&lt;span class='s'&gt;name_service=DNS&lt;/span&gt;
&lt;span class='s'&gt;{&lt;/span&gt;
&lt;span class='s'&gt;    domain_name=${DOMAIN}&lt;/span&gt;
&lt;span class='s'&gt;    name_server=`awk &amp;#39;/^nameserver/ { print $NF; exit }&amp;#39; /etc/resolv.conf`&lt;/span&gt;
&lt;span class='s'&gt;}&lt;/span&gt;
&lt;span class='s'&gt;nfs4_domain=dynamic&lt;/span&gt;
&lt;span class='s'&gt;root_password=`awk -F: &amp;#39;/^root/ {print $2}&amp;#39; /etc/shadow`&lt;/span&gt;
&lt;span class='s'&gt;security_policy=NONE&lt;/span&gt;
&lt;span class='s'&gt;service_profile=limited_net&lt;/span&gt;
&lt;span class='s'&gt;system_locale=C&lt;/span&gt;
&lt;span class='s'&gt;terminal=xterm&lt;/span&gt;
&lt;span class='s'&gt;timezone=Europe/London&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Use the limited_net profile and install custom site.xml if provided.&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
rm /zones/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;name&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/root/var/svc/profile/generic.xml
ln -s generic_limited_net.xml /zones/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;name&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/root/var/svc/profile/generic.xml
&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; -f /install/zones/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;name&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.xml &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;cp /install/zones/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;name&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.xml /zones/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;name&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/root/var/svc/profile/site.xml
&lt;span class='k'&gt;fi&lt;/span&gt;

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Disable nscd host cache&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
ex /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/nscd.conf &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='s'&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class='s'&gt;/enable-cache/s/^#//&lt;/span&gt;
&lt;span class='s'&gt;wq&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Configure sendmail to masquerade and route via smarthost.&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
ex /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/mail/cf/cf/submit.mc &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='s'&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class='s'&gt;/^dnl/&lt;/span&gt;
&lt;span class='s'&gt;a&lt;/span&gt;
&lt;span class='s'&gt;FEATURE(\`masquerade_envelope&amp;#39;)dnl&lt;/span&gt;
&lt;span class='s'&gt;MASQUERADE_AS(\`${MASQDOMAIN}&amp;#39;)dnl&lt;/span&gt;
&lt;span class='s'&gt;dnl&lt;/span&gt;
&lt;span class='s'&gt;.&lt;/span&gt;
&lt;span class='s'&gt;/^FEATURE.*msp/s/.127.0.0.1./mail.perkin.org.uk/&lt;/span&gt;
&lt;span class='s'&gt;wq!&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;
&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cd&lt;/span&gt; /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/mail/cf/cf; /usr/ccs/bin/make submit.cf &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&lt;span class='o'&gt;)&lt;/span&gt;
cp /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/mail/cf/cf/submit.cf /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/mail/submit.cf

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Use SHA512 crypted passwords, and change root&amp;#39;s home directory.&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
ex /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/security/policy.conf &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='s'&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class='s'&gt;/^CRYPT_DEFAULT/s/__unix__/6/&lt;/span&gt;
&lt;span class='s'&gt;wq&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;
mkdir -m 0700 /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/root
ex /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/passwd &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='s'&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class='s'&gt;/^root/s,:/:,:/root:,&lt;/span&gt;
&lt;span class='s'&gt;/^root/s,:/sbin/sh,:/bin/bash,&lt;/span&gt;
&lt;span class='s'&gt;wq&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;

cp /root/.bash_profile /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/root/.bash_profile

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Allow root login over SSH (rest of network takes care of external access&lt;/span&gt;
&lt;span class='c'&gt;# so this isn&amp;#39;t a problem) and enforce SSH key authentication.&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
ex /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/ssh/sshd_config &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='s'&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class='s'&gt;/^PermitRootLogin/s/no$/yes/&lt;/span&gt;
&lt;span class='s'&gt;/^PasswordAuthentication/s/yes$/no/&lt;/span&gt;
&lt;span class='s'&gt;wq&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;
mkdir -m 0700 /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/root/.ssh
cp /home/jperkin/.ssh/local_rsa.pub /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/root/.ssh/authorized_keys

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Automount shared directories from global zone using direct mounts&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
ex /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/auto_master &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='s'&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class='s'&gt;a&lt;/span&gt;
&lt;span class='s'&gt;/-        auto_direct&lt;/span&gt;
&lt;span class='s'&gt;.&lt;/span&gt;
&lt;span class='s'&gt;wq&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;
ex /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/auto_direct &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='s'&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class='s'&gt;a&lt;/span&gt;
&lt;span class='s'&gt;/content    gromit-lan:/content&lt;/span&gt;
&lt;span class='s'&gt;/install    gromit-lan:/install&lt;/span&gt;
&lt;span class='s'&gt;.&lt;/span&gt;
&lt;span class='s'&gt;wq&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# All done!  Fire it up...&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
zoneadm -z &lt;span class='nv'&gt;$name&lt;/span&gt; boot
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And the corresponding &lt;a href='/files/solaris-pkgsrc/delete-zone'&gt;&lt;code&gt;delete-zone&lt;/code&gt;&lt;/a&gt; script is:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

&lt;span class='nv'&gt;RPOOL&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;gromit&amp;quot;&lt;/span&gt;

&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='nv'&gt;$# &lt;/span&gt;-ne 1 &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;usage: $0 &amp;lt;zone&amp;gt;&amp;quot;&lt;/span&gt;
    &lt;span class='nb'&gt;exit &lt;/span&gt;2
&lt;span class='k'&gt;fi&lt;/span&gt;

zoneadm -z &lt;span class='nv'&gt;$1&lt;/span&gt; halt
zonecfg -z &lt;span class='nv'&gt;$1&lt;/span&gt; delete -F
zfs destroy &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;RPOOL&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/zones/&lt;span class='nv'&gt;$1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you want to use them then there are some variables to set at the top, and you may want to scan through them for additional bits to change, for example &lt;a href='/files/solaris-pkgsrc/create-zone'&gt;&lt;code&gt;create-zone&lt;/code&gt;&lt;/a&gt; copies my ssh public key which will most likely be wrong for your setup :-)&lt;/p&gt;

&lt;p&gt;One additional piece of configuration for &lt;a href='/files/solaris-pkgsrc/create-zone'&gt;&lt;code&gt;create-zone&lt;/code&gt;&lt;/a&gt; is an optional SMF xml file. I use this file to disable inetd inside the zone for additional security, like so:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='xml'&gt;&lt;span class='cp'&gt;&amp;lt;?xml version=&amp;#39;1.0&amp;#39;?&amp;gt;&lt;/span&gt;
&lt;span class='cp'&gt;&amp;lt;!DOCTYPE service_bundle SYSTEM &amp;#39;/usr/share/lib/xml/dtd/service_bundle.dtd.1&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class='nt'&gt;&amp;lt;service_bundle&lt;/span&gt; &lt;span class='na'&gt;type=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;profile&amp;#39;&lt;/span&gt; &lt;span class='na'&gt;name=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;extract&amp;#39;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;lt;service&lt;/span&gt; &lt;span class='na'&gt;name=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;network/inetd&amp;#39;&lt;/span&gt; &lt;span class='na'&gt;type=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;service&amp;#39;&lt;/span&gt; &lt;span class='na'&gt;version=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
    &lt;span class='nt'&gt;&amp;lt;instance&lt;/span&gt; &lt;span class='na'&gt;name=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;default&amp;#39;&lt;/span&gt; &lt;span class='na'&gt;enabled=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;false&amp;#39;&lt;/span&gt;&lt;span class='nt'&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;lt;/service&amp;gt;&lt;/span&gt;
&lt;span class='nt'&gt;&amp;lt;/service_bundle&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The file should be named &amp;#60;yourzonename&amp;#62;.xml. Mine is named &lt;a href='/files/solaris-pkgsrc/vm-generic.xml'&gt;&lt;code&gt;vm-generic.xml&lt;/code&gt;&lt;/a&gt; and I then create symlinks to it for each VM I want with that default configuration.&lt;/p&gt;

&lt;h2 id='fetch_pkgsrc'&gt;Fetch pkgsrc&lt;/h2&gt;

&lt;p&gt;pkgsrc is developed very rapidly. Tracking nearly 9,000 pieces of third-party software means there are always many updates. Thankfully, we provide quarterly branches for people who want more stability, and I recommend using the latest quarterly release. At time of writing, this is known as &lt;code&gt;pkgsrc-2009Q2&lt;/code&gt;. Within the next month or so we will release &lt;code&gt;pkgsrc-2009Q3&lt;/code&gt;, and you can figure out the names of future releases yourself.&lt;/p&gt;

&lt;p&gt;The easiest way to get pkgsrc is using cvs. I keep stuff like this under &lt;code&gt;/content&lt;/code&gt; as opposed to the default of &lt;code&gt;/usr&lt;/code&gt;, you can use whatever you wish but will need to change all my example scripts to match where you put it.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /content
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;pkgsrc-2009Q2&amp;quot;&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; cvs -d anoncvs@anoncvs.netbsd.org:/cvsroot co -r&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; -d&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; -P pkgsrc
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Alternatively, you can fetch either bzip2 or gzip archives of the current branch. I recommend the cvs method as, with the branch being updated for security fixes and other important changes, you can easily track it using&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /content/pkgsrc-2009Q2
&lt;span class='gp'&gt;$&lt;/span&gt; cvs update
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='pkgsrc_configuration'&gt;pkgsrc configuration&lt;/h2&gt;

&lt;p&gt;pkgsrc is configured using a &lt;code&gt;mk.conf&lt;/code&gt; file, &lt;a href='/files/solaris-pkgsrc/mk.conf'&gt;this&lt;/a&gt; is mine:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;#
# Local settings
#
OS_HOST!= uname -n

#
# Per-host settings
#
#    vm0 builds local packages
#
.if !empty(OS_HOST:Mvm0.*) || !empty(OS_HOST:Mgromit.*)
PKGDIRSUFFIX=
PKG_DEFAULT_OPTIONS=    inet6 perl sasl ssl ncursesw
PKG_OPTIONS.mutt+=      mutt-hcache mutt-smtp
PKG_UID.cyrus=          2000
#PKG_GID.cyrus=         mail
PKG_SHELL.cyrus=        /usr/bin/false
PKG_UID.www=            2001
PKG_GID.www=            2001
PYTHON_VERSION_DEFAULT= 24
X11_TYPE=               modular
#
#    vm1 modular X11 bulk builds
#
.elif !empty(OS_HOST:Mvm1.*)
X11_TYPE=       modular
PKGDIRSUFFIX=   -${X11_TYPE}
#
#    vm2 native X11 bulk builds
#
.elif !empty(OS_HOST:Mvm2.*)
X11_TYPE=       native
PKGDIRSUFFIX=   -${X11_TYPE}
#
#    vm3 pkgsrc dev builds
#
.elif !empty(OS_HOST:Mvm3.*)
X11_TYPE=       modular
PKGDIRSUFFIX=   -${X11_TYPE}
.endif

.if exists(../../CVS/Tag)
PKG_BRANCH!=    ${TOOLS_PLATFORM.awk} -F- &amp;#39;{print $$2}&amp;#39; &amp;lt; ../../CVS/Tag
.else
PKG_BRANCH=     HEAD
.endif

ALLOW_VULNERABLE_PACKAGES=  YES
BULKFILESDIR=               ${WRKOBJDIR}
DISTDIR=                    /install/pkgsrc/distfiles/
FAILOVER_FETCH=             YES
INSTALL_UNSTRIPPED=         YES
LINTPKGSRC_DB=              ${_PKGSRCDIR}/.lintpkgsrc.db
MASTER_SITE_OVERRIDE=       ftp://ftp.netbsd.org/pub/NetBSD/packages/distfiles/
PACKAGES=                   /install/pkgsrc/packages/${PKG_BRANCH}${PKGDIRSUFFIX}
PKGCHK_CONF=                /install/pkgsrc/misc/pkgchk.conf
SKIP_LICENSE_CHECK=         YES
WRKOBJDIR=                  /tmp/pkgsrc

#
# Parse pkgchk.conf and supply list of packages for the bulk build framework.
#
.if defined(SPECIFIC_PKGS)
PKGLIST!= ${TOOLS_PLATFORM.awk} &amp;#39;$$1 !~ /^(\#|$$)/ {print $$1}&amp;#39; ${PKGCHK_CONF}
.  for _pkg_ in ${PKGLIST}
HOST_SPECIFIC_PKGS+= ${_pkg_}
.  endfor
.endif
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is the primary configuration file for pkgsrc. Again, you may need to tailor this to your environment, and may find it useful to read the pkgsrc guide to understand what it all means.&lt;/p&gt;

&lt;p&gt;As I do a lot of pkgsrc development I have a number of virtual machines up and running doing various bits and pieces. Obviously I don&amp;#8217;t want to copy that &lt;a href='/files/solaris-pkgsrc/mk.conf'&gt;mk.conf&lt;/a&gt; around, so I also have a small &lt;a href='/files/solaris-pkgsrc/mk-include.conf'&gt;fragment&lt;/a&gt; file which is appended to each virtual machine&amp;#8217;s &lt;code&gt;mk.conf&lt;/code&gt; (using the &lt;code&gt;--mk-fragment&lt;/code&gt; argument to &lt;code&gt;bootstrap&lt;/code&gt;) and includes the global copy:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;.include &amp;quot;/install/pkgsrc/misc/mk.conf&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The bulk build setup in pkgsrc requires its own configuration, and for this you will need to edit a file inside pkgsrc. There is an example file provided, so what I usually do is symlink this to the real copy then I can easily keep it up-to-date via cvs.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /content/pkgsrc-2009Q2/mk/bulk
&lt;span class='gp'&gt;$&lt;/span&gt; ln -s build.conf-example build.conf
&lt;span class='gp'&gt;$&lt;/span&gt; vi build.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Again, you can find my personal build.conf here.&lt;/p&gt;

&lt;p&gt;Finally, there is a configuration file for &lt;code&gt;pkg_chk&lt;/code&gt; which is a package inside pkgsrc which makes managing upgrades easier (ideally it should be a part of the main pkgsrc tools but that&amp;#8217;s for another day). &lt;code&gt;pkgchk.conf&lt;/code&gt; is a list of package directories, relative to the pkgsrc top level, which are to be built and installed for this setup. If you have a large installation then &lt;code&gt;pkg_chk&lt;/code&gt; has extra features to make it possible to share &lt;code&gt;pkgchk.conf&lt;/code&gt; across a number of machines and configure packages on a per-host, per-OS etc basis.&lt;/p&gt;

&lt;p&gt;Thus, a sample &lt;a href='/files/solaris-pkgsrc/pkgchk.conf'&gt;&lt;code&gt;pkgchk.conf&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;chat/irssi
chat/irssi-icb
converters/xlhtml
databases/lbdb
databases/rrdtool
devel/autoconf
devel/automake
devel/bzr
devel/bzrtools
devel/diffutils
devel/libtool-base
devel/scmcvs
editors/vim
mail/mutt-devel
misc/screen
net/p5-Net-SNMP
net/p5-Net-SNMP-Interfaces
net/rsync
net/samba
net/tnftp
pkgtools/digest
pkgtools/pkg_chk
pkgtools/rc.subr
print/mp
security/cy2-login
security/cy2-plain
security/sudo
sysutils/coreutils
textproc/antiword
textproc/grep
textproc/urlview
www/apache22
www/w3m
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It is highly likely you will want to change the &lt;code&gt;pkgchk.conf&lt;/code&gt; file from what I use :-)&lt;/p&gt;

&lt;h2 id='build_scripts'&gt;Build scripts&lt;/h2&gt;

&lt;p&gt;Once everything is set up, I have two scripts to build then update my packages, intuitively called &lt;a href='/files/solaris-pkgsrc/build-packages'&gt;&lt;code&gt;build-packages&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

&lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;/opt/pkg/sbin:/opt/pkg/bin:/sbin:/usr/sbin:/usr/bin:/usr/ccs/bin&amp;quot;&lt;/span&gt;
&lt;span class='nb'&gt;export &lt;/span&gt;PATH

&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;2009Q2&amp;quot;&lt;/span&gt;
&lt;span class='nb'&gt;export &lt;/span&gt;BRANCH

&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; ! -f /install/pkgsrc/bootstrap-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.tar &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nb'&gt;cd&lt;/span&gt; /content/pkgsrc-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/bootstrap
    ./bootstrap --workdir&lt;span class='o'&gt;=&lt;/span&gt;/tmp/pkgsrc --prefix&lt;span class='o'&gt;=&lt;/span&gt;/opt/pkg --varbase&lt;span class='o'&gt;=&lt;/span&gt;/var/opt/pkg --sysconfdir&lt;span class='o'&gt;=&lt;/span&gt;/etc/opt/pkg --mk-fragment&lt;span class='o'&gt;=&lt;/span&gt;/install/pkgsrc/misc/mk-include.conf --binary-kit&lt;span class='o'&gt;=&lt;/span&gt;/install/pkgsrc/bootstrap-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.tar
    rm -rf /tmp/pkgsrc
&lt;span class='k'&gt;fi&lt;/span&gt;

&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; ! -f /opt/pkg/bin/bmake &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
    &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cd&lt;/span&gt; /; tar -xf /install/pkgsrc/bootstrap-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.tar&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='k'&gt;fi&lt;/span&gt;

&lt;span class='nb'&gt;cd&lt;/span&gt; /content/pkgsrc-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;

/bin/ksh mk/bulk/build -s  2&amp;gt;&amp;amp;1 | tee -a /install/pkgsrc/logs/bulk-build-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.log
/bin/ksh mk/bulk/upload -n 2&amp;gt;&amp;amp;1 | tee -a /install/pkgsrc/logs/bulk-upload-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.log
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and &lt;a href='/files/solaris-pkgsrc/update-packages'&gt;&lt;code&gt;update-packages&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

&lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;/opt/pkg/sbin:/opt/pkg/bin:/sbin:/usr/sbin:/usr/bin:/usr/ccs/bin&amp;quot;&lt;/span&gt;
&lt;span class='nb'&gt;export &lt;/span&gt;PATH

&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;2009Q2
&lt;span class='nb'&gt;export &lt;/span&gt;BRANCH

&lt;span class='nv'&gt;PKGSRCDIR&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/content/pkgsrc-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
&lt;span class='nb'&gt;export &lt;/span&gt;PKGSRCDIR

&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; ! -f /opt/pkg/bin/bmake &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
    &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cd&lt;/span&gt; /; tar -xf /install/pkgsrc/bootstrap-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.tar&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='k'&gt;fi&lt;/span&gt;

&lt;span class='c'&gt;# Run this anyway in case there are updates to pkg_chk&lt;/span&gt;
env &lt;span class='nv'&gt;PKG_PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/install/pkgsrc/packages/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/All pkg_add -u pkg_chk

&lt;span class='c'&gt;# Dry run first&lt;/span&gt;
pkg_chk -aurbn

&lt;span class='nb'&gt;printf&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Do you wish to install? [y/N]: &amp;quot;&lt;/span&gt;
&lt;span class='nb'&gt;read &lt;/span&gt;ans
&lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;${ans}&amp;quot;&lt;/span&gt; in
&lt;span class='o'&gt;[&lt;/span&gt;Yy&lt;span class='o'&gt;])&lt;/span&gt;
    pkg_chk -aurb 2&amp;gt;&amp;amp;1 | tee -a /install/pkgsrc/logs/pkg_chk-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.log
    ;;
&lt;span class='k'&gt;esac&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;These are pretty simple as all the hard work has all been done. &lt;a href='/files/solaris-pkgsrc/build-packages'&gt;&lt;code&gt;build-packages&lt;/code&gt;&lt;/a&gt; is ran inside the zone, then &lt;a href='/files/solaris-pkgsrc/update-packages'&gt;&lt;code&gt;update-packages&lt;/code&gt;&lt;/a&gt; on the main host. These scripts hardcode the name of the branch currently used, so you will need to update this when moving to newer releases.&lt;/p&gt;

&lt;h2 id='quick_recap'&gt;Quick recap&lt;/h2&gt;

&lt;p&gt;Ok, so here is the stuff I have for my setup and where I keep them:&lt;/p&gt;
&lt;div class='table'&gt;
 &lt;table&gt;
  &lt;thead&gt;
   &lt;tr&gt;&lt;th&gt;Path&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/content/pkgsrc-2009Q2&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Checked out pkgsrc tree, &quot;2009Q2&quot; branch&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/content/scripts/&lt;a href='/files/solaris-pkgsrc/create-zone'&gt;create-zone&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Creates Solaris zone&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/content/scripts/&lt;a href='/files/solaris-pkgsrc/delete-zone'&gt;delete-zone&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Uninstalls and deletes zone&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/content/scripts/&lt;a href='/files/solaris-pkgsrc/build-packages'&gt;build-packages&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Bulk build packages inside the zone&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/content/scripts/&lt;a href='/files/solaris-pkgsrc/update-packages'&gt;update-packages&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Updates installed packages&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/install/pkgsrc/misc/&lt;a href='/files/solaris-pkgsrc/mk.conf'&gt;mk.conf&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Main pkgsrc configuration file&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/install/pkgsrc/misc/&lt;a href='/files/solaris-pkgsrc/mk-include.conf'&gt;mk-include.conf&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Fragment file included in each zone's &lt;code&gt;mk.conf&lt;/code&gt;, sources the global &lt;code&gt;mk.conf&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/install/pkgsrc/misc/&lt;a href='/files/solaris-pkgsrc/pkgchk.conf'&gt;pkgchk.conf&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;pkg_chk&lt;/code&gt; configuration file&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/install/zones/&lt;a href='/files/solaris-pkgsrc/vm-generic.xml'&gt;vm-generic.xml&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Shared SMF configuration file, symlinked to from e.g. &quot;&lt;code&gt;vm0.xml&lt;/code&gt;&quot;&lt;/td&gt;&lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;And these are the paths where stuff will be created:&lt;/p&gt;
&lt;div class='table'&gt;
 &lt;table&gt;
  &lt;thead&gt;
   &lt;tr&gt;&lt;th&gt;Path&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/install/pkgsrc/distfiles&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Source tarballs of packages&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/install/pkgsrc/packages/2009Q2&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Resulting binary packages&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/tmp/pkgsrc&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Temporary build area for packages&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/content/vwww/www.adsl.perkin.org.uk/pkgstat&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Bulk build results directory&lt;/td&gt;&lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;It&amp;#8217;s definitely harder than it should be to get this all setup, but the good news is that once it&amp;#8217;s done there&amp;#8217;s very little maintenance.&lt;/p&gt;

&lt;h2 id='kicking_it_all_off'&gt;Kicking it all off&lt;/h2&gt;

&lt;p&gt;Once everything is setup:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; /content/scripts/create-zone vm0
&lt;span class='gp'&gt;$&lt;/span&gt; ssh vm0 /content/scripts/build-packages
&lt;span class='gp'&gt;$&lt;/span&gt; /content/scripts/update-packages
&lt;span class='gp'&gt;$&lt;/span&gt; /content/scripts/delete-zone vm0
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This should do the lot. Once &lt;a href='/files/solaris-pkgsrc/build-packages'&gt;&lt;code&gt;build-packages&lt;/code&gt;&lt;/a&gt; has finished you should, if you configured your email address in build.conf, get an email with the bulk build results which looks similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href='http://mail-index.netbsd.org/pkgsrc-bulk/2009/08/23/msg006883.html'&gt;http://mail-index.netbsd.org/pkgsrc-bulk/2009/08/23/msg006883.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A fuller report is available if you configure a web server to serve the &lt;code&gt;pkgstat&lt;/code&gt; directory created by the bulk build, and this can help debug problems (again see the above URL for an example).&lt;/p&gt;

&lt;p&gt;You will need to add &lt;code&gt;/opt/pkg/sbin:/opt/pkg/bin&lt;/code&gt; to &lt;code&gt;$PATH&lt;/code&gt;. Configuration files are in &lt;code&gt;/etc/opt/pkg&lt;/code&gt;, and log files and metadata are kept in &lt;code&gt;/var/opt/pkg&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id='this_stuff_should_be_obsolete'&gt;This stuff should be obsolete&lt;/h2&gt;

&lt;p&gt;While this all works well for me, it&amp;#8217;s pretty lame for users who just want to install packages and have stuff work. I&amp;#8217;m working on providing regular updates of binary packages, including a SVR4 package of the bootstrap kit, so that in theory all a user needs to do is&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; pkgadd TNFpkgsrc.pkg
&lt;span class='gp'&gt;$&lt;/span&gt; pkg_add apache22
&lt;span class='gp'&gt;#&lt;/span&gt; Upgrade all installed packages to latest releases
&lt;span class='gp'&gt;$&lt;/span&gt; pkg_chk -aurb
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I&amp;#8217;m almost there, just needs some tidying up and regular builds. Please feel free to help out!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Jumpstart from OSX</title>
      <link>http://www.perkin.org.uk/blog/2008/12/jumpstart-from-osx/</link>
      <pubDate>Tue, 09 Dec 2008 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/blog/2008/12/jumpstart-from-osx</guid>
      <description>&lt;p&gt;I recently built a new file server on which I planned to install Solaris 10 10/08. I&amp;#8217;m not a fan of CD/DVD installs, so wanted to jumpstart via PXE, though I only had OSX handy.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s how I installed my new machine (gromit.adsl.perkin.org.uk/192.168.1.10) from my iMac (192.168.1.30) over the local network.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note that since writing this piece I&amp;#8217;ve updated to Solaris 10 10/09, and have changed the examples to use that instead.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id='step_1_prepare_file_system'&gt;Step 1, Prepare File System&lt;/h2&gt;

&lt;p&gt;First off, create a dedicated file system which we can export our jumpstart configuration from. You can probably skip this and just use any existing file system but this way everything is self-contained and we avoid NFS exporting more than we need.&lt;/p&gt;

&lt;p&gt;We use HFSX to ensure that the file system is case sensitive, HFS+ can cause problems with &lt;code&gt;pkgadd(1M)&lt;/code&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; hdiutil create -size 1g -type SPARSE -fs HFSX -volname &lt;span class='s2'&gt;&amp;quot;install&amp;quot;&lt;/span&gt; install
&lt;span class='gp'&gt;$&lt;/span&gt; hdiutil attach install.sparseimage -mountpoint /install
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Next up, download and mount &lt;code&gt;sol-10-u8-ga-x86-dvd.iso&lt;/code&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; open sol-10-u8-ga-x86-dvd.iso
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='step_2_nfs'&gt;Step 2, NFS&lt;/h2&gt;

&lt;p&gt;Share &lt;code&gt;/install&lt;/code&gt; and the DVD via NFS with the correct options. &lt;code&gt;-alldirs&lt;/code&gt; allows clients to mount from any point within that file system (which jumpstart requires), and &lt;code&gt;-maproot=root&lt;/code&gt; is also required by jumpstart. As this allows root-owned files to be created, make sure you understand the security risks.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo vi /etc/exports
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;/install                  -alldirs -maproot=root
/Volumes/SOL_10_1009_X86  -alldirs -maproot=root
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo nfsd checkexports &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo nfsd &lt;span class='nb'&gt;enable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='step_3_dhcp'&gt;Step 3, DHCP&lt;/h2&gt;

&lt;p&gt;For DHCP I happen to already use my Cisco router as a DHCP server on the local network, so added the following configuration:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;ip dhcp pool gromit.adsl.perkin.org.uk
   host 192.168.1.10 255.255.255.0
   hardware-address xxxx.xxxx.xxxx
   bootfile /boot/grub/pxegrub
   next-server 192.168.1.30
   client-name gromit
   domain-name adsl.perkin.org.uk
   dns-server xxx.xxx.xxx.xxx
   default-router 192.168.1.1
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;however, given this is a guide for setting everything up under OSX I also tried using ISC DHCP on OSX to prove it can be done that way too.&lt;/p&gt;

&lt;p&gt;I used &lt;a href='http://www.pkgsrc.org/'&gt;pkgsrc&lt;/a&gt; to install it (I&amp;#8217;ll add another blog some time showing how to set up pkgsrc)&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /usr/pkgsrc/net/isc-dhcpd
&lt;span class='gp'&gt;$&lt;/span&gt; sudo bmake package
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And here is my DHCP configuration file in full:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;option domain-name &amp;quot;adsl.perkin.org.uk&amp;quot;;
option domain-name-servers xxx.xxx.xxx.xxx;
ddns-update-style none;
authoritative;
log-facility local7;

subnet 192.168.1.0 netmask 255.255.255.0 {
    option routers 192.168.1.1;
}

group {
    filename &amp;quot;/boot/grub/pxegrub&amp;quot;;
    next-server 192.168.1.30;

    host gromit {
        hardware ethernet xx:xx:xx:xx:xx:xx;
        fixed-address 192.168.1.10;
        option host-name &amp;quot;gromit.adsl.perkin.org.uk&amp;quot;;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Finally, start DHCP with:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo /usr/pkg/sbin/dhcpd
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Most parts of these configurations should be self-explanatory. The &lt;code&gt;/boot/grub/pxegrub&lt;/code&gt; entry is important for our next step, and I&amp;#8217;d recommend using that exact pathname for reasons explained later.&lt;/p&gt;

&lt;h2 id='step_4_tftp'&gt;Step 4, TFTP&lt;/h2&gt;

&lt;p&gt;Now, enable the TFTP server which comes with OSX. I added the &lt;code&gt;-s&lt;/code&gt; option so tftpd would chroot to the tftpboot directory, both for security reasons and also to ensure that paths specified as &lt;code&gt;/path/to/file&lt;/code&gt; would work correctly (relative to &lt;code&gt;/install/tftpboot&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;I also changed the location of the tftpboot directory so that everything was self-contained within the UFS image. In previous attempts I didn&amp;#8217;t do this and ran into problems with GRUB which I think are again caused by case-insensitive file systems.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo vi /System/Library/LaunchDaemons/tftp.plist
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='xml'&gt;[...]
    &lt;span class='nt'&gt;&amp;lt;key&amp;gt;&lt;/span&gt;ProgramArguments&lt;span class='nt'&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class='nt'&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
        &lt;span class='nt'&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/usr/libexec/tftpd&lt;span class='nt'&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class='nt'&gt;&amp;lt;string&amp;gt;&lt;/span&gt;-i&lt;span class='nt'&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class='nt'&gt;&amp;lt;string&amp;gt;&lt;/span&gt;-s&lt;span class='nt'&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class='nt'&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/install/tftpboot&lt;span class='nt'&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class='nt'&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
[...]
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; mkdir /install/tftpboot
&lt;span class='gp'&gt;$&lt;/span&gt; sudo launchctl load -w /System/Library/LaunchDaemons/tftp.plist
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can then create a test file and check that it&amp;#8217;s working as you expect, using:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;testing&amp;quot;&lt;/span&gt; &amp;gt;/install/tftpboot/testfile
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;printf&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;verbose\ntrace\nget testfile\n&amp;quot;&lt;/span&gt; | tftp localhost
&lt;span class='gp'&gt;$&lt;/span&gt; rm /install/tftpboot/testfile
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='step_5_grub'&gt;Step 5, GRUB&lt;/h2&gt;

&lt;p&gt;Next up, configure PXE booting using GRUB. We need to copy the GRUB images and configuration from the Solaris install DVD then modify it for our environment:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; rsync -av /Volumes/SOL_10_1009_X86/boot/grub /install/tftpboot/boot/
&lt;span class='gp'&gt;$&lt;/span&gt; rsync -av /Volumes/SOL_10_1009_X86/boot/multiboot /install/tftpboot/sol10u8x/
&lt;span class='gp'&gt;$&lt;/span&gt; rsync -av /Volumes/SOL_10_1009_X86/boot/x86.miniroot /install/tftpboot/sol10u8x/
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As we are copying the boot files from the DVD, they come hardcoded with particular pathnames to e.g. the &lt;code&gt;menu.lst&lt;/code&gt; file. While it may be possible to pass extra parameters to pxegrub and load this from a different path, I simply recommend doing as I do and replicating the &lt;code&gt;/boot/grub/&lt;/code&gt; path structure so that everything Just Works.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;menu.lst&lt;/code&gt; file includes kernel arguments and allows you to choose which type of install to perform at startup. My file listed below has 3 choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unattended install using a graphical environment (if available). The &amp;#8216;install&amp;#8217; keyword after the kernel instructs it to perform an unattended install, so long as it can find the necessary settings from sysidcfg etc.&lt;/li&gt;

&lt;li&gt;As above, but force the use of the console and do not start a graphical environment (using the &amp;#8216;nowin&amp;#8217; keyword)&lt;/li&gt;

&lt;li&gt;A manual install, so you need to go through the steps of layout out disks, selecting packages, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; vi /install/tftpboot/boot/grub/menu.lst
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;default=0
timeout=60

title Solaris PXE Unattended Install
    kernel /sol10u8x/multiboot kernel/unix - install -B \
      install_media=192.168.1.30:/Volumes/SOL_10_1009_X86,\
      sysid_config=192.168.1.30:/install/jumpstart,\
      install_config=192.168.1.30:/install/jumpstart
    module /sol10u8x/x86.miniroot

title Solaris PXE Unattended Install (console)
    kernel /sol10u8x/multiboot kernel/unix - install nowin -B \
      install_media=192.168.1.30:/Volumes/SOL_10_1009_X86,\
      sysid_config=192.168.1.30:/install/jumpstart,\
      install_config=192.168.1.30:/install/jumpstart
    module /sol10u8x/x86.miniroot

title Solaris PXE Manual Install
    kernel /sol10u8x/multiboot kernel/unix -B \
      install_media=192.168.1.30:/Volumes/SOL_10_1009_X86
    module /sol10u8x/x86.miniroot
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Anyone used to doing jumpstart but with RARP/bootparams will notice the symmetry between &lt;code&gt;install_config&lt;/code&gt; etc in the GRUB configuration and similar options in &lt;code&gt;/etc/bootparams&lt;/code&gt;. Make sure that the full kernel arguments are all on one line, and that there are no spaces in between the &lt;code&gt;install_media=..,sysid_config=..&lt;/code&gt; options.&lt;/p&gt;

&lt;h2 id='step_6_jumpstart'&gt;Step 6, Jumpstart&lt;/h2&gt;

&lt;p&gt;Finally, set up your Jumpstart configuration. Here&amp;#8217;s what I personally use, you may want something different:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; mkdir /install/jumpstart
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /install/jumpstart
&lt;span class='gp'&gt;$&lt;/span&gt; vi sysidcfg
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;name_service=DNS
{
    domain_name=adsl.perkin.org.uk
    name_server=xxx.xxx.xxx.xxx
}
network_interface=PRIMARY
{
    default_route=192.168.1.1
    netmask=255.255.255.0
    protocol_ipv6=yes
}
nfs4_domain=dynamic
root_password=xxxxxxxx
terminal=xterm
timeserver=localhost
timezone=Europe/London
security_policy=NONE
service_profile=limited_net
system_locale=C
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Ordinarily this file is processed using a &lt;code&gt;check&lt;/code&gt; script available in the &lt;code&gt;jumpstart_sample&lt;/code&gt; directory on the Solaris DVD, however this only works from a Solaris host. To create the &lt;code&gt;rules.ok&lt;/code&gt; file, we need to strip out any comments and put entries on one line, then create the checksum (although this isn&amp;#8217;t actually necessary).&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; vi rules &lt;span class='c'&gt;# emacs sucks :)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;hostname gromit.adsl.perkin.org.uk - profile -
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; cp rules rules.ok
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;# version=2 checksum=$(cksum -o 2 rules | awk &amp;#39;{print $1}&amp;#39;)&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; rules.ok
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Machine profile. This gives me a full Solaris install (minus OEM stuff) on mirrored ZFS disks with additional dump/swap space (the defaults made dump a bit too small I found).&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; vi profile
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;install_type    initial_install
pool            store auto 4g 4g mirror c1t0d0s0 c1t1d0s0
bootenv         installbe bename sol10u8x
cluster         SUNWCall
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='step_7_make_a_cup_of_tea'&gt;Step 7, Make A Cup Of Tea&lt;/h2&gt;

&lt;p&gt;With everything set up you should be able to enable PXE booting in your BIOS and watch it automatically install. One small minor problem you may have if you don&amp;#8217;t have a BIOS which allows you to hit F12 or similar and choose PXE booting for one boot only is that it will infinitely cycle through installing, rebooting, installing, rebooting.. until you change your boot options.&lt;/p&gt;

&lt;p&gt;If this happens, I recommend making more cups of tea until you happen to return in time to change the BIOS settings. If you aren&amp;#8217;t able to do this for a while, you may need to add the extra steps 8, 9 and 10 titled &amp;#8220;Visit The Bathroom&amp;#8221;.&lt;/p&gt;</description>
    </item>
    

  </channel>
</rss>

