Thursday, May 16, 2013

Do-it-yourself uptime command for Windows 7

How long has my computer been running? A fundamental question that Unix-y systems can answer with the uptime command.

For some odd reason, Windows 7 has no built-in uptime command. You can simulate this by displaying the date and time Windows 7 last rebooted as reported by the net statistics command. Put this in a file named uptime.bat somewhere on your path:

@echo off
for /f "tokens=1,2,*" %%i in ('net statistics workstations ^| find "since"') do @echo %COMPUTERNAME% up since %%k

Then open a command prompt and type in the freshly minted command:

C:\Users\philip>uptime
MYCOMPUTER up since 5/15/2013 5:21:27 PM

Saturday, May 11, 2013

Ruby, Ruby


You enter the j'Edit Five bistro from the steamy Paris evening. A sultry blonde, encased in a tight red dress, leans into the light over the toolbar at the far end of the room. She beckons to you with a heavy-lidded gaze, one eye obscured behind a curtain of flowing golden locks.

You step toward her, confident in that instant you're about to begin a beautiful friendship. You carry your plans and UML diagrams tucked inside the breast pocket of your jacket, a sheaf of ideas and ambition that only she can satisfy.

But as you draw near, you see the faint crow's feet around her eyes, the smudges on her dress, notice the style is seasons out of date. For the first time, you see the stringy, diminutive man in striped coveralls and a bill cap perched on the stool at her far side. A large red stone twinkles from the ring he twists around his pinkie.

You feel the heat from her body as you slide onto the bar stool beside her. "What is your name," you ask.

"Ruby," she breathes, "Ruby One Eight Seven." You inhale the cloying musk of her perfume, notice the slight trembling in her slim fingers as she lifts a tall flute of champagne to crimson lips. A trickle of moisture slides down the groove by her chin, spotting the front of her dress.

You try to mask your disappointment. You had so anticipated this meeting, a chance to make glorious music. But she is old, her skin creasing as she fits on a smile. She is deprecated, you think.

"And your little friend?" you ask, returning the railroader's nod.

"Him? He is only Rails Two Oh Three," her lip curls as she sneers. "He is just hoping to get lucky again tonight, but we are finished."

"You were so good together," you say, "I saw you performing together here years ago, up on the Web Two Oh stage."

"Yes," she says, "but I am tired. I live only to remember how I once danced here. The man who introduced us to j'Edit, he has gone away. And my younger sister, Ruby Two, has taken the limelight. Mais, she cannot dance here, my plugin is too old for her. So she prefers to dance for the Vim on Rue Rivoli, the Cafe Sublime, and le Palais de RubyMine." As she sweeps a cascade of gold away from her furrowed brow, the glitter of tears in her eyes reflects the flash of the red gems on her delicate earlobes.

You turn your gaze to the dim room. It is a good room, the windows edged with chrome, cups of Java steaming on the tables. Many coders and hackers huddle in booths by the glow of their screens, pecking out lines of Perl and Python, HTML and Scala. An aging XML roue nudges a tangled mass of angle brackets through the XSLT parser, chuckling as his XPaths return nodes.

"It could happen again," you say, "I could update the plugin to bring Ruby Two and her companion Rails Four back into the j'Edit. We could see them light up the windows again. She could parse, and colourize, and even debug in this room again. What do you say? Shall we find your little sister, and bring her back here?"

She tips her head back, stilling the quiver in her lip. "I will take you to the source, where we will set out the latest plugin for her, and repair the compiler errors and deprecations. We will update the mode to fit her. I may never dance here again, but my little Ruby Two, she will, and you will see to it. It will be her day, Ruby Two's day."

She demurs when you offer your hand. Instead, she lifts her satin clutch from the dark wood of the bar, and strides on her tall heels toward the door, a new vigor in her step. She pauses, and glances back at you. "Well, shall we?" she asks, not waiting for your answer as she exits, letting in the rush of traffic on the warm air.

Sunday, April 14, 2013

Cygwin bash: inspect the contents of .gitignore files

When git complained
The following path is ignored by one of your .gitignore files:puppet/modules/postgresql
it neglected to tell me which file. I used bash find to search all of the .gitignore files in my project:
$ find . -name .gitignore -print -exec cat '{}' \;
./.gitignore
.vagrant
./puppet/modules/apt/.gitignore
*.swp
pkg/
Gemfile.lock
./puppet/modules/mysql/.gitignore
*.swp
pkg/
./puppet/modules/stdlib/.gitignore
pkg/
.DS_Store
metadata.json
coverage/
Gemfile.lock
.bundle/
vendor/bundle/
The "-print" option produces the file path, then the "-exec" option calls the "cat" command to dump the contents of the file, passing the file path to cat in the '{}' argument.

Saturday, April 13, 2013

Vagrant: how to fix "VM inaccessible" error

I've hit an annoying error a couple of times when trying to "vagrant up" a box after waking Windows 7 laptop from hibernation:
Your VM has become "inaccessible." Unfortunately, this is a critical error with VirtualBox that Vagrant can not cleanly recover from. Please open VirtualBox and clear out your inaccessible virtual machines or find a way to fix them.
This message came from vagrant 1.1.5. Under the hood, vagrant calls the command-line VBoxManage utility provided by VirtualBox to manipulate the VMs. vagrant helpfully traps the error flag produced by VBoxManage and serves up that vague yet soothing error message. Although considerate, the message doesn't really help me diagnose the problem. Fortunately, when run in debug mode (set VAGRANT_LOG=debug then run vagrant status), vagrant will cough up all the nasty error messages from VBoxManage.

After some digging through the debug output, I discovered that even though the actual VM is intact (I can load and run it from the VirtualBox GUI app), somewhere in its guts, VirtualBox flagged this VM as "<inaccessible>". Vagrant, rightly believing what it's told, spits out the error message.

After looking at VBoxManage's help, I found that one its commands, list vms, unsurprisingly lists all of the VMs registered with VirtualBox:

$ /cygdrive/c/Program\ Files/Oracle/VirtualBox/VBoxManage.exe list vms
"precise64" {3613de48-6295-4a91-81fd-36e936beda4b}
"<inaccessible>" {2568227e-e73d-4056-978e-9ae8596493d9}
"<inaccessible>" {0fb42965-61cb-4388-89c4-de572d4ea7fc}
"<inaccessible>" {c65b1456-5771-4617-a6fb-869dffebeddd}
"<inaccessible>" {
9709d3d5-ce4d-42b9-ad5e-07726823fd02}

One of those VMs flagged as inaccessible is my lost VM! Time to fix VBoxManage's wagon, by unregistering the VM as inaccessible, then re-registering it with the correct name:
  1. Open the configuration file for your lost VM. Mine was saved to C:\cygwin\home\Philip\VirtualBox VMs\rails-vm-v2\rails-vm-v2.vbox
  2. Find and copy the value of the uuid attribute of the Machine node. Mine was 9709d3d5-ce4d-42b9-ad5e-07726823fd02.
  3. In a Windows command prompt (or Cygwin terminal), unregister the VM with the unregistervm command, using the [uuid] value from step 2:
    $ C:\Program Files\Oracle\VirtualBox\VBoxManage.exe unregistervm [uuid]
  4. Now register the VM using the registervm command, with the path to the VM configuration file:
    $ C:\Program Files\Oracle\VirtualBox\VBoxManage.exe registervm C:\cygwin\home\Philip\Virtual VMs\rails-vm-v2\rails-vm-v2.vbox
Now you should be able to start the VM as expected.


Sunday, March 17, 2013

UltiSnips requires multibyte support enabled in Vim

UltiSnips, a Vim plugin, is "an implementation of TextMates Snippets for the Vim Text Editor," according to its author. I had some trouble getting it running in Cygwin, especially with an error on a Vim variable &encoding thrown by the plugin's Python code, so I hope this post will help others avoid my problems.

Make sure that
  1. Python 2.6.x or better is installed for Cygwin,
  2. vim is compiled with the +python or +python3 configuration flag (as appropriate), and
  3. vim is compiled with the +multi_byte config flag.

You can check vim's configuration flags by running this command in a Cygwin shell:
$ vim --version | grep -E '(python|multi)'
You should see something like
+mouse_xterm +multi_byte +multi_lang -mzscheme +netbeans_intg -osfiletype
+path_extra -perl +persistent_undo +postscript +printer -profile +python
-python3 +quickfix +reltime +rightleft +ruby +scrollbind +signs +smartindent
Linking: gcc   -L.   -L/usr/local/lib -o vim.exe             -lm -lncurses            -L/usr/lib/python2.7/config -lpython2.7 -lruby191 -lrt

The + signs on the +python and +multi_byte flags indicates Vim was compiled with Python and multibyte support.

The UltiSnips Vim plugin wraps a Python application to do the heavy lifting. It will fail if Python is not available.

In addition, if vim is not configured for multibyte code, then the Python code will fail on an empty Vim variable &encoding. See line 18 in this example:



Happy vimming!

Saturday, March 16, 2013

Wow, that was f***ing fast!

Today I noticed a small error in a graphic included in section 5.2 of the Edge RailsGuide Getting Started with Rails. I raised an issue on the Rails Github project, figuring, OK, I've made my little contribution to the March of Open Source Goodness.

I was pleasantly surprised when Rails maintainer Steve Klabnik responded moments later that I had indeed caught a bug, as he'd done a couple of days before on another issue I'd raised (does this guy never leave his keyboard?). In the earlier case, the error was on my part, a semantic mismatch between using Rails 3.2.12 with the edge docs intended for the new Rails 4.0.0.

This time, after I read Steve's speedy response, I gave the RailsGuide page a reload, thinking, "OK, it' probably be a couple of days before that change gets committed."

I was astonished to see that not only had Steve committed a fix for the error, he'd used my screen grab to fix it. Major grin :)

Coming from a waterfall-ish project world where changes can take weeks and months to find their way to end users, I'd call this delight "moving at the speed of Rails".

Saturday, February 2, 2013

Preparing for Ruby on Rails job interviews

There are lots of excellent books and websites that provide general help with preparing for coding interviews, but few discuss the expectations of Ruby on Rails employers.

Here are a few links to fill in that gap:
Many of the ideas for Ruby job interviews could of course be extrapolated to any software development interview. Happy hunting!

Saturday, January 19, 2013

apropos and whatis for Cygwin

apropos and whatis are Unix-y commands that display a short description of other commands available on your system.

apropos is handy when you're looking for a particular function, say reading the contents of compressed files. It tends to be over-zealous with keywords, so for example, typing apropos compare compressed files returns 184 one line descriptions on my system. Typing just apropos compressed returns a more manageable 22 descriptions:

$ apropos compressed
bzcmp []             (1)  - compare bzip2 compressed files
bzdiff []            (1)  - compare bzip2 compressed files
...
zmore []             (1)  - file perusal filter for crt viewing of compressed text

whatis comes in when you know the name of an unfamiliar command, but you want a simple description of it's purpose:

$ whatis zmore
zmore []             (1)  - file perusal filter for crt viewing of compressed text

To use apropos (or man -k or whatis) in Cygwin, you must first create the whatis database by running the /usr/sbin/makewhatis command, probably with admin permissions to write the database.

Note (15 Jan 2014): apropos and whatis will not work from a Windows command prompt unless you've put the Cygwin bin directory ahead of the Windows and Windows\System32 directories in the PATH. Otherwise, apropos and whatis, which are shell scripts, will try to use the Windows 'find'command instead of the Cygwin 'find' command