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
/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
/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
$ 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
postgres for compatibility with the usual system-installed version. It
also builds all contrib modules, including PL/Perl using
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
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
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
on a system, it ought to just work.
How it works is by building each version in its own directory:
~/.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
~/.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
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.