Tag “Bash”

I sighted increasing interest to my project Bash Booster last week. There is a lot of links, tweets, discussions over the Internet. So, I think I have to write this post to clarify what Bash Booster is and what it isn’t.

First of all, I am definitely not devop. However I played this role at the begin of last summer. This is how it happened. I finished my project, and had to wait while Thumbtack’s sales team was signing a contract of a new one. At that time, another team went into production and they needed help. Because I had nothing to do, I joined the team as a devop engineer. I had to write Chef recipes for AWS OpsWorks to deploy and manage application cluster. It was my first and last time I was using Chef.

Chef is awesome thing, but IMO it is too complicated. I spent a week looking into it. I think, it is mainly because of Chef documentation. I guess, it had been written by marketing-oriented assholes. I understand their goals, you can buy support, and they will make you happy. But if you decide to make it work by your own... Well, there is nobody to blame. Another reason is that Chef is written in Ruby (at least some of its components). The fact itself is not bad. However, in my experience, rubists don’t give a shit about backward compatibility. If Ruby is not your primary tool, get ready to shamanic dance. The most stuff does not work on Ruby shipped with your favorite distributive, because it’s too old. It is also very possible that it will not work on the most recent version, because this version breaks backward compatibility.

Despite all of these, I got working cluster after three weeks. And Chef have done its work perfectly. It is a good tool for devops, sysadmins, and everyone who works with dozens of servers. However, using it for provisioning single Vagrant virtual machine is overkill, it is like hunting a fly with sledgehammer.

When this project was done, my new one had been postponed, and I decided to go to vacation. But before it happened, I had joined to another team for a couple of days. They asked me to set up developing environment using Vagrant. I had written provisioning script using Bash, and went to booze trip into Kazakhstan.

In the middle of the vacation, I reviewed this script. It had been written in Chef recipe style. I didn’t think about it when I was writing it. But in fact Chef’s philosophy influenced me. So I decide to prove a crazy idea—write a Bash version of Chef subset.

As I wrote above, I am not devop, I am developer. I do not work with dozens of servers. It would rather an exception, when I had to. However, it is my normal routine when I have to setup single server for development purposes. It is also usual to me to share my virtual machines with teammates. So it is obvious, that I intensively use Vagrant. Because it is the best tool for such tasks.

Additionally, I do not like overcomplicated tools, which enforce end user set up various dependencies, write config files, and so on. And learning time is also critical to me. Ideally, it should be zero hours.

So, Bash is such tool. Everybody knows it, and it is installed everywhere. BTW, this fact have played Old Harry with Bash recently. I mean ShellShock vulnerability. But anyway, I decided to make a provisioning tool using Bash. So this is how Bash Booster was born.

It does not include any remote execution feature, because I do not need it. It does not try to cover all existent package managers, because I mainly use Debian-based and RedHat-based distributives. So support of Apt and Yum is enough for me. I also did not try, to unify these two ones. Because similar packages have different names in Apt and Yum, anyway you will have to check what manager do you use. So I applied JavaScript approach: test for feature, instead of version. That is why there are functions bb-apt? and bb-yum?.

I also like readability. Because of readability there is a lot of short functions of 1–2 LOC like this one:

bb-apt-package?() {
    local PACKAGE=$1
    dpkg -s "$PACKAGE" 2> /dev/null | grep -q '^Status:.\+installed'
}

I can use $1 variable directly, but assignment to $PACKAGE means that this function accepts single argument—package name. It is for self documenting. The black magic spell of the second line... Well, I do not want to see it in my final script. After a month I would have to find out what does it mean. And I would hardly reproduce it in the next script. So let it live in the library.

The main feature of Bash Booster is delayed events. It helps to avoid unnecessary operations. That is why sync module does not use rsync (I got a lot of criticism about it). It is not about coping files and directories, it is for triggering events when target and destination files are different.

In short, I solved my practical tasks developing Bash Booster. It is definitely not a Chef substitution. You can not manage a server park using it. It is not useful in writing universal platform-agnostic scripts. But if you need a little bit more than simple Bash script, especially when you need event driven Bash script, it will be helpful for you. Moreover, if you missed something, I will be happy to merge your pull request.