1

I've installed postgres 9.5 on ubuntu 16.04 which creates postgresql.service and postgresql@.service.

I understand that the postgresql.service spawns all enabled instances of postgres, and I can call a specific instance with postgresql@9.5-main but postgresql@.service is a template file, and I can't see any place where the instance string (represented by %i or %I in the template) would be passed by postgresql.service.

How does postgresql.service know which instances are enabled, and how does it pass them to the systemd template file?

3

To answer this, start with checking the contents of the two files in question. If you aren't sure where to find them, you can search the package contents for systemd files:

 dpkg -L postgresql-common| grep systemd

From looking at the postgresql.service file you can see you not doing much at all:

# systemd service for managing all PostgreSQL clusters on the system. This
# service is actually a systemd target, but we are using a service since
# targets cannot be reloaded.

[Unit]
Description=PostgreSQL RDBMS

[Service]
Type=oneshot
ExecStart=/bin/true
ExecReload=/bin/true
RemainAfterExit=on

[Install]
WantedBy=multi-user.target

From the comments, we learn that the file is being used as a systemd "target". Moving on to the template file:

# systemd service template for PostgreSQL clusters. The actual instances will
# be called "postgresql@version-cluster", e.g. "postgresql@9.3-main". The
# variable %i expands to "version-cluster", %I expands to "version/cluster".
# (%I breaks for cluster names containing dashes.)

[Unit]
Description=PostgreSQL Cluster %i
ConditionPathExists=/etc/postgresql/%I/postgresql.conf
PartOf=postgresql.service
ReloadPropagatedFrom=postgresql.service
Before=postgresql.service

[Service]
Type=forking
# @: use "postgresql@%i" as process name
ExecStart=@/usr/bin/pg_ctlcluster postgresql@%i --skip-systemctl-redirect %i start
ExecStop=/usr/bin/pg_ctlcluster --skip-systemctl-redirect -m fast %i stop
ExecReload=/usr/bin/pg_ctlcluster --skip-systemctl-redirect %i reload
PIDFile=/var/run/postgresql/%i.pid
SyslogIdentifier=postgresql@%i
# prevent OOM killer from choosing the postmaster (individual backends will
# reset the score to 0)
OOMScoreAdjust=-900
# restarting automatically will prevent "pg_ctlcluster ... stop" from working,
# so we disable it here. Also, the postmaster will restart by itself on most
# problems anyway, so it is questionable if one wants to enable external
# automatic restarts.
#Restart=on-failure
# (This should make pg_ctlcluster stop work, but doesn't:)
#RestartPreventExitStatus=SIGINT SIGTERM

[Install]
WantedBy=multi-user.target

The interesting directives are:

PartOf=postgresql.service
ReloadPropagatedFrom=postgresql.service

If you aren't sure where find the docs for a systemd directive, you can check: man systemd.directives. From there, we find both these directives in man systemd.unit.

Your biggest clue comes when you enable the service:

sudo systemctl enable postgresql@9.6
Created symlink /etc/systemd/system/multi-user.target.wants/postgresql@9.6.service → /lib/systemd/system/postgresql@.service.

Putting it all together:

  • The symlink is how systemd knows to boot up PostgreSQL 9.6 when the server starts.
  • The PartOf= and ReloadPropagatedFrom= directives handle making sure that stop, start, restart and reload on the postgresql service end up applying to all the related installed PostgreSQL instances.
  • 1
    Perfect answer, I never actually tried to enable/disable the service and I should have. – icecream_hobbit Apr 10 '18 at 19:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.