Localizando el log de PostgreSQL

A menudo no es una tarea fácil dar con el log de un servidor PostgreSQL, sobre todo si no lo hemos instalado ni configurado nosotros. En este artículo vamos a aprender a explorar el sistema para conocer su paradero, y de paso veremos los parámetros del servidor implicados en la configuración del log de PostgreSQL.

Lo primero que tenemos que saber es que, desde el mismo momento en que el servicio de PostgreSQL levanta, los mensajes que emite se escriben en la salida estándar de errores del sistema operativo, y PostgreSQL (o las aplicaciones que lo inician) pueden redigir la salida de muchas formas posibles.

Por ejemplo, si iniciamos PostgreSQL manualmente, usando la aplicación pg_ctl sin indicar una redirección para los mensajes del log, estos se mostrarán por pantalla.

Levanta el servidor PostgreSQL de esta forma:

pg_ctl -D /var/lib/pgsql/12/data/ start

Tendrás una salida similar a esta:

esperando que el servidor se inicie.…
2020-11-25 11:06:45.885 CET [4101] LOG: iniciando PostgreSQL 12.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-bit
2020-11-25 11:06:45.886 CET [4101] LOG: escuchando en la dirección IPv4 «0.0.0.0», port 5432
2020-11-25 11:06:45.886 CET [4101] LOG: escuchando en la dirección IPv6 «::», port 5432
2020-11-25 11:06:45.887 CET [4101] LOG: escuchando en el socket Unix «/var/run/postgresql/.s.PGSQL.5432»
2020-11-25 11:06:45.890 CET [4101] LOG: escuchando en el socket Unix «/tmp/.s.PGSQL.5432»
2020-11-25 11:06:45.895 CET [4102] LOG: el sistema de bases de datos fue apagado en 2020-11-25 11:06:35 CET
2020-11-25 11:06:45.897 CET [4101] LOG: el sistema de bases de datos está listo para aceptar conexiones

Ahora prueba a provocar errores desde otra terminal:

psql -c “create database demo;”
CREATE DATABASE
psql -c “create database demo;”
ERROR: la base de datos «demo» ya existe

Verás cómo los mensajes son volcados a la terminal:

2020-11-25 11:07:16.785 CET [4323] ERROR: la base de datos «demo» ya existe
2020-11-25 11:07:16.785 CET [4323] SENTENCIA: create database demo;

Si indicamos un destino para los mensajes del log con el parámetro -l de pg_ctl serán redirigidos a ese fichero.

Levanta el servidor PostgreSQL de esta forma:

pg_ctl -D /var/lib/pgsql/12/data/ start -l /var/lib/pgsql/server_pgsql12.log

Recuperarás el control de la terminal tras estos mensajes:

esperando que el servidor se inicie…. listo
servidor iniciado

Mira el contenido del log:

cat /var/lib/pgsql/server_pgsql12.log
2020-11-25 11:20:28.105 CET [5297] LOG: iniciando PostgreSQL 12.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-bit
2020-11-25 11:20:28.106 CET [5297] LOG: escuchando en la dirección IPv4 «0.0.0.0», port 5432
2020-11-25 11:20:28.106 CET [5297] LOG: escuchando en la dirección IPv6 «::», port 5432
2020-11-25 11:20:28.107 CET [5297] LOG: escuchando en el socket Unix «/var/run/postgresql/.s.PGSQL.5432»
2020-11-25 11:20:28.108 CET [5297] LOG: escuchando en el socket Unix «/tmp/.s.PGSQL.5432»
2020-11-25 11:20:28.116 CET [5298] LOG: el sistema de bases de datos fue apagado en 2020-11-25 11:19:43 CET
2020-11-25 11:20:28.118 CET [5297] LOG: el sistema de bases de datos está listo para aceptar conexiones

Si provocamos errores ahora:

psql -c “create database demo;”
ERROR: la base de datos «demo» ya existe

Veremos que los mensajes han sido redirigidos al fichero del log indicado:

cat /var/lib/pgsql/server_pgsql12.log

Si el proceso logger está en ejecución, la salida estándar de errores será capturada y redirigida al fichero con nombre log_filename, en la ruta indicada en log_directory.

logger es un proceso de PostgreSQL que se inicia al levantar el servicio si así está establecido en el servidor, es decir, si logging_collector = ‘on’.

Lo comprobamos así:

psql -At -c “show logging_collector;”
on

También podríamos ver si el proceso está levantado de esta forma:

ps -ef | grep postgres
postgres 2876 1 0 10:29 ? 00:00:00 /usr/lib/postgresql/12/bin/postgres -D /var/lib/postgresql/12/main -c config_file=/etc/postgresql/12/main/postgresql.conf
postgres 2877 2876 0 10:29 ? 00:00:00 postgres: 12/main: logger
postgres 2879 2876 0 10:29 ? 00:00:00 postgres: 12/main: checkpointer
postgres 2880 2876 0 10:29 ? 00:00:00 postgres: 12/main: background writer
postgres 2881 2876 0 10:29 ? 00:00:00 postgres: 12/main: walwriter
postgres 2882 2876 0 10:29 ? 00:00:00 postgres: 12/main: autovacuum launcher
postgres 2883 2876 0 10:29 ? 00:00:00 postgres: 12/main: stats collector
postgres 2884 2876 0 10:29 ? 00:00:00 postgres: 12/main: logical replication launcher

log_directory puede indicar una ruta absoluta o una ruta relativa al directorio de datos. Lo comprobamos:

psql -At -c “show log_directory;”
log

Como se trata de una ruta relativa, averiguamos ahora la ruta del directorio de datos:

psql -At -c “show data_directory;”
/var/lib/postgresql/12/main

Y ahora, el nombre del fichero de log:

psql -At -c “show log_filename;”
postgresql-%Y-%m-%d_%H%M%S.log

Por lo tanto, la salida estándar de errores del servidor PostgreSQL está siendo redirigida al fichero:

/var/lib/postgresql/12/main/log/postgresql-%Y-%m-%d_%H%M%S.log

El carácter % seguido por un carácter modificador se convierten de manera automática creando nombres de archivo que varíen en el tiempo. Al iniciar el servidor se creará un fichero:

postgresql-<año>–_.log

Si logger no está en ejecución y hemos iniciado PostgreSQL con otra aplicación distinta a pg_ctl, podemos saber hacia dónde está redirigida la salida estándar de errores de PostgreSQL buscando en /proc de nuestro sistema de ficheros.

Para ello necesitamos averiguar el PID del servicio de base de datos así que lo primero será ejecutar:

ps -ef | grep postgres
postgres 2876 1 0 10:29 ? 00:00:00 /usr/lib/postgresql/12/bin/postgres -D /var/lib/postgresql/12/main -c config_file=/etc/postgresql/12/main/postgresql.conf
postgres 2877 2876 0 10:29 ? 00:00:00 postgres: 12/main: logger
postgres 2879 2876 0 10:29 ? 00:00:00 postgres: 12/main: checkpointer
postgres 2880 2876 0 10:29 ? 00:00:00 postgres: 12/main: background writer
postgres 2881 2876 0 10:29 ? 00:00:00 postgres: 12/main: walwriter
postgres 2882 2876 0 10:29 ? 00:00:00 postgres: 12/main: autovacuum launcher
postgres 2883 2876 0 10:29 ? 00:00:00 postgres: 12/main: stats collector
postgres 2884 2876 0 10:29 ? 00:00:00 postgres: 12/main: logical replication launcher

Y luego:

ll /proc/2876/fd/2
l-wx—— 1 postgres postgres 64 Nov 25 10:47 /proc/2876/fd/2 -> /var/log/postgresql/postgresql-12-main.log

Esta ruta es un enlace simbólico al destino del log.

Esto es así en el arranque de PostgreSQL como hemos dicho pero, en cuanto PostgreSQL lee los parámetros de configuración del log, definidos por el servidor, se lleva a cabo la redirección al destino final. Por esta razón siempre se registran trazas en la salida de error estándar cuando iniciamos PostgreSQL a pesar de tener una configuración distinta para el destino del log.

Los destinos posibles se indican en el parámetro log_destination y pueden ser alguno de los siguientes:

log_destination = ‘stderr’

Es el valor por defecto.

Le indica a PostgreSQL que continué redirigiendo el log a la salida estándar de errores.

log_destination = ‘csvlog’

Le indica a PostgreSQL que capture los mensajes de log, de la salida estándar de errores, en el fichero indicado por:

[data_directory/]log_directory/log_filename

en formato CSV (comma separated values).

Requiere que logging_collector esté habilitado.

log_destination = ‘syslog’

Le indica a PostgreSQL que dirija los mensajes de log al syslog del sistema, en alguna de las utilidades de LOCAL0 a LOCAL7 que le indiquemos en el parámetro syslog_facility (‘LOCAL0’ por defecto), y los identifique con el nombre indicado en syslog_ident (‘postgres’ por defecto).

El syslog, con todas sus ventajas, es un poco el cajón de sastre de los logs del sistema. De ahí que haya que diferenciar los que vienen del servidor PostgreSQL de alguna manera, y varía de un sistema operativo.

En Ubuntu lo encontramos en /var/log/syslog y en Centos lo tenemos en /var/log/messages.

log_destination = ‘eventlogs’

Exclusivo para plataformas Windows.

También es posible indicar más de un destino separándolos por comas:

log_destination = ‘stderr, csvlog’

Como habrás podido comprobar, las opciones de destino para las trazas de un servidor PostgreSQL son muchas y variadas. Todas tienen sus ventajas e inconvenientes, y como todo, unas son más válidas para determinados servidores que otras.

Si quieres saber todo acerca del log de PostgreSQL echa un vistazo aquí: Administración PostgreSQL: El Log del servidor.