Category Archives: Computing

Git submodules cheat sheet

Note: run these from the top level of your repo.

Clone a repo with submodules:

    $ git clone .vim
    $ git submodule update --init

View status of all submodules:

    $ git submodule status

Update submodules after switching branches:

    $ git submodule update

Add a submodule:

    $ git submodule add git:// bundle/vim-sensible

Update all submodules to latest remote version

    $ git submodule update --remote --merge
    $ git commit -m "Update submodules"

Update a specific submodule to the latest version (explicit method):

    cd bundle/vim-sensible
    git pull origin master
    cd ../..
    git add bundle/vim-sensible
    git commit -m "update vim-sensible"

Remove a submodule:

    edit .gitmodules and remove this submodule's section
    $ git rm --cached bundle/vim-sensible
    $ rm -rf bundle/vim-sensible
    $ git commit -m "Remove vim-sensible"


    git submodule deinit bundle/vim-sensible    
    git rm bundle/vim-sensible
    git commit -m "Remove vim-sensible"


Routing specific traffic to the VPN on OS X

I have a client that requires me to use a VPN when connecting to their servers. I use OS X's built in L2TP VPN to connect, but don't want all my traffic going that way.

To do this, I unchecked the Advanced VPN setting "Send all traffic over VPN connection" in the Network preferences and then created the file /etc/ppp/ip-up like this:

sudo touch /etc/ppp/ip-up
sudo chmod 755 /etc/ppp/ip-up

The file itself is a bash script that runs various /sbin/route commands and looks similar to this:


/sbin/route add -net -interface ppp0

Now, whenever I connect to the VPN, only traffic for hosts on 192.168.1.x is sent to the client's VPN and we're both happy.

Provisioning with Ansible within the Vagrant guest

I've been setting up a Vagrant VM for use with some client projects and picked Ansible to do this. Firstly, I played with the Ansible provisioner, but found it a little slow and then I realised that Ansible doesn't run on Windows.

Rather than migrate what I'd done to Puppet, Evan recommended that I look into running Ansible on the guest instead and provided some hints. This turned out to be quite easy.

These are the steps when starting from the ubuntu/trusty64 base box.

Use the Shell provisioner

As we're running Ansible on the guest, we use the shell provisioner, so my Vagrantfile contains:

config.vm.provision :shell,
  :keep_color => true,
  :inline => "export PYTHONUNBUFFERED=1 && export ANSIBLE_FORCE_COLOR=1 && cd /vagrant/provisioning && ./"

This simply tells Vagrant to run which is stored in the provisioning directory of my project.

I immediately noticed a warning when running vagrant up: "stdin: is not a tty error". This is due to the way Ubuntu tries to echo a message to a shell that isn't interactive. To get rid of this, we need to configure Vagrant's ssh shell to be a non-login one in the Vagrantfile: = "bash -c 'BASH_ENV=/etc/profile exec bash'"

Our shell provisioner needs to do two things:

  1. Install Ansible
  2. Run our playbook

So, looks like this:

#!/usr/bin/env bash

if [ $(dpkg-query -W -f='${Status}' ansible 2>/dev/null | grep -c "ok installed") -eq 0 ];
    echo "Add APT repositories"
    export DEBIAN_FRONTEND=noninteractive
    apt-get install -qq software-properties-common &> /dev/null || exit 1
    apt-add-repository ppa:ansible/ansible &> /dev/null || exit 1

    apt-get update -qq

    echo "Installing Ansible"
    apt-get install -qq ansible &> /dev/null || exit 1
    echo "Ansible installed"

cd /vagrant/provisioning
ansible-playbook setup.yml --connection=local

Obviously, we only want to install Ansible once, so we check the output of dpkg-query and only install if it's not already installed. Installation is easy enough: we just use apt-get to add install what we need (quietly!) from the ansible ppa as per the docs.

Once Ansible is installed, we can run ansible-playbook with the --connnection-local switch to run out playbook, setup.yml in my case.

At this point, it's all standard Ansible all the way for your provisioning. It's just faster and works with Windows.

Git push to multiple repositories

I have a couple of projects where I need to push to more than one repo all the time.

I have been using this command line to do so:

git push origin && git push other-remote

However, I recently discovered that I can create a remote that points to more than one repository using these commands:

git remote add all
git remote set-url --add all ssh://

I now have a remote called all that will push to both repositories!

There's no automatic way to go the other way and fetch from multiple repositories though as apparently it makes less sense to fetch the same branch identifier from multiple places.

Further details in this email by Linus in 2006.

If you want to script the creation of the all remote, then you could use this script which manipulates the remote configuration settings directly:


if [ "`git remote| grep all`" == "all" ] ; then
    git remote remove all

for r in `git remote`
    git config --add remote.all.url `git config remote.$r.url`

Create this as /usr/local/bin/ and then you can just run it in the root of your project.

Context specific history at the bash prompt

One change I made recently to my .profile is this:

# up & down map to history search once a command has been started.
bind '"\e[A":history-search-backward'
bind '"\e[B":history-search-forward'

These two bind command change the way that the up and down arrow keys work once you start typing a command to only search the history for lines that start with what you've typed so far.

This means that I type, say, git and then press ↑ & ↓ to go through all the times I've typed a git command without having to go through all the other commands.

It's quite handy and I find it easier to use than ctrl+r.

Setting up mailcatcher as a service in Debian/Ubuntu

I've recently been changing's Vagrant system to use Debian and one issue I came across was getting Mailcatcher to start on boot and integrate property with the service command.

To do this, I created an init script which is based off the skeleton and then stored this in /etc/init.d and then ran update-rc.d mailcatcher defaults to set up the correct links in the various rc.d directories.

This is the init script:


#! /bin/sh
# Provides:          mailcatcher
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Example initscript
# Description:       This file should be used to construct scripts to be
#                    placed in /etc/init.d.

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the script
DESC="Super simple SMTP server"
DAEMON_ARGS=" --http-ip"

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions

# Function that starts the daemon/service
    # Return
    #   0 if daemon has been started
    #   1 if daemon was already running
    #   2 if daemon could not be started
    start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
        || return 1
    start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
        $DAEMON_ARGS \
        || return 2
    # Add code here, if necessary, that waits for the process to be ready
    # to handle requests from services started subsequently which depend
    # on this one.  As a last resort, sleep for some time.
    # Create the PIDFILE
    pidof mailcatcher >> $PIDFILE

# Function that stops the daemon/service
    # Return
    #   0 if daemon has been stopped
    #   1 if daemon was already stopped
    #   2 if daemon could not be stopped
    #   other if a failure occurred
    if [ -f "$PIDFILE" ]
        kill `cat $PIDFILE`
        rm -f $PIDFILE
        return 0
        return 1

# Function that sends a SIGHUP to the daemon/service
do_reload() {
    # If the daemon can reload its configuration without
    # restarting (for example, when it is sent a SIGHUP),
    # then implement that here.
    start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
    return 0

case "$1" in
    [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
    case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
    case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
    # If do_reload() is not implemented then leave this commented out
    # and leave 'force-reload' as an alias for 'restart'.
    #log_daemon_msg "Reloading $DESC" "$NAME"
    #log_end_msg $?
    # If the "reload" option is implemented then remove the
    # 'force-reload' alias
    log_daemon_msg "Restarting $DESC" "$NAME"
    case "$?" in
        case "$?" in
            0) log_end_msg 0 ;;
            1) log_end_msg 1 ;; # Old process is still running
            *) log_end_msg 1 ;; # Failed to start
        # Failed to stop
        log_end_msg 1
    #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
    echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
    exit 3


As you can probably tell, it's very obviously a tweaked version of /etc/init.d/skeleton, but there are some important changes:

Path to binary
As Mailcatcher is a ruby app, the correct path to the binary is actually /usr/local/rvm/wrappers/default/mailcatcher which is not where which tells you it is. I suspect that my lack of knowledge about Ruby environments is showing…

The do_start() function calls through to start-stop-daemon to start mailcatcher. However this doesn't create a pid file in /var/run for us, so we create it ourselves using:

pidof mailcatcher >> $PIDFILE

Mailcatcher is intended to be stopped by pressing the Quit button in the HTML interface, so the default code in skeleton doesn't work. I rewrote it to simply kill the process if the pid file exists:

    if [ -f "$PIDFILE" ]
        kill `cat $PIDFILE`
        rm -f $PIDFILE
        return 0
        return 1

That's it. The most important thing about these changes is that service mailcatcher status now works as expected and so Puppet's ensure => 'running' test actually works correctly.

Sharing host VPN with Vagrant

When moving a project into Vagrant, I realised that I needed the vagrant guest to share my OS X's VPN.

I'm using a separate IP address within a private network like this: :private_network, ip: ""

So, after some Googling, I added this provider configuration setting:

  config.vm.provider :virtualbox do |vb|
      vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]

and now my VM is sending data over the VPN. Note that this will not work when using the Vagrant's public_network setting though.