pgenv
For years, I’ve managed multiple versions of PostgreSQL by regularly editing and
running a simple script that builds each major version from source and
installs it in /usr/local
. I would shut down the current version, remove the
symlink to /usr/local/pgsql
, symlink the one I wanted, and start it up again.
This is a pain in the ass.
Recently I wiped my work computer (because reasons) and started reinstalling all
my usual tools. PostgreSQL, I decided, no longer needs to run as the postgres
user from /usr/local
. What would be much nicer, when it came time to test
pgTAP against all supported versions of Postgres, would be to use a tool like
plenv or rbenv to do all the work for me.
So I wrote pgenv. To use it, clone it into ~/.pgenv
(or wherever you want)
and add its bin
directories to your $PATH
environment variable:
git clone https://github.com/theory/pgenv.git
echo 'export PATH="$HOME/.pgenv/bin:$HOME/.pgenv/pgsql/bin:$PATH"' >> ~/.bash_profile
Then you’re ready to go:
pgenv build 10.4
A few minutes later, it’s there:
$ pgenv versions
pgsql-10.4
Let’s use it:
$ pgenv use 10.4
The files belonging to this database system will be owned by user "david".
This user must also own the server process.
# (initdb output elided)
waiting for server to start.... done
server started
PostgreSQL 10.4 started
Now connect:
$ psql -U postgres
psql (10.4)
Type "help" for help.
postgres=#
Easy. Each version you install – as far back as 8.0 – has the default super
user postgres
for compatibility with the usual system-installed version. It
also builds all contrib modules, including PL/Perl using /usr/bin/perl
.
With this little app in place, I quickly built all the versions I need. Check it out:
$ pgenv versions
pgsql-10.3
* pgsql-10.4
pgsql-11beta2
pgsql-8.0.26
pgsql-8.1.23
pgsql-8.2.23
pgsql-8.3.23
pgsql-8.4.22
pgsql-9.0.19
pgsql-9.1.24
pgsql-9.2.24
pgsql-9.3.23
pgsql-9.4.18
pgsql-9.5.13
pgsql-9.6.9
Other commands include start
, stop
, and restart
, which act on the
currently active version; version
, which shows the currently-active version
(also indicated by the asterisk in the output of the versions
command);
clear
, to clear the currently-active version (in case you’d rather fall back
on a system-installed version, for example); and remove
, which will remove a
version. See the docs for details on all the commands.
How it Works
All this was written in an uncomplicated Bash script. I’ve ony tested it on a
couple of Macs, so YMMV, but as long as you have Bash, Curl, and /usr/bin/perl
on a system, it ought to just work.
How it works is by building each version in its own directory:
~/.pgenv/pgsql-10.4
, ~/.pgenv/pgsql-11beta2
, and so on. The currently-active
version is nothing more than symlink, ~/.pgenv/pgsql
, to the proper version
directory. There is no other configuration. pgenv downloads and builds versions
in the ~/.pgenv/src
directory, and the tarballs and compiled source left in
place, in case they’re needed for development or testing. pgenv never uses them
again unless you delete a version and pgenv build
it again, in which case
pgenv deletes the old build directory and unpacks from the tarball again.
Works for Me!
Over the last week, I hacked on pgenv to get all of these commands working. It
works very well for my needs. Still, I think it might be useful to add support
for a configuration file. It might allow one to change the name of the default
superuser, the location Perl, and perhaps a method to change postgresql.conf
settings following an initdb
. I don’t know when (or if) I’ll need that stuff,
though. Maybe you do, though? Pull requests welcome!
But even if you don’t, give it a whirl and let me know if you find any issues.