bash

Bash script notes

A couple of points I wanted to track regarding a bash script a had to write recently:

1 - Do and action if the command execution is successful

Assuming you want to delete a docker container only if it exists. You can first try to inspect that container and if the return value is successful you can then delete it.

if docker inspect $CONTAINER_NAME &> /dev/null;  
  then
  echo "Destroying $CONTAINER_NAME container"
  docker rm -f $CONTAINER_NAME
fi  
2 - Use absolute paths when referring to dependent scripts

A common problem with scripts with multiple dependent files is that a certain path must be hardcoded on the script which can then lead to breaking paths depending on where the user executes that script. To avoid any issues on that regards you can use the bash variable BASH_SOURCE

script_dir=$(dirname "${BASH_SOURCE[0]}")  

So if you need to execute a script relative to the one being executed you can refer to:

$script_dir/my-other-script.sh

Instead of just

./my-other-script.sh

Executing script on the host when running Vagrant commands

When running Vagrant commands there might be the need to execute something on the host as a pre setup requirement.

Since Vagrant is built with ruby it is possible to execute a shell script utilizing the system utility

system("script.sh")  

In some cases you might want to run a script only in a certain command of Vagrant, for example, when reloading the Vagrant box you might need to check if your host has all gateway routes configured or any other pre setup task.

system("  
  if [ #{ARGV[0]} = 'reload' ]; then
    echo 'Setting up routes on the host when reloading Vagrant box'
    ./set-up-routes.sh
  fi
")

Bash script to check if route exists with netstat and grep

Recently while crafting a Vagrantfile I came across the need of checking if I had already added a route to my host when reload the vagrant box.

Listing routes
netstat -nr  
  • -r shows the routing table
  • -n shows the network addresses as number
Matching the pattern
grep -co '172.17 *192.168.14.10'  
  • -c writes the number of matches to stdout
  • -o prints only the matching part of the line

Putting both commands together

if [ $(netstat -nr | grep -co '172.17 *192.168.14.10') = 0 ]; then  
        echo 'Adding gateway route for docker0 network'
        sudo route -n add 172.17.0.0/16 " + $vb_ip_address + "
    fi

Migrate git repositories

Recently I came across the task of migrating existing repositories from one gitlabs instance to another.

I could have generated a backup and restored it, however, I didn’t want to deal with any migration issues so I decided to simple push the existing repositories to a new remote.

Below is a shell scripts that clones existing git repositories and then push their refs to a new remote:


 #!/bin/bash

old_name[0]="old-repo-name"  
 old_name[1]="same-repo-name"  
 new_name[0]="new-repo-name"  
 new_name[1]="same-repo-name"

cur_dir=$(pwd)  
 for (( i = 0 ; i < ${#old_name[@]} ; i=$i+1 ));  
 do  
 echo -e "nnRepo $i"  
 old=${old_name[${i}]}  
 new=${new_name[${i}]}  
 echo "old – $old"  
 echo "new – $new"

 if [ ! -d "$old" ]; then  
 echo -e "nCloning repository $old…"

 git clone git@gitlabs.dev.cloud:clouddynamics/$old.git  
 cd $old  
 git remote rm origin  
 git remote add origin git@gitlabs.cloud:cloud-dynamics/$new.git  
 git push –all origin  
 cd $cur_dir  
 fi  
 done  

**UPDATE

The script above will not push all branches to the new remote.
If you want to migrate all branches run the following script as well:

  
 #!/bin/bash

old_name[0]="repo-name"  
 old_name[1]="another-repo-name"

cur_dir=$(pwd)  
 for (( i = 0 ; i < ${#old_name[@]} ; i=$i+1 ));  
 do  
 echo -e "nnRepo $i"  
 old=${old_name[${i}]}  
 echo "old – $old"  
 cd $old  
 echo -e "nPushing branches from old to origin remote…"  
 git remote add old git@gitlabs.dev.cloud:clouddynamics/$old.git  
 git fetch old  
 git push origin refs/remotes/old/*:refs/heads/*  
 cd $cur_dir  
 done