Many times I craft things that have to be installed in some place, which means that an installer is a nice thing to have. Here’s one, Perl-based.
The basic idea that probably anyone has for a poor man’s deployment system is to pack stuff in a tarball, together with a deployment script inside that has to be executed in the target machine. Without too much fantasy, I figured that I could walk the extra mile and make a package that behaves like a tarball with a twist - i.e. it is capable of executing things after unpacking.
Download self-contained bundled version and save
deployable in some directory in your
PATH. Make sure it’s
Put your stuff in a directory. The current directory is fine. Assume
it is exactly as you want it to appear when you unpack in the
destination. Include a deployment script, i.e. the one that you usually
include for starting the real deployment after unpacking –we’ll call
deploy.sh– and make sure it’s executable. You should have
something like this in the directory:
deploy.sh file1.foo file2.bar somedir/ ...
package.pl ready for deployment, run:
deployable -o package.pl -d deploy.sh \ file1.foo file2.bar somedir ...
package.pl, execute in place and you’re done.
deployable is a handful of tools to help you with remote management of multiple servers. It was born when there was no Puppet or Chef in town - not that I know of, at least - and worked pretty well for me.
In this post we’ll concentrate on the main script –named after the bunch of tools– i.e. the one that allows you to generate smart packages.
Before continuing, if you find it interesting, please note that you
will need to carry also the
remote script with you, together with
installing dependencies. If you like compact packages - and you
probably do if you’re interested in packing thing smartly - you
can download the bundled version. Ensure to
put it in some place in
PATH and to set its execution bits, this
is what we will assume in the rest of this post.
So what was your workflow before deployable? Let’s assume it was something like this:
- place all relevant files in a directory (possibly in a subdirectory)
- add a deployment script to the directory
- create a tarball of that directory
- write instructions to unpack the tarball and execute the deployment script inside the directory that is created
- ship the tarball and the instructions
Something along the following line:
mkdir foobar cp /lots/of/stuff/* foobar vi foobar/deploy.sh # and put what's needed chmod +x foobar/deploy.sh tar cvzf package.tar.gz foobar
You actually don’t have to change your workflow that much. If you want to stick to it, you can still put all your stuff in a directory, like the first bullet above, and create a package with the whole contents of that directory via deployable instead of the last step in the example above:
# preparation goes exactly like before, but packaging is: deployable -o /path/to/package.pl -H foobar -d deploy.sh
You end up with
/path/to/package.pl (you can omit the path to create it
in the current directory of course). At this point, you hardly have to
write any instructions: just tell your recipients to put the script in
the destination server with the execution bits turned on, and execute it.
So what does that command do? Easy:
-osets the output. If not set, the resulting script will be printed on standard output, but if you provide a filename deployable will make it executable
--heredir) tells deployable where your stuff is (in terms of a directory). The contents of the directory will be included in the package, but the initial path set with
-Hwill be stripped away. In the example above, file
foobar/deploy.shwill be included simply as
./deploy.sh). This is useful if you want to store all files/directories to be shipped in one single place, but you don’t care about the containing directory
-dtells deployable that the specified file (i.e.
deploy.shin our example) has to be executed. You can specify whatever file you include, even multiple ones; only remember that the path to the files that you include will be referred to their position in the package, so in our example you have to specify it as
foobaris stripped away.
Here are some shortcuts that deployable provides.
Stuff in current directory
If you just want to ship some files in the current directory, you’re not
obliged to use
-H at all, just tell deployable which files you want
to include. Remember that they will be recorded with the path you provide.
deployable -o p.pl file1 file2 ...
Execute multiple deployment programs
If you want to execute multiple programs, make sure they are all
executable and pass them with multiple
deployable -o p.pl -d exec1 -d exec2 exec1 exec2 file1 ...
If you want to execute all executable files inside the default current
directory, you can just pass the
-X command line parameter. Beware that
it will execute whatever it finds, so make sure that this is what you
deployable -o p.pl -X exec1 exec2 file1 ...
Install stuff in place
At the time that I needed it, chances where that I had to update
some system files in multiple machines at once. This meant that I
wanted the tarball to optionally extract things based on the
root directory (i.e.
/) so that the files go in place.
While this is not hard to do with what explained above –it’s a
matter of crafting the
deploy.sh script for this– it was too
handy to leave outside. You have two ways:
- create a directory
target-rootand put all the stuff you want to install like
target-rootwere the root directory
/of the target system, or
- include files/directories (presumably inside the current directory)
to be directly extracted in the root directory
/of the target system.
If you go the first way, this is how you call deployable:
deployable -o p.pl -r target-root
You can of course add scripts to call within the same command line. If you’re more into the second, this is how you do it:
deployable -o p.pl -R etc
The surface is scratched now…
deployable has plenty of documentation. After installing it, you can run either of these commands, in increasing level of verbosity:
deployable --usage deployable --help deployable --man
and read it. Have fun!