Tag Archives: bash

Print the active Pow config in a readable format

[Pow](http://pow.cx/) is great. I don’t know why it’s taken me so long to make the switch from `rails s`. Pow is short on management utilities though; probably for good reason. Ideally, you never have to touch your Pow instance. It ‘just works’. I like to dig around under the hood though, so I put together this quick Python script that outputs the running Pow config in a format I can read.

#!/usr/bin/env python

# filename: powconfig

#############################################################################
# Print POW config with nice formatting #####################################
#
# Works as is with Python 2.6. For Python 2.7, ‘import simplejson as json’
# instead. Save this file to a location in your PATH and make sure it is
# executable. Then you can call ‘powconfig’ from anywhere and see the active
# POW configuration.
#############################################################################

import sys
import json as json
import httplib as http

conn = http.HTTPConnection(“localhost”)
conn.request(“GET”, “/config.json”, ”, {“Host”:”pow”})
resp = conn.getresponse()
data = resp.read()
print json.dumps(json.loads(data), indent=4)
sys.exit(0)

Save this script somewhere in your path and you can run `powconfig` from anywhere to see your running config, which looks like this:

bradland@macbookpro:~$ powconfig
{
“bin”: “/Users/bradland/Library/Application Support/Pow/Versions/0.3.2/bin/pow”,
“rvmPath”: “/Users/bradland/.rvm/scripts/rvm”,
“workers”: 2,
“dnsPort”: 20560,
“httpPort”: 20559,
“logRoot”: “/Users/bradland/Library/Logs/Pow”,
“timeout”: 900,
“domains”: [
“dev”
],
“dstPort”: 80,
“hostRoot”: “/Users/bradland/Library/Application Support/Pow/Hosts”,
“extDomains”: []
}

If you don’t care about formatting, you can simply add this snippet as a bash alias.

alias powconfig=’curl -H host:pow localhost/config.json’

Bash one-liner: Copy current working directory to clipboard in OS X

I frequently find myself in need of copying the path to my current working directory. Under OS X, you can pipe the output of any command to the clipboard using the pbcopy and pbpaste (see `man pbcopy`). Easy enough with `pwd | pbcopy`, but you end up with a newline. No problem, `tr` to the rescue.

pwd | tr -d ‘\n’ | pbcopy
^[1] ^[2] ^[3] ^[4]

1. `pwd` prints the working directory; pwd outputs a newline, which isn’t very handy if you need to paste this elsewhere, and especially unhelpful in a shell
2. `tr` is short for translate characters (think find/replace); normally it takes two arguments, but passing the `-d` flag deletes the string passed as an argument from the stdin
3. `\n` is the escape sequence for newlines; the character we want to get rid of
4. `pbcopy` is the OS X bash clipboard tool; see also: xclip or xsel for X-Windows environments

Use `man ` for more details about any of the above.

I’ve added the following as a bash alias so I can call this one quickly:

alias cpwd=”pwd | tr -d ‘\n’ | pbcopy”

Easy!

Simple wrapper for Ruby scripts running in an RVM environment

Ruby is a fantastic programming language, but I’ve not been all that happy with the community’s viewpoint of the execution environment. Ruby is fast moving, so you often encounter scripts or applications that require specific versions of Ruby. This problem isn’t unique to Ruby, but the solutions the Ruby community offers are.

Typically, versioned interpreters are installed using a convention that works something like this. If Ruby 1.9 and Ruby 1.8 were installed concurrently, the interpreters would be installed using /usr/bin/ruby19 and /usr/bin/ruby18. Scripts that require Ruby would have their shebang altered appropriately. You’d also typically symlink /usr/bin/ruby to your preferred (default) Ruby install.

Ruby eschews this convention. Ruby interpreters that come with many Linux packages use this convention, but most Rubyists will advise you to avoid OS packages because of other issues. As a system administrator, the entire scenario borders on horrifying. I get why Rubyists feel the way they do, but to people on the “other side”, it’s terrifying. Hearing “just install from source” keeps sysadmins up at night.

Enter RVM. Ruby enVironment Manager is a tool for installing and managing Ruby interpreters and RubyGems (Ruby’scripts library package manager). At it’s core, RVM is a collection of bash scripts, written by author Wayne Seguin. It’s an excellent tool, and while it gets some public criticism over methodologies like overriding common shell commands like cd, I’m generally happy with it. I’m one of a growing group of sysadmins who cross over in to the programming side of things, so the power and flexibility of having multiple Ruby interpreters and multiple RubyGems gemsets is has a lot of value to me.

RVM works by altering the execution environment. I won’t go in to details about how to use RVM, but you should be able to glean enough from this simple statement to get some idea of what’s going on:

$ rvm use ruby-1.9.2-p290@sprinkle

This tells RVM to “use” (load) the environment for Ruby version 1.9.2, patch level 290, and use the “sprinkle” gemset. A gemset is just a collection of gems that you give a name. This appears to work like magic, but it’s really quite simple. RVM changes a set of environment variables that are relevant to the execution of Ruby and RubyGems. Basically, a bunch of load and execution paths. That’s all.

So where’s this all headed? The beauty of RVM is that it encapsulates Ruby execution environments. The primary drawback of RVM is that it encapsulates Ruby execution environments. How’s that? Take the ruby executable path for example:

/Users/myser/.rvm/rubies/ruby-1.9.2-p290/bin/ruby

Not exactly as friendly as /usr/local/bin/ruby. Fortunately, that’s a solved problem. We have /usr/bin/env to work around that problem. The catch is, env works by searching the current environment. As we know, RVM dynamically loads an environment that works for each Ruby. What happens if RVM is never executed, and why would that be the case?

One example is cron. When you run a cron task, a very minimal environment is loaded. This means that RVM isn’t loaded. The standard solution to this is to source the rvm script prior to execution, but this means including the source line in every cron task, which A) requires that you remember it, and B) adds a lot of visual clutter to the crontab. When you’re reviewing a list of cron tasks looking for something specific, all these source lines make a real mess.

Additionally, if you write shell scripts in Ruby, you may need some scripts to run in Ruby 1.8, while others work in Ruby 1.9. In an interactive session, Ruby shell scripts are executed in the currently loaded environment, so you may not get what you expect. I’d prefer a self contained script that loads an expected interpreter and environment explicitly.

Wayne provides some example code for loading the RVM environment on the scripting page, but stops short of a working script example. I’ve taken the very, very small leap to a working script wrapper. The benefit of this wrapper is that it is portable to any environment where RVM is available at a user or system-wide level. You will, however, have to ensure that the appropriate Ruby and gemset are available. The script looks like this:

#!/usr/bin/env bash

# Load RVM into a shell session *as a function*
if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then
  # First try to load from a user install
  source "$HOME/.rvm/scripts/rvm"
elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then
  # Then try to load from a root install
  source "/usr/local/rvm/scripts/rvm"
else
  printf "ERROR: An RVM installation was not found.\n"
fi

# Configure ruby and gemset
rvm ruby-1.9.2-p290@gemset_name >/dev/null

ruby <<-rb
  puts "Hello!"
rb

I’m a jack of all trades, so I’m sure that there are different ideas and methods that may be better than this. I’d love to hear about them! Trackbacks are open on this page, so please comment and let me know what you think.

Augmenting my command line tool kit

A nice little list of command line tools for a variety of tasks. I’m probably not going to be using the calendar any time soon, but I already use htop, iptraf, mtr, and siege (along with the obvious ones like xargs and vim).

“A little collection of cool unix terminal/console/curses tools”:http://kkovacs.eu/cool-but-obscure-unix-tools

unix-tools.png