A collection of computer systems and programming tips that you may find useful.
 
Brought to you by Craic Computing LLC, a bioinformatics consulting company.

Thursday, June 14, 2012

logit - selective logging of commands from a Bash shell

I spend a lot of time running custom scripts on datasets in a unix bash shell - typically I'm running various tools on DNA and protein sequence datasets. I need to try different tools, edit files and change parameters.

I wanted a way to capture those commands that worked and ignore all the others that simply listed directories, ran the editor, etc. Cutting and pasting from the shell history was really inefficient and the output of script was too voluminous.

To solve this I have written logit - a tool that lets you selective log commands and comments to a file while you work in a shell.

logit consists of a Ruby script and an associated bash shell script. When you run 'logit start' it creates a custom bash sub shell that you do your work in.

You can log comments to the log file with:
$ logit 'here is a comment'
And you log the last command you ran with just:
$ logit
There are other options to help you log commands further back in your history.

The resulting log file contains only those commands and comments that you chose to log. As such it serves as a concise record of a work session and may form the basis for an executable script in itself.

The regular Bash history mechanism is does not allow you to record lines from your history in a files. I'm not clear why but the cleanest solution I could come up with was the pairing of a Ruby and a Bash script. In practice you only ever deal with the Ruby script.

The code is distributed freely under the MIT license and can be found on Github at https://github.com/craic/logit


Tuesday, June 12, 2012

CSS and Rails - Migrating from Less to Sass

In my Rails projects over the past couple of years I have been using Less to make my CSS files easier to work with. Less is a CSS pre-processor that lets you use variables for color, etc.

Less is pretty similar to Sass and I didn't see any real reason to move away from it. But then Rails 3.1 made the decision to uses Sass and CoffeeScript as CSS and JavaScript preprocessors. So now I want to migrate my Less files over to Scss (the v2 format of Sass) so I can go with the flow in current Rails versions.

Sass comes with a conversion tool called sass-convert that you can find in the bin directory of the gem.
You can find where that is located with 'gem which sass'. But this gave me this error:
NameError: undefined method `build' for module `Less::StyleSheet::Mixin4'
From the sass github site it seems like sass -convert has not kept up with changes in Less and there seems little motivation to fix the problem.

Never mind - the Less and Scss syntaxes are pretty similar and my files do not include anything too complex, so manually converting them in an editor is quite feasible. In fact the main difference is that Less prefixes variables with @ and Sass uses $. The important exception here is that @import should not be changed as it is exactly the same in Sass.

Less has an equivalent to Sass Mixins. You create a custom class and then insert that into other CSS blocks. Here is an example followed by the Sass equivalent.
.my-mixin {
  color: red;
}
.my-class {
  width: 200px;
  .my-mixin;
}

In Sass you would write:
@mixin my-mixin {
  color: red;
}
.my-class {
  width: 200px;
  @include my-mixin;
}
Making this conversion is easy enough to do with find and replace in your editor.

The easiest way to validate the modified files is to run sass on them and check the css.
$ sass my.scss my.css

You can try validating the CSS using a service like http://jigsaw.w3.org/css-validator/validator


Thursday, June 7, 2012

Setting a Title for a Tab in iTerm2 on Mac OS X

 iTerm2 (http://www.iterm2.com) by George Nachman is an excellent terminal emulator for Mac OS X that is highly configurable. I it prefer over the system Terminal application.

I tend to have a number of terminal sessions open at the same time and for a while I have wanted a way to give each Tab in the window an informative name. You can do that through the iTerm2 preferences but I wanted a way to set it directly from the shell command line.

iTerm2 can be scripted via AppleScript and so I wrote a simple script to do the job. It uses a system application called osascript which will execute a AppleScript script from the Unix command line.

The code is freely available at https://github.com/craic/iterm_title - see the README for more details.

The code should be a useful starting point if you want to write something in AppleScript that you can call from UNIX.

Wednesday, May 30, 2012

rbenv - quick start

rbenv is a way to handle multiple versions of Ruby on a single machine and is an alternative to rvm.

I have been using rvm for some time and it works fine, but rbenv seems to have a slight edge in terms of simplicity and, perhaps, transparency in the way it handles version specific gems.

I installed it on a new machine with Mac OS X Lion using homebrew
$ brew update
$ brew install rbenv
$ brew install ruby-build
The only wrinkle was that it requires a regular installation of the gcc compiler, whereas Xcode installs llvn-gcc. You can find the good version at https://github.com/kennethreitz/osx-gcc-installer

You can see which versions of ruby are available using
$ rbenv versions
You can install them like this
$ rbenv install 1.9.3-p0
$ rbenv install 1.8.7-p302
$ rbenv install jruby-1.6.7
Not surprisingly, Jruby required that Java be installed but it was smart enough to trigger the download automatically.

You need to add two lines to your .bashrc, .bash_profile or whatever config file is appropriate for your preferred shell. Then create a new shell to pick up the definitions.

export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
The documentation is pretty straightforward in terms of setting different versions of Ruby in different projects.


Things get a bit confusing when it comes time to set up gems. rvm places copies of each gem in directories that are linked to each ruby version. By and large, rbenv doesn't mess with them.

With rbenv you install specific gems into a single system wide directory, as you would with a single Ruby version. For a given project you specify the required gems in a Gemfile in the project directory and you run

$ bundle exec

to make sure that you have correct versions of all the gems for that given project.
If you have installed a specific gem but find that it does not work or does not appear to exist then run this to, hopefully, fix the issue.


$ rbenv rehash



Tuesday, February 21, 2012

Running Ruby executable in a world-writable directory

Just now I needed to run a Ruby executable that was located in a world-writable directory.

Normally this is something that you never want to do - anyone could put an executable into your directory  and/or replace your script with their own. BUT sometimes you just need to do this - in my case I am in a secure environment, working with collaborators but we have not been able to get IT to set us up as a 'group' as yet.

The problem is that Ruby will issue a warning about "Insecure world writable directory" every time you run your script.

The real solution is to get past the need for those permissions. But in the short term I just want to get rid of the warnings.

There are two options:

You can pass the -W0 (that's a zero) flag to ruby
$ ruby -W0

But I use this 'hash bang' line at the start of all my scripts:
#!/usr/bin/env ruby
and I can't figure out how to pass the flag correctly in this case

The alternative is to add this line right after the hash bang line
$VERBOSE = nil

That does work. It clearly silences any other warnings that I might want to see but at least it gets me past my current issue.


Wednesday, February 15, 2012

Compiling Ruby 1.9.3 from source

I had to install Ruby 1.9.3 from source today.

Ruby comes with a load of documentation but I never use it. It's just easier to look it up on the web. But creating and installing that documentation takes a huge amount of time.

To disable it pass this option to 'configure'
$ ./configure --disable-install-doc

The other issue I had to deal with was that libyaml was installed in a non-standard location. With some libraries you can pass a specific option to 'configure' but not here... Instead you have to add the include and lib directories to Environment variables, like this:
$ export CPPFLAGS="-I/my/location/include"
$ export LDFLAGS="-L/my/location/lib"

'configure' will pick those up without any additional arguments.



Friday, January 27, 2012

Getting absolute paths with the Unix ls command

The standard Unix command ls lists filenames and directories in the specified directory. The default behaviour is to list just the filenames as including the full pathname would clutter the screen.

But sometimes you want the absolute paths. I need this all the time if I want to create a file containing a list fo filenames. The obvious command to get all the YAML files, for example, is:
$ ls -1 *yml
A.yml
B.yml

In order to get the full pathnames you need to use this:
$ ls -1 -d $PWD/*yml
/home/jones/A.yml
/home/jones/B.yml







Archive of Tips