Waiting on postgres readiness (in 1 line)
I recently launched postgres via docker, and needed a second command to wait for postgres to be ready before trying to connect to it (to apply migrations).
While there's an executable for checking postgres readiness called pg_isready, it's not installed everywhere by default.
Postgres doesn't have any HTTP interface, but it does listen for commands on a TCP port. Let's use netcat
to send the following payload to postgres (in my case, postgres was running via docker on localhost (127.0.0.1) and port 5432)
echo -ne "\x00\x00\x00\x17\x00\x03\x00\x00user\x00username\x00\x00" | nc -w 3 127.0.0.1 5432 2>/dev/null | head -c1
If postgres is ready to accept connections, it will respond with R
$ echo -ne "\x00\x00\x00\x17\x00\x03\x00\x00user\x00username\x00\x00" | nc -w 3 127.0.0.1 5432 2>/dev/null | head -c1
R
Knowing that, we can use this request to send the same payload in a loop until postgres responds with R
.
Via a makefile, it can be done this way:
@while ! test "`echo -ne "\x00\x00\x00\x17\x00\x03\x00\x00user\x00username\x00\x00" | nc -w 3 127.0.0.1 5432 2>/dev/null | head -c1`" = R; do echo "waiting on postgres..."; sleep 0.3; done;
This uses bash syntax, so we'll have to specify the shell as bash
for this specific makefile target:
my-make-target: $(eval SHELL:=/bin/bash)
Putting it all together, this gives us:
my-make-target: $(eval SHELL:=/bin/bash)
@while ! test "`echo -ne "\x00\x00\x00\x17\x00\x03\x00\x00user\x00username\x00\x00" | nc -w 3 127.0.0.1 5432 2>/dev/null | head -c1`" = R; do echo "waiting on postgres..."; sleep 0.3; done;
echo "put your commands that depend on postgres being ready here..."
That's it ! We're now able to have any makefile command wait for postgres to be ready before running. And as a bonus, it holds in one line !