Modifying Sproutcore Copyright Headers

I've been teaching myself Sproutcore over the past few days and ran into a minor annoyance. At the top of each generated template, there is a header with a copyright that reads "My Company, Inc.":
// Copyright: ©2011 My Company, Inc.
Fixing this requires modifying the templates for each generator (23 files, if you are wondering). These files are located in the gems/sproutcore-1.4.5/lib/gen folder. After navigating to that folder it is easy enough to change the company with grep, piping through cut and sed:
grep -r "My Company, Inc." . | cut -d: -f1 | xargs sed -i 's/My Company, Inc./Matthew Downey/'
Obviously, you want to replace your name with mine in the above example ;) Permalink

Packaging a Ruby C Extension as a Gem

Recently, I created my first ruby gem. It also happened to be a C extension. While there is a fairly good deal of information available on the web on how to package a basic gem, there isn't very much information about how to package a gem that includes a C extension. Bundler has a nice feature that creates a project skeleton for a gem, so it is easiest to start there:
bundle gem hello_world
That command should produce the following output:
      create  hello_world/Gemfile
      create  hello_world/Rakefile
      create  hello_world/.gitignore
      create  hello_world/hello_world.gemspec
      create  hello_world/lib/hello_world.rb
      create  hello_world/lib/hello_world/version.rb
Initializating git repo in /home/matt/hello_world
Now we need to create a directory where the extension will live:
mkdir -p hello_world/ext/hello_world
Inside this directory, we need to create our C extension, in our case, hello_world.c, and also an extconf.rb that ruby uses to create a makefile. The first file, hello_world/ext/hello_world/hello_world.c:
#include "ruby.h"
#include <stdio.h>

static VALUE method_hello_world(VALUE self)
{
        printf("Hello World!\n");
        return Qnil;
}

VALUE HelloWorldModule;
VALUE HelloWorldClass;

void Init_hello_world()
{
        HelloWorldModule = rb_define_module("HelloWorld");
        HelloWorldClass = rb_define_class_under(HelloWorldModule, "HelloWorld", rb_cObject);
        rb_define_method(HelloWorldClass, "hello_world", method_hello_world, 0);
}
This should be a fairly straightforward C extension, it's basically just a module with a class and a method that lives inside that class that prints "Hello World!". The next file, hello_world/ext/hello_world/extconf.rb:
require 'mkmf'

create_makefile("hello_world")
Next, we need to load the extension from the hello_world.rb file located in the lib directory. Basically, all we need to do is add a require statement: hello_world/lib/hello_world.rb:
require 'hello_world/hello_world'

module HelloWorld
  # Your code goes here...
end
The require statement seems a little redundant, but the .so file that is built actually gets stored in hello_world/lib/hello_world. The next step is to modify the Rakefile in the root directory. Note that in order to build a gem that includes a C extension, we are going to need the rake extensiontask gem, so if you don't have that, now would be a good time to install it. Modify your hello_world/Rakefile as follows:
require 'rubygems'
require 'rake'
require 'rake/extensiontask'
require 'bundler'

Rake::ExtensionTask.new("hello_world") do |extension|
  extension.lib_dir = "lib/hello_world"
end

task :chmod do
  File.chmod(0775, 'lib/hello_world/hello_world.so')
end
task :build => [:clean, :compile, :chmod]

Bundler::GemHelper.install_tasks
Next, we need to modify the hello_world.gemspec. Bundler creates a nice skeleton for us, the only thing we need to do is fill in the information for author, email, homepage, summary, and description, and add one line that points to the extconf.rb file, the s.extensions line. Modify the hello_world/hello_world.gemspec as follows, replacing your info with mine:
# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
require "hello_world/version"

Gem::Specification.new do |s|
  s.name        = "hello_world"
  s.version     = HelloWorld::VERSION
  s.platform    = Gem::Platform::RUBY
  s.authors     = ["Matthew Downey"]
  s.email       = ["mattddowney@gmail.NOSPAM.com"]
  s.homepage    = "http://www.writehack.com"
  s.summary     = %q{Hello World!}
  s.description = %q{Gem that prints Hello World!}

  s.rubyforge_project = "hello_world"

  s.files         = `git ls-files`.split("\n")
  s.test_files    = `git ls-files -- {test,spec,features}/*`.split("\n")
  s.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
  s.require_paths = ["lib"]
  s.extensions = ["ext/hello_world/extconf.rb"]
end
Next, build the extension, which should compile the .so file for us:
rake build
If you notice, the s.files line in the gemspec gets the files for the project from a git repository. It's probably a good idea to create a .gitignore file, but we won't cover that here. Just create an empty git repository, add everything, and make your initial commit:
git init
git add .
git commit -m 'initial commit'
Now, all thats left to do is install and test the gem!
rake install
If everything went well, we should no be able to fire up irb and test our gem:
ruby-1.9.2-p136 :001 > require 'rubygems'
 => true 
ruby-1.9.2-p136 :002 > require 'hello_world'
 => true 
ruby-1.9.2-p136 :003 > hello = HelloWorld::HelloWorld.new
 => #<HelloWorld::HelloWorld:0x000000027d7c40> 
ruby-1.9.2-p136 :004 > hello.hello_world
Hello World!
 => nil 
ruby-1.9.2-p136 :005 > 
Hopefully this helps someone that is trying to package a C extension as a gem. I wrestled with this for hours. Permalink

Scanning for Random DNS Servers

Nmap is such a useful tool. One neat feature is the ability to scan random IP addresses. Someone recently asked me if there was a way to discover random DNS servers.
sudo nmap -Pn -sS -p 53 -iR 1000 --open | grep -B 4 "53/tcp open"
That will invoke nmap to scan 1000 random IP addresses for an open TCP port 53. It pipes through grep to filter out the garbage (the -B option grabs 4 lines of output before the line that was grepped for). Permalink

Clearing Logs on Ubuntu System Shutdown

I have a virtual machine of Ubuntu 10.10 that I use for development purposes. The other day, I got this message:

The volume "var" has only 0 bytes disk space remaining.

Since the box is for development purposes, I have no real need to keep several days worth of logs. So I cooked up a script to delete the logs:

#!/bin/bash

# delete archived logfiles
for i in `find /var/log -type f \( -name \*.\[0-9\] -o -name \*.bz2 -o -name \*.gz -o -name \*.old \)`
do
  rm $i
done

# clear remaining logfiles
for i in `find /var/log -type f`
do
  cat /dev/null > $i
done

I saved it as clearlogs.sh, in my /etc/init.d folder. Then, I made it executable, and created symbolic links in rc0.d and rc6.d to make it run on shutdown and restart:

chmod +x /etc/init.d/clearlogs.sh
ln -s /etc/init.d/clearlogs.sh /etc/rc0.d/K10clearlogs.sh
ln -s /etc/init.d/clearlogs.sh /etc/rc6.d/K10clearlogs.sh

Now every time I load my system, I have clean logs. I would never do this on a production system or even my primary system, but for a dev box this works great.

Permalink

Virtual Linux Lab Series

This post serves as a marker for my virtual linux lab series. It is a series of tutorials that shows how to install and configure two CentOS 5.5 guests on a Windows 7 host as a virtual lab with VirtualBox. It is geared towards absolute beginners; I designed it to help my fellow linux system administration students at the Community College of Aurora.

Many of us don't have access to a proper lab, but thanks to virtualization technology, we can set one up on a single computer. Hopefully you will learn as much as I did reading these as I did creating them. :)

Check back often, as I will most likely be adding to this series in the future.

Permalink

VirtualBox Bridged Networking

If you've been using VirtualBox for a while, you've probably been scratching your head wondering how you can give two virtual machines the ability to communicate. The easiest way to do this is to configure bridged networking. In this tutorial, we are going to configure and test two CentOS 5.5 guests and a Windows 7 host. We also assume you already have guest additions installed.

Make sure your virtual machines are shutdown, then click "Settings." Select "Network" from the list on the left. This will bring up the guest machine's network settings. As you can see, VirtualBox allows a lot of network flexibility, with support for up four adapters and four different networking modes. Click the dropdown box labeled "Attached to" and change it to "Bridged Adapter" like so:

Now we must make sure that we select the proper network adapter that our host is using. On my laptop, I have two adapters, a physical adapter and a wireless one. Since I am connected to my network wirelessly, I need to select my wireless adapter. Click the dropdown box labeled "Name" and select the appropriate adapter that you are connecting with:

After clicking "OK," modify the other virtual machines on the network in the same manner. Start them both.

Bridged networking does a bit of voodoo to retrieve multiple IP addresses from your router with the same adapter card. If you login to your router after your guest OSes are connected, you should notice that there are multiple IP addresses for the same MAC address in your router.

Let's test that everything is working. First, verify that your host can connect to the internet. If that is working properly, and it should be (you are reading this), the next step is to verify internet connectivity on each guest machine. Open up a terminal, and ping google. If everything went okay, you should get something like this:

[matt@localhost ~]$ ping -c 3 google.com
PING google.com (209.85.225.106) 56(84) bytes of data.
64 bytes from iy-in-f106.1e100.net (209.85.225.106): icmp_seq=1 ttl=52 time=83.4 ms
64 bytes from iy-in-f106.1e100.net (209.85.225.106): icmp_seq=2 ttl=52 time=82.3 ms
64 bytes from iy-in-f106.1e100.net (209.85.225.106): icmp_seq=3 ttl=52 time=82.9 ms

--- google.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 82.397/82.942/83.443/0.428 ms

The important thing is at the bottom: all packets that were transmitted were recieved.

Next, let's verify connectivity between the the host and each guest, and in between our two guests. To do this, we need to get the ip addresses for each machine. First, lets get the Windows host's ip address. Open up a command promt by going to "Start" and typing "cmd" into the search box. Now run ipconfig:

C:\Users\Matt>ipconfig

The should produce a fairly decent amount of output. The line we are interested in is near the top, the first IPv4 Address:

IPv4 Address. . . . . . . . . . . : 192.168.1.60

Write this number down.

Now, let's move onto each guest. In linux, the command to get the computer's ip address is ifconfig, and it must be run as root. If you have sudoers configured, and have added /sbin to your path, open up a terminal and type the following:

sudo ifconfig

The line we are looking for is also near the top, listed under our network adapter, which should be eth0. Specifically, we are looking for the second line:

inet addr:192.168.1.114  Bcast:192.168.1.255  Mask:255.255.255.0

The first number in this line is our ip address. Write this down, and do this for each guest. My ip addresses are the following:

Machine IP address
Windows Host 192.168.1.60
CentOS Guest #1 192.168.1.114
CentOS Guest #2 192.168.1.111

To verify that I can connect to each guest from my host, I just ping them from my Windows command prompt. The Windows and linux ping commands are different, yet similar. For Windows, there's no need to specify a number of packets to send. Let's ping both guests now:

As you can see, I can reach both guests from my Windows host just fine.

Next, we'll ping the host and other guest from each guest:


(Click for full size image)

Again, no errors-- everything appears to be working fine. Now we can move onto more interesting things, like using ssh and configuring various servers.

Permalink

Cloning a VirtualBox Disk

One nice thing about using virtual machines is that you can make copies of them. This way if you install and configure a machine to your liking, you can just clone it and get another machine without having to go through the hassle of installation and configuration again. You can't just copy the .vdi file, however, because each virtual disk has a unique id. You can however, clone a disk relatively easily with the VBoxManage command.

In this tutorial we will be using a Windows 7 host, and cloning the hard disk for the CentOS 5.5 install that we performed in an earlier post. We will also assume that VBoxManage is in the Windows path. Open up a command prompt on the Windows host by clicking "Start" and typing "cmd" into the search box.

Once we open up a command prompt, we need to navigate to the directory where our hard disks are stored. These are in the your user's directory in the ".Virtualbox\HardDisks" subfolder. When you first open the command prompt, you should already be in your user's directory. Change to the hard disks folder by typing the following:

cd .VirtualBox\HardDisks

At this point, you can type "dir" to get a list of your .vdi files. If you followed along in the previous tutorial, you probably installed CentOS on a disk named "CentOS.vdi".

The syntax for the command to clone the disk is simple, "VBoxManage clonehd [infile.vdi] [outfile.vdi]". To clone disk named "CentOS.vdi" and create a duplicate "CentOS2.vdi" we type:

VBoxManage clonehd CentOS.vdi CentOS2.vdi

This process will take a few minutes.

To make the disk available to VirtualBox, we need to add it in the "Virtual Media Manager." From the main VirtualBox window, go to "File > Virtual Media Manager." Click "Add" and select the new disk we just cloned. Click "OK" and it should now be available in the dropdown box when you create a new machine.

Permalink

Adding Virtualbox to the Windows Path

VirtualBox comes with a useful command line utility called VBoxManage that allows you to do anything that can be done with the GUI tool and more. The only problem is it isn't added to the Windows path. Adding it to the path is relatively easy.

First, bring up the System properties. The easiest way to access this is through a keyboard shortcut, "Windows-Break." Alternatively, you can get there by clicking "Start," right-clicking on "Computer," and then selecting "Properties."

Now click "Advanced system settings" in the list on the left hand side.

Click the "Environment Variables..." button towards the bottom of this dialog.

This will open up an "Environment Variables" dialog. In the section labeled "System variables" scroll down to the one that says "Path" and click "Edit..."

Append the following to the end of the box labeled "Variable value" and click "OK." If you installed VirtualBox to another directory, use that instead:

;C:\Program Files\Oracle\VirtualBox

Click "OK" on the "Environment Variables" and "System Properties" dialogs. Open a Windows command prompt by clicking "Start" and then typing "cmd" into the search box. If everything went well, you should be able to type the following to get a list of your virtual machines:

VBoxManage list vms

Permalink

Virtualbox Shared Directories

Virtualbox allows you to share files between the guest and host operating systems. For the purposes of this tutorial, the host OS is Windows 7 and the guest OS is CentOS 5.5, although we could use any flavor of Linux. This tutorial also assumes that you have guest additions installed.

To start with, create a folder on the host operating system. You can exist anywhere you like. For ease of access, we'll just place ours on the desktop. To do this, right-click on the Windows desktop and select "New > Folder." Give this folder the name "share."

Next, run Virtualbox and start the guest operating system. From Virtualbox's menu, select "Devices > Shared Folders."

This will open up a dialog box with the title "Shared Folders."

On the top right of the dialog, click on the folder icon with the green plus sign. This will open up a file browser.

Browse to the share folder that was created on the host desktop and make sure to check the box labeled "Make Permanent." If this box is unchecked, it will create a transient share folder that will disappear the next time the guest OS is started. Click OK. The share should now appear in the list under the heading labeled "Machine Folders."

After clicking OK, the configuration is complete on the host operating system. Now we need to configure the guest OS. Login to the guest machine, and open up a terminal. We need to create a directory for the shared folder to reside. This can be anywhere on the filesystem, but for our purposes, we will be creating the directory /share. Since we will be creating this directory in the root folder, we need be root. Either change to the root user using su -, or prefix the command with sudo. We will be using sudo. Issue the following command:

sudo mkdir /share

Now we must mount the host's share folder to the /share directory we just created on the guest operating system. We could do this with the mount command, however that would require us to mount the folder every time we start the guest OS. Since we want this share to be permanent, it needs to be mounted on startup. To do this, we must add a line to the /etc/fstab file. We must be root to edit this file, so issue the following command:

sudo vi /etc/fstab

This will open up the /etc/fstab in vi. Scroll down to the bottom of the file, and push o to switch to edit mode and insert the following line at the end of the file:

share                /share        vboxsf        defaults        0  0

The first column is the name of the share we are mounting, given to us from the name column of the shared folders dialog. The second column is the mountpoint, the name of the directory we created on the guest that we will be mounting the folder to. The third column is the filesystem type, and the remaining columns are various options, of which we will use the default setting. After adding the line, save and edit the editor using :wq.

At this point, everything is setup, and all that is required is a reboot of the guest OS for the system to reload the /etc/fstab file. But before we do so, it would be nice to have a shortcut to our share on our linux desktop. To do this, we need to create a symbolic link, and store it in the ~/Desktop directory. Make sure you are logged in as your normal user, and type the following into the terminal:

ln -s  /share ~/Desktop/share

A link to the /share folder should now appear on your desktop.

Now, reboot the guest OS and test the shared folder by placing some files into it. If everything went well, the files should show up in the folder on both the host and guest operating systems.

Permalink

Installing Virtualbox Guest Additions

Virtualbox is nice because it comes with a set of drivers called guest additions, that allow you to be able to resize the guest window and provide seamless integration for the mouse and keyboard, without the need for using the host key. Installing guest additions also allows for more advanced networking modes, among other things. This tutorial assumes that your guest OS is CentOS or other Red Hat based, although the installation is similar for all distributions, you just have to substitute your distros package manager for yum.

To get started we need to install a few packages as root. Type the following into a terminal:

sudo yum install gcc kernel kernel-devel

Yum should ask you if you really want to install the packages, so tell it yes. After the packages have installed, reboot the virtual machine, and login to the desktop. Then, from the Virtualbox menu, select "Devices > Install Guest Additions."

This should automount the guest additions, which will show up as a CD on the desktop. Open another terminal, and switch to the root user:

su -

Enter your password and change to the directory where the guest additions reside:

cd /media/VBOXADDITIONS_3.2.8_64453

You might have a different version of guest additions, so substitute accordingly.

Next, depending on your guest machine's architecture, run either VBoxLinuxAdditions-x86.run or VBoxLinuxAdditions-amd64.run using sh.

sh VBoxLinuxAdditions-amd64.run

This will take a couple of minutes, just be patient. The system is recompiling the kernel with the new guest addition drivers. After it finishes, reboot. After your machine finishes booting, if everything went well you should be able to resize the window and the mouse will move seamlessly from guest to host without the need for using the host key.

Permalink
Older Posts  -  Home