My Musings2014-08-11T06:32:52+00:00http://.github.com/Blog/Dr Nic Williamswilliams@gmail.comFixing rack-protection2013-05-12T00:00:00+00:00http://.github.com/Blog/2013/05/12/Fixing-rack-protection<p>Today, I ran into a problem on my Debian development system. In coding something with a friend of mine, I needed to install Sinatra so that we could get a quick Web UI going to be able to both see the output at the same time. I ran into a problem though.</p>
<pre><code> jeff@dev> sudo gem1.9.1 install sinatra ~/Projects
ERROR: While executing gem ... (ArgumentError)
invalid byte sequence in US-ASCII
</code></pre>
<p>Googling for this answer produced some unhelpful results, so I started to dig into this a bit further. It seemed to be a locale problem, so I checked <code>env</code> but didn’t find anything problematic. Regardless, I tried one of the suggestions of setting some environmental variables to specify a locale. No change. </p>
<p>So, I thought, if it’s not my environment, it must be the gem. So I forked the Sinatra gem on Github and cloned it to my local machine – this would make it easier to submit a pull request later when I found and fixed the bug. After cloning, I edited the Gemfile to contain one of the fixes I had found. I built the gem and ran gem install again – but again felt no love. After some coffee, head-scratching, and chin-hair stroking, I tried strace.</p>
<pre><code> open("/var/lib/gems/1.9.1/cache/rack-protection-1.5.0.gem", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 6
ioctl(6, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7ffffa3631b0) = -1 ENOTTY (Inappropriate ioctl for device)
write(6, "data.tar.gz\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 15872) = 15872
close(6) = 0
stat("/var/lib/gems/1.9.1/cache/rack-protection-1.5.0.gem", {st_mode=S_IFREG|0644, st_size=15872, ...}) = 0
open("/var/lib/gems/1.9.1/cache/rack-protection-1.5.0.gem", O_RDONLY) = 6
ioctl(6, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7ffffa362e90) = -1 ENOTTY (Inappropriate ioctl for device)
read(6, "data.tar.gz\0\0\0\0\0\0\0\0\0", 20) = 20
close(6) = 0
open("/var/lib/gems/1.9.1/cache/rack-protection-1.5.0.gem", O_RDONLY) = 6
ioctl(6, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7ffffa362e30) = -1 ENOTTY (Inappropriate ioctl for device)
lseek(6, 0, SEEK_CUR) = 0
read(6, "data.tar.gz\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 8192) = 8192
lseek(6, -7680, SEEK_CUR) = 512
lseek(6, 0, SEEK_CUR) = 512
lseek(6, 12054, SEEK_CUR) = 12566
read(6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 234) = 234
read(6, "metadata.gz\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 8192) = 3072
lseek(6, -2560, SEEK_CUR) = 13312
lseek(6, 0, SEEK_CUR) = 13312
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
read(6, "\37\213\10\0R @Q\0\3\334W\333n\3436\20}\327W0OyhM;\t\212\26\2\272\260"..., 1137) = 1137
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
close(6) = 0
write(2, "ERROR: While executing gem ... "..., 85ERROR: While executing gem ... (ArgumentError)
invalid byte sequence in US-ASCII) = 85
write(2, "\n", 1
) = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
getrlimit(RLIMIT_STACK, {rlim_cur=8192*1024, rlim_max=RLIM_INFINITY}) = 0
futex(0x7f72f1d98a04, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x7f72f1d98a00, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
futex(0x7f72f1d989c0, FUTEX_WAKE_PRIVATE, 1) = 1
rt_sigaction(SIGINT, {SIG_IGN, [], SA_RESTORER|SA_SIGINFO, 0x7f72f179aff0}, {0x7f72f1a97780, [], SA_RESTORER|SA_SIGINFO, 0x7f72f179aff0}, 8) = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER|SA_SIGINFO, 0x7f72f179aff0}, {SIG_IGN, [], SA_RESTORER|SA_SIGINFO, 0x7f72f179aff0}, 8) = 0
close(5) = 0
close(3) = 0
close(4) = 0
exit_group(1) = ?
</code></pre>
<p>Alright, now we’re getting somewhere. Looking at where it prints the error message, we can track back up the output to see what the previous operation was:</p>
<pre><code> read(6, "\37\213\10\0R @Q\0\3\334W\333n\3436\20}\327W0OyhM;\t\212\26\2\272\260"..., 1137) = 1137
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
close(6) = 0
write(2, "ERROR: While executing gem ... "..., 85ERROR: While executing gem ... (ArgumentError)
invalid byte sequence in US-ASCII) = 85
write(2, "\n", 1
) = 1
</code></pre>
<p>So, there was a read from file descriptor 6, and then it closed up and printed the error. Ok, so what’s file descriptor 6?</p>
<pre><code> open("/var/lib/gems/1.9.1/cache/rack-protection-1.5.0.gem", O_RDONLY) = 6
</code></pre>
<p>So, the problem may in fact lay with the rack-protection gem! The progress, we are making it and it tastes delicious! Alright, so let’s fork and clone the rack-protection gem and try the same suggested fix to it’s Gemfile. 1 rebuilt gem later,</p>
<pre><code> root@dev:/home/jeff/Projects/rack-protection# gem1.9.1 install -l rack-protection
Successfully installed rack-protection-1.5.0
1 gem installed
Installing ri documentation for rack-protection-1.5.0...
Building YARD (yri) index for rack-protection-1.5.0...
Installing RDoc documentation for rack-protection-1.5.0...
root@dev:/home/jeff/Projects/rack-protection# gem1.9.1 install sinatra
Successfully installed sinatra-1.4.2
1 gem installed
Installing ri documentation for sinatra-1.4.2...
Building YARD (yri) index for sinatra-1.4.2...
[warn]: Could not find readme file: README.rdoc
Installing RDoc documentation for sinatra-1.4.2...
</code></pre>
<p>Winning! Alrighty then! Let’s push to Github and submit a Pull Request, then have cake! Mmm, cake.</p>
Xen on Debian Part 12013-01-28T00:00:00+00:00http://.github.com/Blog/2013/01/28/Xen-part-1<p><a href="http://en.wikipedia.org/wiki/Xen">Xen is a bare metal hypervisor</a>, and a really neat one at that. If you’re used to the VMWare world, it works a bit differently from vSphere in that when you install vSphere you don’t have access to <a href="http://wiki.xen.org/wiki/Dom0">dom0</a>, vSphere is dom0, but in Xen you have access to and <a href="http://wiki.xen.org/wiki/Dom0_Kernels_for_Xen">get to choose (within reason)</a> which operating system runs in dom0, though you’ll want to make that decision long before it comes time to install xen itself.</p>
<p>There are plenty of places out there already that talk about Xen and what it is, and how it compares to other hypervisors, so I won’t digress into that here. This page assumes you already kind of know what Xen is and know that you want to give it a go to see it in action.</p>
<h2 id="installation">Installation</h2>
<p>Installation is quite straight-forward;</p>
<ul>
<li>Choose and install dom0 Operating System – in this case Debian</li>
<li><code>apt-get install xen-linux-system</code></li>
<li>Edit Grub to boot from Xen</li>
<li>Reboot</li>
</ul>
<p>Well OK, there’s a couple tricks. I found that in order to get Xen to boot by default I had to reboot to see what the menu entry index was (it was the 5th down, so index 4), then I could edit Grub to boot Xen, then I rebootted into Xen. Booting in to Xen is the easy part, figuring out the networking shenanigans is something else entirely. In hindsight, it’s actually pretty straight forward once you know what you’re doing but figuring out what to do on a Debian system from the documentation on the Xen wiki is, to put it kindly, lacking. I understand from reading the documentation that the way that Xen handles networking on non-Debian systems is widely different from the way that it’s done on Debian. I’ve only dealt with the Debian way so I can’t speak to which is easier, but the Debian way is pretty easy if you ask me. The following instructions assume ‘eth0’ is the only ethernet port on the system, please adapt for your configuration.</p>
<ul>
<li><code>ifdown eth0</code></li>
<li>Edit /etc/network/interfaces, change it to reflect this;</li>
</ul>
<pre><code> iface eth0 inet manual
iface xenbr0 inet static
bridge_ports eth0
address 192.168.X.X
netmask 255.255.255.0
gateway 192.168.X.X
bridge_stp off
bridge_maxwait 0
bridge_fd 0
</code></pre>
<ul>
<li>Edit /etc/xen/xend-config.sxp – Do not uncomment any of the network scripts which look like this “(network-script network-bridge)” “(network-script ‘network-bridge bridge=br0’)” and “(network-script ‘network-bridge netdev=eth0’)”. Because we are running Debian and we setup the bridge manually by editing the <code>/etc/network/interfaces</code> file, we don’t need the network-scripts. This is one of the things that the documentation on the Xen wiki confused me, I was trying to get it to work with the network scripts which caused me all kinds of headaches. </li>
<li>Verify that this file contains an un-commented-out line<br />
(vif-script vif-bridge) </li>
<li>It would be a good idea for you to browse through the rest of this file, if only to give yourself an idea of what options are available to you. </li>
<li><code>ifup xenbr0</code> </li>
</ul>
<p>And that’s it for Installation! Really quite easy, comparatively. Now of course you’ll want to try and spin up a new VM, and who wouldn’t! So, on to the next section!</p>
<h2 id="hello-virtual-world">Hello Virtual World</h2>
<p><a href="http://wiki.debian.org/Xen">Full details are available on the Xen wiki</a> but for now, we’ll jump straight to setting up our first VM. So exciting!</p>
<p>First of all, we need to install the tool that creates the VMs.</p>
<p><code>apt-get install xen-tools</code></p>
<p>And after that completes we can make our first VM!</p>
<p><code>xen-create-image --hostname Tux --ip 192.168.0.5 --gateway 192.168.0.1 --netmask 255.255.255.0 --nameserver 192.168.0.1 --vcpus 1 --pygrub --dist squeeze --dir ~/</code></p>
<p>This command will take awhile to run. </p>
<p>This will create a new VM in your home directory in a sub-directory called ‘xen’. It will default to 128 Megabytes of RAM if you don’t provide that on the command line with the <code>--memory=</code> option, which by the way, takes a number such as ‘2Gb’. Please note that ‘2GB’ is not acceptable, nor is ‘2’, as I found out through my own testing. You can also set the size of the disk image using the <code>--size=</code> option, and I would strongly encourage you to read the man page for xen-create-image to give yourself an idea of what is possible when you create the image. It’s possible to specify the root password, it’s also possible to it to use a randomized password for root and display that to you after completing the xen-create-image command, set the VM to boot after creation, and a plethora of other cool options.</p>
<p>So, now you’ve got your first VM created, how do we start it? Well, one way is to specify the <code>--boot</code> option in the xen-create-image command, or you can start if after the fact using the command</p>
<p><code>xm create /etc/xen/Tux.cfg</code></p>
<p>Please note that the filename that you pass to the <code>xm create</code> command is $HOSTNAME.cfg so if you used a hostname other than Tux then you’ll need to use that hostname here as well. If there’s any confusion, check the contents of the <code>/etc/xen</code> directory for an idea of the available VMs and their hostnames. </p>
My boot problem2012-09-30T00:00:00+00:00http://.github.com/Blog/2012/09/30/My-boot-problem<p>I’ve had a problem with one of my servers for quite a while now. Luckily, it was one of those intermittent problems that only reared its head long enough to be a pain in the ass, but not quite a big enough pain as to make me spend more than an hours worth of time troubleshooting it. And being a hardware problem, it can often take a bit longer then that to troubleshoot.</p>
<p>I have a server with several hard drives plugged in, most via SATA but one or two via USB. I installed Debian and happily configured my system. Then, one day, I had a drive die on me. Never mind the ugly pain it was trying to identify which drive failed, that’s a story for another time, we’ll just skip to the part where I have figured out which drive has failed. After turning off the machine and unplugging the drive, I turned it back on again and expected a successful boot. I was watching the screen boot, I saw the regular BIOS output and memory tests, and then I saw the blinking cursor that [experience told me] indicated that it couldn’t find grub.</p>
<p>I was perplexed, I had just done a base install, how could it possibly have a boot problem now, I know that the root partition was not on the drive that had failed. The drive that failed was part of a RAID array and the root partition was not even on the RAID array. I hadn’t even done anything like reformat any drives so it seemed quite unlikely that I had accidentally blown away my root drive.</p>
<p>Confused, but not knowing where to begin troubleshooting, and needing a boot-able system rather quickly, I felt I had no choice but to just reinstall the operating system and restore the files on the RAID from backup. Had this been anything other then a personal side-project at home, I would have felt an obligation to determine the cause of the problem before just reinstalling the operating system because without knowing how it happened in the first place you cannot know for sure that it won’t happen again. I reinstalled the operating system, and tried some basic tests like plugging in a USB drive and rebooting the system and it seemed stable. Luckily, when I went to build a new array out of the old drives, I found that the system had already rebuilt the array based on the filesystem type on each of the drives. Before adding the drives to the RAID I used fdisk to set the “partition’s system ID” to “Linux raid autodetect”.</p>
<pre><code>fdisk /dev/sda
Command (m for help): t
Hex code (type L to list codes): fd
Command (m for help): q
</code></pre>
<p>This it seems allowed mdadm to rebuild the array at boot without the need of a configuration file (I had never set the configuration file for mdadm at all on any system).</p>
<p>Some time later, I bought a replacement drive for the RAID array to increase the stability. I use RAID6 and so the array can sustain a loss of up to two drives without any loss of the files on it. Lose 3 drives however, and your files vanish in a puff of bytes. At that point if memory serves I was running the array while being down 2 drives, so if I had another drive failure before I added a new drive, my files were gone, so I put together some funds and got a replacement. Well, after installing the replacement drive and trying to boot the system, I ran into the same problem of the system being unboot-able.</p>
<p>I wasn’t sure how to troubleshoot a problem like this, and personally I loathe hardware problems because of how inconsistent they can be and how hard they can be to track down with certainty, so for a long time I ignored the problem by A) having the good luck of not needing to replace any more dead drives, and B) by not rebooting the system very often if at all and making sure the same number of drives were plugged in as when I last booted.</p>
<p>A while later I moved to a new place with a geek room mate and so of course I had to make sure my computers worked and were in pristine condition. Some people might not understand the sublet competition that can take place when two geeks live under the same roof, it’s like a subtle little geeky arms race, and when one of those people is a Mac advocate and one is a hardcore FOSS advocate, that competition can shall we say intensify a bit. So maybe you now understand why I had to make sure that my systems were in expected working condition.</p>
<p>One night while having some long-time friends over to visit who also happened to be infected with the geek virus, got bored and so we decided to take a go at troubleshooting why this computer had a problem booting. We turned it off, rebooted it, turned it off again, unplugged a drive, rebooted it, tried unplugging another drive, and so on. Eventually we came to the conclusion that one of the ports on the SATA card had a problem with it because whenever a drive was plugged in to that port the system wouldn’t boot. </p>
<p>So, happy as can be that we solved the problem, I configured the system and got it ready for “production” here at the house. Then, I had another drive die in the RAID array, which isn’t unexpected because by now these drives are a couple years old at least as is the rest of the computer. So I turned the machine off and unplugged the drive, but when I rebooted I was again greeted with the blinking cursor of doooooom. </p>
<p>At this point I was getting exasperated by this decidedly irritating problem, and so resolved to go with a solution that I knew worked – PXE boot the system. Since the problem appeared to be that it couldn’t even find grub let alone the root partition, this felt like it should work. I rebooted the system into the BIOS and went rooting around for the configuration options to set the system to boot from the network, and while I was in the system I noted that the drive that was listed first among a list of the available drives that were plugged in was a Hitachi drive, and I only had one of those and it was plugged into the SATA card (as opposed to a slot on the motherboard itself). This clued me in to what could be the problem, when a drive was plugged in to the SATA card the system thought of it as coming before the drives that were plugged into the SATA slots on the motherboard. </p>
<p>So, having an idea what the problem was now, I had an idea for a solution. I would install grub to each of the drives attached to the system via SATA. So I did, and so far everything has been working perfectly. I even tested by going through another bout of unplugging and replugging a bunch of various drives and it booted every time. </p>
<p>TLDR – The problem seems to be that because I was using a SATA card, drives attached to the SATA card were considered to be before the drives plugged into the SATA ports on the motherboard, and so the system had installed grub to one of the drives attached to the SATA card. When that drive died, the master boot record on it went as well. By installing grub to each drive the system is booting consistently, even when I add a new drive or remove an old one. I just have to make sure I install grub to each new drive installed, that way it doesn’t matter what drive the system tries to boot from.</p>
How to commit with Rugged2012-09-26T00:00:00+00:00http://.github.com/Blog/2012/09/26/How-to-commit-with-rugged<p>So far in my brief use, the Rugged gem seems to be a delightfully fast way of using git in Ruby, I just have one gripe (and it’s a petty one): The interface takes getting used to and requires intimate knowledge of the inner workings of git.</p>
<p>Rugged is still in development, so this blog may be out of date by the time you read it, you should definitely check with the lates documentation for both Rugged and libgit2 (if there is a discrepency in the documentation of one project about how the other project works, go with the documentation that goes with the project). </p>
<p>1) Add the files to the index.<br />
2) Write the index.<br />
3) Create the commit.<br />
4) Save the commit. </p>
<p>Which can be done like this; </p>
<pre><code>pry$ require 'rugged'
pry$ repo = Rugged::Repository.new repository_path
pry$ index = repo.index
pry$ index.add 'second_fakefile'
pry$ tree= repo.lookup( repo.index.write_tree ) #At this point, the files are staged
pry$ author={ :email=>'jeff.welling@gmail.com', :time=>Time.now, :name=>'Jeff Welling' }
pry$ parents=[ repo.lookup( repo.head.target ).oid ]
</code></pre>
<p>It was at this point that I ran into trouble. <code>index.write_tree</code> would succeed, and would return the sha of the tree that was written in string form, and I could verify this by using <code>git status</code> to see that the file was indeed staged and ready to be committed. When I tried to commit though, I got an error; </p>
<pre><code>pry$ x=Rugged::Commit.create(
repo,
:author=>author,
:message=>"Hello world\n\n",
:committer=>author,
:parents=>parents,
:tree=>tree.oid,
:update_ref=>'HEAD' )
TypeError: wrong argument type nil (expected String)
</code></pre>
<p>I double-checked my usage against the documentation from the README on the Rugged Github page, but even after asking for help in the #libgit2 irc channel on Freenode and <a href="http://stackoverflow.com/questions/12649697/how-to-commit-with-ruby-bindings-for-libgit2/12651234">posting a question on Stackoverflow</a> I wasn’t getting anywhere. One of (well, the only) answer I got to the Stackoverflow asked what code I was running which lead me to wonder if it was a version discrepency. I checked the Rugged Rubygems page and though it said the main version was 0.16.0, the version I was running, there was a prerelease version available with version number 0.17.0.b6. I wasn’t aware that Rubygems did prereleases, but after learning about the –prerelease option to the <code>gem</code> command I did <code>gem install --prerelease rugged</code> and that installed the version 0.17.0.b6. After installing that prerelease gem I was able to do the commit like normal.</p>
<p>Note: The <code>:update_ref</code> option to the Commit.create command isn’t documented in the README on the Rugged Github page, but if it documented in the comments in the <code>ext/rugged_commit.c</code> file in the Github repository, and I’ve tested using it. The catch is that without that, the commit will be created and written to the ODB but no reference will be updated so it will appear to most people that Commit.create is broken because they can’t see it on any of their branches. </p>
<p>Note: To get the sha of an object, the method you’re looking for is <code>obj.oid</code>. </p>
<p>And so that is the story of how I learned to do commits in Rugged. I hope this has been useful or at least an educational read for you.</p>
<p>I went back after the fact and ran the tests that came with 0.16.0 and many of the tests relating to creating and writing commits failed, so it’s no wonder I was having trouble. Hopefully 0.17.0 has been published as non-prerelease by the time you come to using Rugged.</p>
<p>References:<br />
0) <a href="http://stackoverflow.com/questions/12649697/how-to-commit-with-ruby-bindings-for-libgit2/12651234">http://stackoverflow.com/questions/12649697/how-to-commit-with-ruby-bindings-for-libgit2/12651234</a><br />
1) <a href="http://librelist.com/browser//libgit2/2011/2/19/initing-a-repository-adding-files-to-the-index-and-committing/#d94ce8df18ff0202ce904180286a4a85">http://librelist.com/browser//libgit2/2011/2/19/initing-a-repository-adding-files-to-the-index-and-committing/#d94ce8df18ff0202ce904180286a4a85</a> <br />
2) <a href="https://github.com/libgit2/rugged/blob/development/ext/rugged/rugged_commit.c">https://github.com/libgit2/rugged/blob/development/ext/rugged/rugged_commit.c</a><br />
3) <a href="https://github.com/libgit2/rugged">https://github.com/libgit2/rugged</a><br />
4) <a href="http://rubydoc.info/gems/rugged/0.16.0/frames">http://rubydoc.info/gems/rugged/0.16.0/frames</a> </p>
Rugged gem on Ubuntu2012-09-21T00:00:00+00:00http://.github.com/Blog/2012/09/21/Rugged-gem-on-Ubuntu<p>I tried to install the Rugged gem today on my Ubuntu 12.04 system and I got this error,</p>
<pre><code>$ gem install -r rugged
Building native extensions. This could take a while...
ERROR: Error installing rugged:
ERROR: Failed to build gem native extension.
/usr/bin/ruby1.8 extconf.rb
-- tar zxvf libgit2-dist.tar.gz
-- make -f Makefile.embed
checking for main() in -lgit2_embed... yes
checking for git2.h... no
ERROR: Failed to build libgit2
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers. Check the mkmf.log file for more
details. You may need configuration options.
Provided configuration options:
--with-opt-dir
--without-opt-dir
--with-opt-include
--without-opt-include=${opt-dir}/include
--with-opt-lib
--without-opt-lib=${opt-dir}/lib
--with-make-prog
--without-make-prog
--srcdir=.
--curdir
--ruby=/usr/bin/ruby1.8
--with-git2_embedlib
--without-git2_embedlib
Gem files will remain installed in /var/lib/gems/1.8/gems/rugged-0.16.0 for inspection.
Results logged to /var/lib/gems/1.8/gems/rugged-0.16.0/ext/rugged/gem_make.out
</code></pre>
<p>It took some digging to find out what was going on, but if you check the bottom of the mkmf.log file you might notice a zlib error;</p>
<pre><code>/var/lib/gems/1.8/gems/rugged-0.16.0/ext/rugged/vendor/libgit2-dist/include/git2/zlib.h:10:18: fatal error: zlib.h: No such file or directory
</code></pre>
<p>Some brief googling will show that this means we need to install the <code>zlib1g-dev</code> package,</p>
<pre><code>$ sudo apt-get install zlib1g-dev
</code></pre>
<p>Now you should be able to install Rugged without problems.</p>
<pre><code>$ sudo apt-get install -r rugged
</code></pre>
<p>And happyness was had by all!</p>
Switching To The Rugged Gem2012-08-12T00:00:00+00:00http://.github.com/Blog/2012/08/12/Switching-to-rugged<p>It’s one of those really annoying problems that can’t be solved with a one-liner change. Not even a small code refactor would fix it. It’s a speed problem, the program is taking too long to load, far longer than it should take. It must be fixed!</p>
<p>After adding some debug output lines to the code, the speed problem seems to be tracked down to lib/ticgit-ng/base.rb file on line 40 in commit d45551213719d8f42ef43208bdb497c00a85b7f8. Now, this line doesn’t inherently require switching to the Rugged gem, it could be written to directly read the .git/re
fs/heads/ directory to retrieve a list of the branch names, bypassing the calls to the git gem and saving time, but A) that would be a dirty hack, B) I need to switch over to the Rugged gem anyway and doing so now may solve both problems at the same time.</p>
<p>So, I need to get familiar enough with Rugged to be able to switch to it. Rugged appears to be written very differently from the Git gem in that the Git gem tries to emulate the user interface to git but in an API, whereas the Rugged gem is a Ruby implementation of the Git API.</p>
<p>I’ll keep a micro-blog of how I managed.</p>
<p>9:29pm – <a href="http://libgit2.github.com/libgit2/ex/HEAD/general.html">This</a> page documents most if not all of the libgit2 methods, with accompanying code examples. Given that Rugged is supposed to be a Ruby interface to libgit2 this seems like a good place to start.</p>
<p>10:36pm – After trying to install the Rugged gem to play around a bit and running into trouble, I think the best thing to do will be to use the dirty hack for now (manually read .git/refs/heads/) to fix the speed problem. I do intend to eventually switch TicGit-ng over to the Rugged gem, but for a patch that switches to Rugged to be applied and pushed I need the Rugged installation to be seamless and at present, due to still being in heavy development, both Rugged and libgit2 are not seamless to install. I will resolve my installation problem with Rugged and continue playing with that separately and will try and get a head start on the patch now, but for the immediate solution for the speed problem I will have to go with the dirty hack.</p>
<p>3:08am – I’ve spent a while now trying to speed up the code and I’ve found a couple different areas that I was able to improve that should help things, I’m just running some tests to be able to compare the differences in speed.</p>
<p>And here it is, the results of the speed test (test.rb ran <code>ti list</code> 300 times);</p>
<pre><code>$ time ./test.rb; git checkout run_faster; time ./test.rb
real 6m36.835s
user 2m40.766s
sys 2m35.706s
Switched to branch 'run_faster'
real 4m17.112s
user 2m2.988s
sys 1m22.889s
</code></pre>
<p>That’s a fairly decent speedup, and it’s definitely noticeable when calling the command as well. All in all, mission accomplished for now.</p>
The Git Problem That Wasnt2011-11-19T00:00:00+00:00http://.github.com/Blog/2011/11/19/The-Git-Problem-That-Wasnt<p>Earlier today I ran into a strange problem that I, at the time, was attributing to using two different versions of git on two different machines. The problem that I was having was that when I tried to do a git pull via ssh from my development VM, I was getting this error:</p>
<pre><code>jeff@stan:~/Documents/Projects/tget$ git fetch cnd
jeff@cnd's password:
fatal: protocol error: bad line length character: GPG_
</code></pre>
<p>My first instinct was to take my problem before the great almighty (though recently diminishing in greatness…) Google, but the results I got weren’t very helpful and didn’t include the “GPG_” part of the string – which should have been my first hint.</p>
<p>It was at this point that I gave up on tackling this specific problem in the interest of progressing on the task at hand, so I put it on the back-burner in my mind.</p>
<p>An hour or so later while copying .bashrc and related files to my desktop, I finally made the connection: the problem was related to having recently installed Gnu-PG and gpg-agent on my development VM. I use it to sign the tags for the releases of my programs, but unbeknownst to me I had misconfigured it due to a lack of understanding of the <a href="http://hacktux.com/bash/bashrc/bash_profile">finer details</a> of the <code>.bashrc</code> and <code>.bash_profile</code> files. After fixing that mistake, I was successfully able to <code>git fetch cnd</code>.<br />
And cake was had by all!</p>
Documentary Review of The War On Kids2011-09-28T00:00:00+00:00http://.github.com/Blog/2011/09/28/First-Android-debug<p>I just ran across my first bug when developing my first Android app!</p>
<p>I’m following along with an EBook called Android Apps For Absolute Beginners, and I got to Chapter 7 when I ran across the first bug in my code. In all previous instances of potentially problematic code, the IDE had called me out on it, but in this instance the IDE was telling me that everything was fine. However, when I ran my app and clicked on an item in the menu, the app crashed.</p>
<p>I first tried attaching the debugger and going at it from that angle, but that proved fruitless after mucking around and not being able to find any helpful indications of what was going wrong. My next approach was to read the source code scouring for something, I didn’t even know what, just anything that stood out as wrong. Several days later, I threw a couple more hours at the problem and ended up using breakpoints to figure out exactly where in the code the crash was occurring.</p>
<p>The crash was occurring on this line:</p>
<pre><code> ImageView image = (ImageView) findViewById(R.id.ImageView01);
</code></pre>
<p>It turned out, the object I was referencing with <code>R.id.ImageView01</code> was a TextView, and was the wrong object. After changing the reference to point to the proper object, the app loaded and works as expected.</p>
<p>It just seems like since the IDE doesn’t warn of this problem, it’s worth noting it in case I come across it again in the future. Coming from a weakly typed Ruby background, these kinds of type related problems aren’t as familiar to me as they may be to someone coming from a strongly typed language.</p>
Diskless Upgrade Problem2011-08-29T00:00:00+00:00http://.github.com/Blog/2011/08/29/Diskless-Upgrade-Problem<p>After following <a href="https://help.ubuntu.com/community/DisklessUbuntuHowto" title="Diskless Ubuntu Howto">this guide</a> to get my diskless Ubuntu system up and running, I ran into a problem when I tried to upgrade.</p>
<pre><code>subprocess installed post-installation script returned error exit status 2
</code></pre>
<p>Basically, update-grub was failing because there was no disk. The problem was that this failure caused upgrades to the kernel and other system components to fail for no good reason (HD was intentionally removed).</p>
<p>I remember I had come across this problem and had solved it once before but couldn’t remember how off the top of my head, so my first tactic was Google. But after a good fifteen minutes of searching with various combinations ofvarious keywords I couldn’t find anything particularly useful aside from a page that suggested uninstalling grub altogether, so I decided to try another tactic. This time I went and found the script that was failing and commented out the command, in this case, <code>exec update-grub</code> in the file <code>/etc/kernel/postinst.d/zz-update-grub</code>.</p>
<p>It’s a small file, and the line that needed commenting out was only line 15.After commenting that line out, I was able to complete my upgrades.</p>
Better booting2011-07-31T00:00:00+00:00http://.github.com/Blog/2011/07/31/Better-booting<p>So I’ve run into this problem on my Debian 5.0 system, as many other people have, involving many storage disks and the nondeterministic assignment of <code>/dev/sd...</code> names at boot time. The problem is documented in many places all over the web, as are many documented solutions, so I won’t go into unnecessary detail describing the problem or every possible solution. What I intend to document here is the solution that I chose in a clear and concise way, I’ve found that many of the pages with solutions aren’t formatted as clearly as they could have been even if they were ultimately helpful in solving the problem.</p>
<p>To add a label to a partition[[3]][<a href="http://webcache.googleusercontent.com/search?q=cache:peBdLm0LTFQJ:www.debian-administration.org/articles/522&hl=en&strip=1" title="Google Cache of 'Mounting file-systems by label rather than device name'">4</a>], use</p>
<pre><code>root@mine:~# tune2fs -Lroot /dev/sda1
</code></pre>
<p>Though for some reason, the label does not become visible in my partition list when I run <code>cfdisk /dev/sda</code> as [<a href="http://www.debian-administration.org/articles/522" title="Mounting file-systems by label rather than device name">3</a>] says it’s supposed to. <a href="http://wiki.debian.org/Part-UUID" title="Part-UUID">One page</a> I found demonstrates that one way of checking that a label has indeed been added is to reboot and then do</p>
<pre><code>ls -l /dev/disk/by-label/
</code></pre>
<p>Which, on my system, shows</p>
<pre><code>root@mine:~# ls -l /dev/disk/by-label
total 0
drwxr-xr-x 2 root root 80 2011-07-31 02:23 .
drwxr-xr-x 6 root root 120 2011-07-31 02:23 ..
lrwxrwxrwx 1 root root 9 2011-07-31 02:23 media -> ../../md0
lrwxrwxrwx 1 root root 10 2011-07-31 02:23 root -> ../../sda1
</code></pre>
<p>After adding a label for root, it’s time to add one for swap as outlined <a href="http://wiki.debian.org/Part-UUID" title="UUIDs, Labels, and fstab">here</a>.</p>
<pre><code># swapoff /dev/sda2
# mkswap -L Swap /dev/sda2
Setting up swapspace version 1, size = 1998737 kB
LABEL=Swap, UUID=7cdfeb21-613b-4588-abb5-9d4049854e9a
# swapon /dev/sda2
</code></pre>
<p>Don’t forget to change <code>/dev/sda2</code> to whatever your swap is, and please <em>please</em> doublecheck your device names before executing, nobody wants you to wipe your / drive.</p>
<p>Then, remembering that these instructions worked on Grub version 0.97 (not Grub2), change your <code>/etc/fstab</code> file to resemble this</p>
<pre><code># <file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0
#/dev/sda1 / ext3 errors=remount-ro 0 1
LABEL=root / ext3 errors=remount-ro 0 1
LABEL=media /mnt2 ext3 errors=remount-ro 0 0
LABEL=swap none swap sw 0 0
/dev/scd0 /media/cdrom0 udf,iso9660 user,noauto 0 0
</code></pre>
<p>Then the last step is to edit <code>/boot/grub/menu.lst</code> to resemble this</p>
<pre><code>title Xen 3.0.3-1-amd64 / Debian GNU/Linux, kernel 2.6.18-4-xen-amd64
root (hd0,0)
kernel /boot/xen-3.0.3-1-amd64.gz
module /boot/vmlinuz-2.6.18-4-xen-amd64 root=LABEL=root ro acpi=off noapic console=tty0
module /boot/initrd.img-2.6.18-4-xen-amd64
savedefault
</code></pre>
<p>And thats it. Now, I haven’t yet figured out a way to reliably reproduce the bug that causes the nondeterministic device names to get shuffled so I’m unable to verify that this <em>actually</em> works, but since implementing this I haven’t had the bug happen to me. If that changes, I will update this blog post accordingly.</p>
<h3 id="references">References</h3>
Troubleshooting Dynamic DNS via DHCP2011-05-05T00:00:00+00:00http://.github.com/Blog/2011/05/05/Troubleshooting-Dynamic-DNS-via-DHCP<p><a href="http://www.debian-administration.org/article/343/Configuring_Dynamic_DNS__DHCP_on_Debian_Stable">This page</a> explains how to get a setup working with dynamic DNS and DHCP.</p>
<p>I’m having a problem where my network was system was configured properly at one point, and then when I made some changes to other parts of the system, dynamic DNS via DHCP functionality broke. Now, when a new client joins the network, all that happens is the regular DHCP address handout. From what I can tell from the lack of any messages other than DHCP addressing in /var/log/syslog,there is now no attempt from DHCP to update DNS.</p>
<p>I found that after changing the /etc/bind/rndc.key file from </p>
<pre><code>key "rndc-key" {
algorithm hmac-md5;
secret "xyz...abc==";
};
</code></pre>
<p>to this.</p>
<pre><code>key "rndc-key" {
algorithm hmac-md5;
secret xyz...abc==;
};
</code></pre>
<p>After restarting both DHCP and DNS services, starting up a VM that was <a href="http://jeffwelling.github.com/2010/01/02/Debian-dynamic-dns.html">properly configured</a> to send a hostname, and watching /var/log/syslog I saw messages indicating things were working properly again, and joy was had by all.</p>
<h3 id="references">References</h3>
<p><a href="http://www.debian-administration.org/article/343/Configuring_Dynamic_DNS__DHCP_on_Debian_Stable">http://www.debian-administration.org/article/343/Configuring_Dynamic_DNS__DHCP_on_Debian_Stable</a> </p>
<p><a href="http://brunogirin.blogspot.com/2007/11/dhcp-and-dynamic-dns-on-ubuntu-server.html">http://brunogirin.blogspot.com/2007/11/dhcp-and-dynamic-dns-on-ubuntu-server.html</a> </p>
<p><a href="http://jeffwelling.github.com/2010/01/02/Debian-dynamic-dns.html">http://jeffwelling.github.com/2010/01/02/Debian-dynamic-dns.html</a> </p>
Diskless Debian Squeeze2011-05-02T00:00:00+00:00http://.github.com/Blog/2011/05/02/Diskless-Debian-Squeeze<h2 id="netbooting-debian-squeeze">Netbooting Debian Squeeze</h2>
<p>This page is about netbooting <a href="http://www.debian.org/">Debian</a> <a href="http://www.debian.org/releases/squeeze/">squeeze</a>. That is, using <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Preboot_Execution_Environment">PXE</a> to boot a <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Diskless_node">diskless</a> system with <code>/</code> (root) on a fileserver mounted via <a href="https://secure.wikimedia.org/wikipedia/en/wiki/NFS">NFS</a>, a method known as NFSRoot. </p>
<p>The easiest way to do this IMO is to actually install Debian Squeeze to a machine, make the necessary modifications to turn it into a diskless client and then copy the filesystem from that machine to a directory in the NFS share. Note, this page assumes root privileges.</p>
<h3 id="first-things-first--install-debian-squeeze-to-a-machine-or-virtual-machine--of-your-choosing">First things first. Install Debian Squeeze to a machine (or virtual machine ) of your choosing.</h3>
<h3 id="prerequisites">Prerequisites</h3>
<p><strong>On the server</strong>, you will need these packages </p>
<pre><code> apt-get install dhcp3-server
apt-get install tftp-hpa
apt-get install syslinux
apt-get install nfs-kernel-server
</code></pre>
<p><strong>On the client</strong>, you will need these packages</p>
<pre><code> apt-get install initramfs-tools
</code></pre>
<h3 id="configure-dhcp-server">Configure DHCP server</h3>
<p><strong>NOTE:</strong>
Most networks already have a DHCP server configured, and having more than one of them on the network at a time can cause problems for other computers on the network. Make sure you disable any other DHCP servers if you are starting a new one, instead of changing the configuration for the existing server. </p>
<p>Now, configure the DHCP server. I prefer vim,</p>
<pre><code>vim /etc/dhcp3/dhcpd.conf
</code></pre>
<p>You need to add a <code>next-server</code> and <code>filename</code> options, and the resulting file should look something like this. </p>
<pre><code>default-lease-time 600;
max-lease-time 7200;
option domain-name "xephon";
option domain-name-servers 192.168.1.1, 192.0.0.1, 194.2.0.50;
option routers 192.168.1.1;
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.50 192.168.1.99;
next-server 192.168.1.1;
filename "/tftpboot/pxelinux.0";
}
</code></pre>
<p>The <code>next-server</code> option tells the client which IP to ask for the file named in <code>filename</code>.<br />
You can see the <strong>Set up DHCP</strong> section of the <a href="http://wiki.linuxquestions.org/wiki/Diskless_Workstation">this page</a> for an example of setting up a static client section.</p>
<h3 id="set-up-nfs">Set up NFS</h3>
<p>First, we will create the directory that will contain our nfs shares, and then a directory for the root of the client who we will name zim. </p>
<pre><code>mkdir /nfs
mkdir /nfs/zim
</code></pre>
<p>Don’t forget to export them,</p>
<p><code>vim /etc/exports</code> </p>
<p>and add this line</p>
<p><code>/nfs/zim 192.168.1.0/255.255.255.0(rw,async,no_root_squash,no_subtree_check)</code></p>
<p>This will allow anyone in the network of 192.168.1.0/24 to mount this share. If this is not what you want, you can restrict it to a single IP such as <code>192.168.1.101/32</code>, or simply <code>*</code> to allow anyone access. Then, reload the file with, </p>
<p><code>exportfs -rv</code> </p>
<h3 id="configure-the-client">Configure the client</h3>
<p>Let’s start with <code>/etc/fstab</code>. Edit it so that your current root and swap are commented out, and add the necessary lines, both of which are shown in this example. </p>
<pre><code>###/dev/hda1 / ext3 noatime,errors=remount-ro 0 1
###/dev/hda5 /mnt/hda5 ext3 noatime 0 2
###/dev/hda6 none swap sw 0 0
/dev/nfs / nfs defaults 0 0
none /tmp tmpfs defaults 0 0
none /var/run tmpfs defaults 0 0
none /var/lock tmpfs defaults 0 0
none /var/tmp tmpfs defaults 0 0
none /media tmpfs defaults 0 0
</code></pre>
<p>Next, we need to edit <code>/etc/initramfs-tools/initramfs.conf</code>. Edit it so the <code>BOOT</code> and <code>MODULES</code> lines are as shown </p>
<pre><code>BOOT=nfs
MODULES=netboot
</code></pre>
<p>Now, create a new initrd image.</p>
<pre><code>mkinitramfs -o initrd.img.netboot
mv initrd.img.netboot /boot/.
</code></pre>
<p>Now, don’t forget to edit the <code>/etc/network/interfaces</code> file. It needs to look like this. </p>
<pre><code># The primary network interface
#allow-hotplug eth0
iface eth0 inet manual
</code></pre>
<p>Then, mount the NFS share and begin copying over the filesystem to the server. </p>
<pre><code>mount -tnfs -onolock 192.168.1.4:/nfs/zim /mnt
cp -axv /. /mnt/.
cp -axv /dev/. /mnt/dev/.
</code></pre>
<p>And finally, back on the server, configure tftp. Remember that in Debian Squeeze, for the tftp-hpa package,
the tftp folder is in <code>/var/lib/tftpboot</code>. </p>
<pre><code>mkdir -p /var/lib/tftpboot/pxelinux.cfg
cp /usr/lib/syslinux/pxelinux.0 /var/lib/tftpboot/.
cp /nfs/zim/boot/vmlinuzTAB /var/lib/tftpboot/vmlinuz-zim
cp /nfs/zim/boot/initrd.img.netboot /var/lib/tftpboot/initrd.img.zim
</code></pre>
<p>Where you see TAB, press the TAB key and it will automagically fill in the kernel version, assuming you only have one version in there.<br />
Now, create a PXE config file</p>
<pre><code>vim /var/lib/tftpboot/pxelinux.cfg/default
</code></pre>
<p>and add contents such as these, replacing the IP address and kernel version with the one your using.</p>
<pre><code>LABEL linux
KERNEL vmlinuz-2.6.15-1-486
APPEND root=/dev/nfs initrd=initrd.img.netboot nfsroot=192.168.1.4:/mnt/hda5/yuki ip=dhcp rw
</code></pre>
<h3 id="enjoy">Enjoy</h3>
<p>Now, you should have a working thinclient.<br />
Don’t forget the changes you’ve made to the existing machine, in it’s current state it isn’t bootable, but that isn’t a problem because we assume you’ve installed it to a machine that you will be using as a thinclient. Simply revert the changes to put the machine back in a bootable state.</p>
<h3 id="references">References</h3>
<p><a href="http://wiki.linuxquestions.org/wiki/Diskless_Workstation">http://wiki.linuxquestions.org/wiki/Diskless_Workstation</a><br />
<a href="https://help.ubuntu.com/community/DisklessUbuntuHowto">https://help.ubuntu.com/community/DisklessUbuntuHowto</a> </p>
Documentary Review of The War On Kids2011-04-09T00:00:00+00:00http://.github.com/Blog/2011/04/09/Documentary-Review-of-The-War-On-Kids<p>The War On Kids is a documentary that explores the war on school children in the United States. There seems to be a fairly unique phenomenon taking place in the good old US of A, particularly since the Columbine incident, where elementary middle and high schools are being treated like prisons to the extent that students are prisoners. Metal detectors, police patrolling hallways, drug sniffing dogs inspecting lockers and backpacks, cameras everywhere… It’s really shocking to see just how bad it’s gotten. </p>
<p>Because it is being argued by school administrators that kids aren’t people, they are being treated as if they have no rights. They are interrogated by their principals who then turn the ‘testimony’ over to the police, without asking parents for permission to question them, and without reading the student their miranda rights. Many students are being charged with felony offences for trivial infractions, things like one student shoving another can become a felony assault charge and can cost that student his right to vote, turning this into a very concerning issue of eroding democratic values. </p>
<p>The film then discusses the extent to which pharmaceutical drugs are being prescribed to children. It notes that in England, these same drugs have been banned from being used on kids because there is no evidence that they work with kids. It mentions how these drugs are stunting the growth of many of the students who are taking them, and highlights a powerful correlation between anti-depressants and school shootings. </p>
<p>Apparently this phenomenon extends all the way to the Supreme Court. In 1988 the US Supreme Court ruled that schools may censor student news papers. The state now also dictates curriculum, even for history classes. </p>
<p>It also raises excellent arguments against the schedule where one subject follows another in quick succession. NY State Teacher Of The Year, John Taylor Gatto, argues that just as you become enveloped in a subject that you enjoy, the bell rings and you are forced to drop everything and go to your next class. </p>
<p>It also makes very good arguments against homework, pointing out a lack of studies supporting the idea that homework improves performance, and noting that the correlations that do exist are weak and in fact fall apart when examined using more sophisticated statistical techniques. In fact, there is <em>no</em> study <em>or</em> correlation that shows homework before high school improves anything. </p>
<p>The documentary consists largely of interviews with various individuals such as teachers, principals, leaders of organizations pushing for better educational environments, and most importantly students. It is broken up into different chapters or “lessons”, which smoothly lead from one into the next. In my opinion they could have made the same points just as well within a shorter period of time, but over all I consider it a documentary well worth watching if the topic interests you.</p>
VMWare to VirtualBox2010-09-05T00:00:00+00:00http://.github.com/Blog/2010/09/05/VMWare-to-Virtual-Box<p>I use virtualization for a lot of things, but most often I’m using it for developing software.</p>
<p>Until today I had been using VMWare and it did a fairly good job. That said, it does have its short comings, and on mac this includes having network difficulties in your virtual machines. This manifested in a number of ways, sometimes as a message when you started your VM saying something was disabled and that as a result networking would start disconnected, and sometimes if you used ping from the VM, you would see hundreds of duplicate responses and you wouldn’t be able to reach download speeds higher than around 60Kbps.</p>
<p>Well today I finally had enough and switched to something that worked, and it turns out one of alternatives for virtualization on Mac is Virtual Box, which is GPL’d so I didn’t have to look any further. So far it is faster than VMWare, is Free Software, doesn’t suffer from any the bugs that aggravated me in VMWare, and has an easy to use and intuitive interface.</p>
<p>If anyone is familiar with VMWare and the bug that I’m talking about, and knows how to fix it or if it is fixed by the time you read this, drop a line in the comments and let me know. Not that I’d jump at the chance to switch back but it would be nice to know what the fix for that problem is.</p>
Apt Pinning2010-09-05T00:00:00+00:00http://.github.com/Blog/2010/09/05/Apt-Pinning<p><a href="http://jaqque.sbih.org/kplug/apt-pinning.html">Apt Pinning</a> is a great way of installing packages from testing or unstable on your stable system. This is especially useful for me when I’m working on a project that requires a newer version of a library than is currently in Debian Stable, but has too many uses to enumerate here.</p>
<p>If you’ll notice though, the Apt Pinning page that comes up at the top of Google searches is somewhat lacking in detail in some aspects.</p>
<p>For example, the examples given for sources.list require changes to actually be useful to anyone today because things have changed. The original author provided two examples, the first one;</p>
<pre><code>#Stable
deb http://ftp.us.debian.org/debian stable main non-free contrib
deb http://non-us.debian.org/debian-non-US stable/non-US main contrib non-free
#Testing
deb http://ftp.us.debian.org/debian testing main non-free contrib
deb http://non-us.debian.org/debian-non-US testing/non-US main contrib non-free
#Unstable
deb http://ftp.us.debian.org/debian unstable main non-free contrib
deb http://non-us.debian.org/debian-non-US unstable/non-US main contrib non-free
</code></pre>
<p>and a <a href="http://jaqque.sbih.org/kplug/sources.list">second one</a>.</p>
<p>The first example is odd because first of all, it doesn’t include a line for security.debian.org, and second it has 2 lines for each version - to my understanding this is superfluous. You only <em>need</em> one line for each of Stable Testing and Unstable, but more can be added.</p>
<p>The problem with the second example is there are so many extraneous lines, and it includes lines that if included today wouldn’t work, and some lines that should be explained so that they can be improved on for international users. You’ll notice in the second example, as well as in my example below that the URLs like <code>ftp.ca.debian.org</code> and <code>ftp.us.debian.org</code> have a pattern, the 2 letter country code in between <code>ftp.</code> and <code>debian.org</code>. This can be changed to your local country code to use a local mirror instead of a mirror from Canada or the US.</p>
<p>This is my sources.list file. I use main contrib and non-free, but if you just wanted to use main or main and contrib you can change it accordingly.</p>
<pre><code>deb http://ftp.ca.debian.org/debian/ stable main contrib non-free
deb http://security.debian.org/ stable/updates main contrib non-free
deb-src http://ftp.ca.debian.org/debian/ stable main contrib non-free
deb-src http://security.debian.org/ stable/updates main contrib non-free
deb http://volatile.debian.org/debian-volatile stable/volatile main contrib non-free
deb-src http://volatile.debian.org/debian-volatile stable/volatile main contrib non-free
deb http://ftp.ca.debian.org/debian/ testing main contrib non-free
deb http://security.debian.org/ testing/updates main contrib non-free
deb-src http://ftp.ca.debian.org/debian/ testing main contrib non-free
deb-src http://security.debian.org/ testing/updates main contrib non-free
deb http://ftp.ca.debian.org/debian/ unstable main contrib non-free
deb-src http://ftp.ca.debian.org/debian/ unstable main contrib non-free
</code></pre>
<p>To setup apt-pinning on your Debian system copy the above and overwrite it onto your old <code>/etc/apt/sources.list</code> file. Then copy this;</p>
<pre><code>Package: *
Pin: release a=stable
Pin-Priority: 700
Package: *
Pin: release a=testing
Pin-Priority: 650
Package: *
Pin: release a=unstable
Pin-Priority: 600
</code></pre>
<p>And paste it into a file which may not exist yet called <code>/etc/apt/preferences</code>. This enables apt pinning and sets it so that stable is the branch that is used when no branch is specified when calling apt-get or aptitude.</p>
<p>Theres two ways two install packages;</p>
<pre><code>aptitude install <package>/unstable
</code></pre>
<p>Will install package from unstable trying to meet dependencies from stable, and this may not always work which is why I use;</p>
<pre><code>aptitude -t unstable install <package>
</code></pre>
<p>Which will install package and all dependencies from unstable.</p>
Debian Git Completion2010-09-03T00:00:00+00:00http://.github.com/Blog/2010/09/03/Debian-Git-Completion<p>I run <a href="http://www.debian.org/intro/about#what">Debian</a> stable, and right now thats 5.0 Lenny. I also use git, and would like it if git completion would work.</p>
<p>First, I added this to my <code>~/.profile</code> file;</p>
<pre><code>#For git tab completion and the special prompt thingy.
source /usr/local/git/contrib/completion/git-completion.bash
GIT_PS1_SHOWDIRTYSTATE=true
export PS1='[\u@CnD \w$(__git_ps1)]\$ '
</code></pre>
<p>This adds the name of the branch to your bash prompt. Thing is though, I was running into this error;</p>
<pre><code>bash: /usr/local/git/contrib/completion/git-completion.bash: No such file or directory
bash: __git_ps1: command not found
</code></pre>
<p>And I didn’t know why. Well, it turns out that the second line that I added to my <code>~/.profile</code> file was wrong, the file <code>/usr/local/git/contrib/completion/git-completion.bash</code> doesn’t exist in that place on Debian. This could be due to any number of reasons, including but not limited to that bit of code was maybe written for another system on which that file does exist. But the solution was easy, just update the <code>source</code> line to point to the new file. Some digging showed me where this was. So, my <code>~/.profile</code> file now looks like this;</p>
<pre><code>#For git tab completion and the special prompt thingy.
source /etc/bash_completion.d/git
GIT_PS1_SHOWDIRTYSTATE=true
export PS1='[\u@CnD \w$(__git_ps1)]\$ '
</code></pre>
<p>And now I have a working tab-completing prompt which shows my current branch.</p>
Adding Apt Sources Securely2010-04-30T00:00:00+00:00http://.github.com/Blog/2010/04/30/Adding-apt-sources-securely<hr />
<p>layout: post<br />
title: Adding Apt sources securely<br />
<del>-</del></p>
<p>Some programs from some groups want you to add their repositories to your apt’s sources.list file in order to install their program and easily facilitate updates. But, what’s to stop them from adding a malicious library or program named something like libc6, something included by default in most installers, and incrementing the version thus tricking your apt into installing it?</p>
<p>Well, consulting the debian <span class="caps">IRC</span> channel gave a helpful response. Use <a href="http://jaqque.sbih.org/kplug/apt-pinning.html">apt pinning</a> .<br />
By giving the untrusted repository a low priority, you can assure that your preferred apt sources are used before the untrusted one while still allowing you to install the app you want from their repo.<br />
Then just do <strong><code>apt-get -t something app_name</code></strong> to install the app, where something is whatever you used on the right side of the a= line in your apt preferences file.</p>Getting Debian to send your DHCP server it's hostname for Dynamic DNS2010-01-02T00:00:00+00:00http://.github.com/Blog/2010/01/02/Debian-dynamic-dns<p>So after installing doing a simple Debian 5.0 stable install the other day, I noticed when the machine booted, it’s hostname wasn’t being mapped in my dns server to hostname.local like my Mac and Ubuntu machine do.</p>
<p>Now to clarify, I’m <em>not</em> talking about dynamic dns in that your server updates your dns records over at EasyDNS or whoever you pay for your dns records, there are packages in the apt repos for that. What I’m talking about is when you configure your <span class="caps">DHCP</span> server to update your <span class="caps">DNS</span> server when hosts request an address.</p>
<p>I found the way to get the fresh Debian system to get its hostname registered in <span class="caps">DNS</span> was to tweak the default /etc/dhcp3/dhclient.conf, uncommenting the <br />
<strong><code>send host-name "";</code></strong><br />
line, and adding in your hostname in between the quotes.</p>
<p>After saving the file and restarting you should now see be able to do an nslookup on that machine’s hostname and have pleasant results.<br />
If anyone out there knows how to take it that one step further so that you don’t have to manually add in a hostname, but can instead get it to automatically detect the hostname and use it. In the dhclient.conf man page, there is mention of<br />
<strong><code>send fqdn.fqdn "";</code></strong><br />
<strong><code>send fqdn.encoded on;</code></strong><br />
<strong><code>send fqdn.server-update off;</code></strong><br />
but, that looks like it has to do with handling updating the dns server from that client instead of from the dhcp server itself, and which doesn’t seem to give any clue about how to get it to automatically detect and use the hostname.</p>
<p>Reference: http://brunogirin.blogspot.com/2007/11/dhcp-and-dynamic-dns-on-ubuntu-server.html</p>Social Networking Me2009-12-12T00:00:00+00:00http://.github.com/Blog/2009/12/12/Social-Networking-Me<hr />
<p>layout: post<br />
title: Socially Networked Me<br />
<del>-</del><br />
Alright, so I bit the bullet and did the Myspace and Facebook thing.<br />
You can find me on Myspace at http://www.myspace.com/512643590</p>
<p>You can find me on Facebook at http://www.facebook.com/profile.php?ref=name&id=100000562880858</p>
<p>There. Now you internet people can find me, see me, message me, touch yourselves at night while thinking about me, whatever you like. Play safe :)</p>
<p>The best way to get in touch with me is still via Email, Phone, and Text, in that order.</p>
<p>Jeff (dot) Welling (at) Gmail (dot) com</p>Ruby's splat operator2009-10-13T00:00:00+00:00http://.github.com/Blog/2009/10/13/rubys-splat-operator<p>So I’ve begun maintaining a fork of <a href="http://wiki.github.com/schacon/ticgit">Ticgit</a> and I was reading the source code the other day for fun and I came across an expression that I’d never seen before in ruby code. The section that I came across was</p>
<p><code>commit_log = `git log -1`.chomp</code><br />
<code>m, commit_id = * commit_log.match(/commit\W*([A-Fa-f0-9]+)/)</code></p>
<p>And the part specifically that confused me, was the <em>= *</em> part. I’d never seen an asterisk used right after an equals sign like that, it completely caught me off guard; Off to the #ruby <span class="caps">IRC</span> channel I was! It turns out, that <em>*</em> is called the <strong>splat operator</strong> in ruby. After a couple minutes asking around and some playtime in irb, I worked out what it did. In the situation it was used in in ticgit, the result of <strong>commit_log.match(/…/)</strong> was</p>
<p><code>["commit 159f9b343e84a1ac4eee716194b2c3ae3769cb7f", "159f9b343e84a1ac4eee716194b2c3ae3769cb7f"]</code></p>
<p>And what was happening was the splat operator was saying, put the fist element in the variable <strong>m</strong>, and put <em>any remaining variables</em> in an array in the variable <strong>commit_id</strong>. The idea behind the splat operator is that if there had been three variables before the <em>= *</em> part, and four parts of the string matched by .match(), then it would have put the first element in the first variable, the second element in the second variable, and both remaining elements as a 2 element array in the third variable.</p>
<p><a href="http://theplana.wordpress.com/2007/03/03/ruby-idioms-the-splat-operator/">Heres</a> <a href="http://stackoverflow.com/questions/776462/where-is-it-legal-to-use-ruby-splat-operator">a</a> <a href="http://chinnakarupan.wordpress.com/2008/03/18/splat-operator-in-ruby/">couple</a> <a href="http://neeraj.name/blog/articles/278-splat-in-ruby">other</a> links to help you understand the splat operator if you don’t already. Playing with it in irb helped me figure out enough of what it did to keep reading the code.</p>Blogging with Github Pages, Jekyll, and Disqus.2009-10-13T00:00:00+00:00http://.github.com/Blog/2009/10/13/github-pages,jekyll,disqus<p>Just the other day, I decided to setup blogging on my Github Pages page, <a href="jeffwelling.github.com">jeffwelling.github.com</a> . It took me longer than I feel was really necessary to get going and one of the most frustrating things, despite the copious amount of docs out there already, was that I really couldn’t find much information on how to <em>use</em> jekyll (aside from how to use it to host the blog from jekyll itself).<br />
Some really good material to <a href="http://drnicwilliams.com/2008/12/21/migrating-project-websites-to-github-pages-with-sake-tasks-new-websites-with-jekyll_generator/">help get you oriented</a></p>
<p>There are many pages and docs out there but few, if any of them were aimed at someone who wasn’t only new to jekyll but who was kind of new to blogging too; I wasn’t aware of any blogger terminology or best practices or even common practices. This blog post is intended to help people in the situation that I was in, you want to start blogging with Github Pages, Jekyll and Disqus for comments but you don’t know what to do or how to approach this, or you read the jekyll documentation and were still left feeling a bit mystified on how to use the thing.</p>
<p>First and foremost, you will need an account on Github.com which is where your blog will be hosted. Your jekyll blog doesn’t have to be located on Github, but it is the method chosen to be covered in this blog. For information on hosting it elsewhere, realize that the _site folder is all you need to copy to your web server, and just Google for jekyll documentation.<br />
The <a href="http://github.com/plans">Github Signup</a> page has several plans, but I just chose the free one for now. If your blog gains a lot of traffic you aught to consider upgrading to a pay account, even if for no other reason than to help support the people who are hosting your blog.</p>
<p>Now that we have a Github account, we can create a repository that will host our blog.<br />
One of the neat features about Github is that if you create a repository called <span class="caps">NAME</span>.github.com where <span class="caps">NAME</span> is your Github username, then it will be published as a Github Pages website at <a href="http://jeffwelling.github.com/">http://<span class="caps">NAME</span>.github.com/</a> . My Github username is jeffwelling, following that link will take you to my main blog page and you can see in the address bar what I mean.<br />
For more information on how you can work with Github Pages and create project specific blogs etc using the gh-pages branch in your project’s repo, see <a href="http://github.com/blog/272-github-pages">this</a> and more importantly, <a href="http://pages.github.com/">this</a> . I won’t be covering it in this blog post.</p>
<p>Now, we have our Github Pages page setup for our user at <span class="caps">NAME</span>.github.com . The next step is to install jekyll and start blogging.</p>
<p>There is a Ruby Gem called <strong>jekyll_generator</strong> which will help you create an empty blog directory.<br />
I wanted to create and store my blog in my ~/Documents/Blog directory, so I did</p>
<p><code>$ cd ~/Documents</code><br />
<code>$ /var/lib/gems/1.8/bin/jekyll_generator Blog --title "My Musings"</code></p>
<p>I had to call it by the full path for some reason, ‘Blog’ is the directory that it will create and put the new empty templates and stuff in, and “My Musings” is the title of my blog in case you hadn’t noticed you insensitive clod!</p>
<p>At this point, you may want to run</p>
<p><code>$ git init</code><br />
<code>$ git add .</code><br />
<code>$ git commit -a -m "Initial commit"</code><br />
Just so that you can return to this clean state if you accidentally muck something up.</p>
<p>This is where I started to get confused though. I had an empty blog directory, but how did I create a post?<br />
The answer is easy, you just start writing a textfile. If you want it to look pretty, check out <a href="http://textile.thresholdstate.com/">Textile</a> and <a href="http://daringfireball.net/projects/markdown/basics">Markup</a> . Also, remember, if your going to use Textile or Markdown make sure you save it with the appropriate extension, .textile and .markdown . Where you save the file, and what you name it is the critical part here in making it a blog post.</p>
<p>When your posting, your post <strong>must</strong> be saved into the ~/Documents/Blog/_posts directory, and it <strong>must</strong> have the name format of <strong>year-month-day-the-title-of-the-post.format</strong> . <br />
By saving the text file in the _posts directory, with that specific name format, you will have created your blog post.</p>
<p>If the name format still confuses you, take a look at <a href="http://github.com/jeffWelling/jeffwelling.github.com/tree/master/_posts/">my _posts</a> directory. Currently there are only a handful of posts, but they were all created on October 13th 2009, and so all three of them begin with “2009-10-13” and they all end with either “.textile” or “.markdown” to indicate which markup to use. The actual <em>title</em> of the post itself, is stored at the top of the file in a section that looks like this;</p>
<p>Now, to publish your blog post on Github, you <b>git add</b> your post from the _posts dir, and <b>git commit</b> it, and then <b>git push origin</b> to push it to Github. Its important to remember that in your git repository, your _site dir should be empty. If you are running jekyll locally on your computer then you may want to simply add _site to your .gitignore file. I made the mistake of running jekyll locally to preview the blog post, and then adding the files in _site to my git repository. The result was that when I pushed to Github, Github wasn’t updating my blog properly.</p>
<p>In this case, the title of the blog post is “Ruby’s splat operator”. To be honest I’m not sure if there is a direct relationship between what you put in the filename as your title and what you specify in that short blip at the beginning of the post as your title, if anyone knows what the connection is please comment on it.</p>
<p>If you haven’t already done so, you need to initialize your .git repository, and add everything under ~/Documents/Blog/ to it (as per our example above, if you use a different directory then obviously change it to accommodate).</p>
<p>Now, if you haven’t already done so, you need to setup your git repository so that you can push to Github to publish your blog on Github Pages by adding an ‘origin’ reference which points to Github. This is outlined on the Github page when you first create your repository. For example, for me and my blog, the commands were</p>
<p><strong>$ git remote add origin \ git@github.com:jeffWelling/jeffWelling.github.com.git</strong><br />
<strong>$ git push origin master</strong></p>
<p>But you will need to change the user name from jeffWelling to your user name if your going to copy/paste that command.</p>
<p>Now, you should have a blog hosted on Github Pages using jekyll. In order to get Disqus comments on your blog, keep reading. Otherwise you can stop here and be content with your comment-less blog.</p>
<p>Using Disqus comments on your blog is as easy as creating a Disqus account, pointing it at your blog, and adding a couple lines of source to your default layout files in the “~/Documents/Blog/_layouts” directory. I would copy and paste the lines for Disqus but the lines that they give you to copy are customized per your blog so it will just be easier to tell you to copy and paste what they give you instead. Note that unfortunately jekyll_generator tries to be friendly and generate the necessary Disqus code for you, but it doesn’t seem to do it correctly. I had to manually remove all of the Disqus code, and replace it with the code that I copied dierctly from the Disqus Install Instructions Universal Code section. If you used jekyll_generator you may have to do the same.</p>
<p>That should be it, now after running jekyll, commiting and pushing your changes to Github, you should have a wonderful new blog, optionally complete with comments as well!</p>
<p>How do you create a new post with jekyll? <br />
Create a new file in the _posts directory with the appropriate date and title information in the name as specified above. Fill it in with your blog text, and accompanying markup if you like. Then, run jekyll in the top level blog directory, in my case ~/Documents/Blog . This will update all the necessary files in _site . Now, you can do a <br />
<code>$ git add</code> <br />
to add any new files/posts, <br />
<code>$ git commit</code><br />
to commit your changes, and finally <br />
<code>$ git push origin</code> <br />
to push your changes to the server and publish them.</p>
<p>Now, if you’ve followed the instructions in this blog, you should have a working Github hosted, jekyll generated, Disqus enabled, git revisioned blog.</p>
<p>Questions? Suggestions? Did I miss something? Did it not work for you?<br />
Leave a comment and let me know!<br />
Cheers.</p>Welcome to 'My Musings'2009-10-13T00:00:00+00:00http://.github.com/Blog/2009/10/13/first-post<p>My Musings is going to be an awesome blog of awesomeness and doom.
BRAINWORMS!</p>
Cool2009-10-13T00:00:00+00:00http://.github.com/Blog/2009/10/13/cool
<hr />
<p>layout: post
title: Second post ever
—</p>
<p>Neat, my second blog post ever.
Loving the Disqus comments, even if they haven’t really been used yet.
Still kind of testing things out.</p>