Postgres Postmaster File Explained

You may have noticed a file called postmaster.pid inside your data directory. This file gets created when Postgres first starts up, and gets removed on a clean shutdown. It seems to contain some random numbers and strings, but what do they all mean?

The file will look like this:

2757
/home/greg/pg/17/data
176540940
5432
/tmp
*
   8675309        12
ready

Here is a quick cheat sheet of the contents:

Line Example value Meaning Postgres source code
1 2757 The PID of the parent postgres process LOCK_FILE_LINE_PID
2 /home/greg/pg/17/data The data directory LOCK_FILE_LINE_DATA_DIR
3 176540940 Epoch value of when postgres started LOCK_FILE_LINE_START_TIME
4 5432 Port number postgres is listening on LOCK_FILE_LINE_PORT
5 /tmp Unix socket directory LOCK_FILE_LINE_SOCKET_DIR
6 * TCP/IP interfaces being listened on LOCK_FILE_LINE_LISTEN_ADDR
7 8675309       12 Shared memory key and id LOCK_FILE_LINE_SHMEM_KEY
8 ready Current status LOCK_FILE_LINE_PM_STATUS

Why is it called postmaster.pid?

The word "postmaster" is a relic from the early days of Postgres. This used to be the name of the main executable. While the main executable was, and still is, named "postgres", it also used to have a symlink named "postmaster". As of version 16, the symlink is no longer created. However, the name "postmaster" is here to stay, as the source code uses it a lot.

So what does postmaster.pid do?

The postmaster.pid file is a semaphore file. When it exists, there is a good chance that Postgres is running. The file gets created in the data directory of Postgres as part of the startup process. It contains exactly eight lines of information inside of it. Other programs look for the existence of the postmaster.pid file as an indication that Postgres is up and running. Postgres itself will complain on startup if the file already exists with this error: FATAL: lock file "postmaster.pid" already exists.

Where is the source code?

Inside the Postgres source code, the postmaster.pid is called a "directory lock file". You can see it defined inside backend/utils/init/miscinit.c:

#define DIRECTORY_LOCK_FILE                "postmaster.pid"

While in theory you could change the name by modifying this line, in practice it will never happen, as the source code does not use this define everywhere. Also, many external tools rely upon the name being exactly "postmaster.pid". They also assume it is being created inside the top level of the Postgres data directory.

Access to the file happens in Postgres via the AddToDataDirLockFile() function, mostly from the file postmaster.c. Here's an example call:

AddToDataDirLockFile(LOCK_FILE_LINE_SOCKET_DIR, socketdir);

The first argument corresponds to one of the eight lines inside the file. The order of the lines is always the same. Let's look at each of them right now!

Line 1 of postmaster.pid: the PID of the main postgres executable

The primary job of the main postgres executable is to listen on a port for incoming connections. Once something connects on that port, postgres forks itself, and lets the new child process handle this new client connection. It then returns to listening. Line one is the process ID (PID) of this main parent postgres executable.

If this number is negative, the server is running with the --single flag, also known as a stand-alone backend.

This PID number is the most common bit of information requested from this file. You can extract it and pass it to something else. For example, a quick recipe to ask Postgres to reload its configuration file is:

kill -HUP $(head -1 postmaster.pid)

In the Postgres source code, line one is LOCK_FILE_LINE_PID.

Line 2 of postmaster.pid: the location of the data directory

Line two is the least useful of any of the lines, as the postmaster.pid file is always created inside of the data directory.

In the Postgres source code, line two is LOCK_FILE_LINE_DATA_DIR.

Line 3 of postmaster.pid: when Postgres was started

Line three tells us exactly when the Postgres cluster came to life. Unfortunately for us humans, this timestamp shows as the number of seconds since January 1, 1970. In other words, an epoch time. You can convert it to a human-readable answer with some unix tools:

$ date -d @`sed -n 3p postmaster.pid`
Thu 25 Dec 2024 12:34:56 PM EST

If you want to use something a little more modern than sed (ha!):

$ date -d @`awk 3==NR postmaster.pid`
Thu 25 Dec 2024 12:34:56 PM EST

In the Postgres source code, line three is LOCK_FILE_LINE_START_TIME.

Line 4 of postmaster.pid: the port number

The second most useful line in the file is line four, which contains the port number that Postgres is listening on. By default, this is 5432, but it can be set inside the postgresql.conf file or even as a command-line argument. Either way, line four is an authoritative way to show the port number clients should be using to connect to Postgres.

In the Postgres source code, line four is LOCK_FILE_LINE_PORT.

Line 5 of postmaster.pid: the first unix socket directory

Postgres uses the port number to listen in two places: unix socket connections (for things local to this server, e.g. the psql program), and TCP/IP connections. Line five is about the socket connection. By default, this is /tmp, but many distributions have changed it to /var/run/postgresql. You are likely to see the latter if you installed Postgres via a packaging system. This line will be blank if the server is in single mode.

Warning! If you are listening on multiple socket directories, which is very possible, only the first one will appear here! So if you have this in your postgresql.conf file:

unix_socket_directories = '/tmp, /var/run/postgresql'

The only thing that will show up on line five in the example above is /tmp. If you need the full list, do not rely on the postmaster.pid file but use this recipe:

bin/postgres -D data -C unix_socket_directories

In the Postgres source code, line five is LOCK_FILE_LINE_SOCKET_DIR.

Line 6 of postmaster.pid: the first network interface

The other place Postgres listens on a port is TCP/IP connections, which is set by the listen_addresses configuration parameter. It is common to set this to '*', instructing Postgres to listen on all interfaces.

Beware! If there are multiple IP addresses listed, only the first one will appear on line six. To see them all, run:

bin/postgres -D data -C listen_addresses

Line six will be blank if the server is in single mode, or if listen_addresses is set to an empty string.

In the Postgres source code, line six is LOCK_FILE_LINE_LISTEN_ADDR.

Line 7 of postmaster.pid: shared memory information

Postgres uses shared memory that each client backend accesses. The startup process handles creating this memory. Line seven indicates the key - and id - of this shared memory. These numbers are not particularly useful except as a deep debugging aid. You can view your current shared memory segments by running:

ipcs -m

The "shmid" column will correspond to the second number of line seven.

On Windows, this line will be blank.

In the Postgres source code, line seven is LOCK_FILE_LINE_SHMEM_KEY.

Line 8 of postmaster.pid: the current status

The final line of the file shows the current status of the Postgres cluster. In most cases, you will see this as "ready". The other three possible options are "starting", "stopping", and "standby".

If running in single mode, this line will not exist!

In the Postgres source code, line eight is LOCK_FILE_LINE_PM_STATUS.

Troubleshooting

I hope you enjoyed this walk through the contents of the postmaster.pid file. If Postgres was not shut down the normal way, it is possible for this file to exist, but the PID mentioned on line 1 does not. Postgres is smart enough to figure this out and remove the file itself on startup, so removing it manually should be a method of last resort.

Avatar for Greg Sabino Mullane

Written by

Greg Sabino Mullane

January 12, 2024 More by this author