sábado, 17 de abril de 2021

Cron y Logrotate

Si tenemos un "script" que necesitamos que se ejecute automáticamente en un momento determinado o cada cierto tiempo podemos usar la aplicación cron. Al ejecutarse el "script" es conveniente guardar registros de su actividad en un archivo "log". Para archivar los registros que se vayan creando y eliminar los antiguos que ya no necesitemos podemos usar la aplicación logrotate.

Creé un "script" para realizar copias de seguridad incrementales y totales usando el comando tar. Es importante que estas copias se realicen automáticamente en los días y horas necesarios. Para ello debemos añadir unas programaciones a la aplicación cron creando el archivo incremental-backup en el directorio /etc/cron.d con el siguiente contenido:

# Full Backup - Saturday 04:00
0  4 * * 6   backup /usr/local/bin/incremental-backup.sh full 

# Incremental Backup Tuesday - Friday 04:00
0  4 * * 2-5 backup /usr/local/bin/incremental-backup.sh incr 

# Incremental Backup Monday - Friday 12:00
0 12 * * 1-5 backup /usr/local/bin/incremental-backup.sh incr 

Suponemos que estamos haciendo un sistema de copias de seguridad para una empresa en la que se trabaja de lunes a viernes. Así que necesitamos hacer una copia incremental todas las madrugadas de martes a viernes con los datos nuevos del día anterior. Llegado el sábado en lugar de una copia incremental hacemos una copia completa, de esta manera para recuperar todos los datos de un día determinado solo necesitaremos extraer el contenido de una copia completa y entre una y cuatro incrementales.

Podemos aumentar el número de copias incrementales haciendo una a media jornada, de esta forma no se perderán datos creados a primera hora y borrados antes de la siguiente copia. Esto todavía deja la posibilidad de perder datos creados y borrados o modificados entre dos copias incrementales. Si necesitamos que quede registro de cualquier cosa que se escriba ya tendríamos que usar otro tipo de sistema de copias de seguridad que estuviera monitorizando continuamente los archivos. Esto lo dejaré para otro artículo.

Como hoy día disponemos de discos duros inmensos y además podemos hacer RAIDs con ellos, no hay problema en guardar copias de seguridad de varios años. Si tenemos limitación de espacio cada cierto tiempo podemos eliminar manualmente las copias antiguas, archivarlas en otro lugar o por ejemplo dejar una sola copia completa por mes de años anteriores. También podemos crear un "script" que haga este trabajo por nosotros y ejecutarlo manualmente o a través de cron. Por ejemplo para eliminar o archivar copias más antiguas a un año podemos usar el comando find para encontrar las copias de más de 365 días y ejecutar sobre cada una de ellas el comando rm para eliminarlas o mv para moverlas a otro lugar.

# find /var/incremental-backup/*.tar.bz2 -mtime +365 -exec rm {} \;

Que el borrado se haga automáticamente tiene el peligro de que si por alguna razón el ordenador tiene una fecha errónea se pueden eliminar archivos que no queremos que se borren. Hacer el borrado o archivado manualmente nos da más seguridad de que los archivos tienen la fecha deseada.

Si queremos que quede un registro de cada ejecución del "script" o de los errores que pudieran suceder podemos redirigir la salida estándar y la de errores a un archivo "log", por ejemplo /var/log/incremental-backup.log. Cron utiliza por defecto el interprete de comandos /bin/sh, donde >> redirige la salida estándar al archivo y la escribe a continuación de lo ya escrito y 2>&1 redirige la salida de errores a la salida estándar, haciendo que todos los mensajes acaben agregándose al archivo "log".

# Full Backup - Saturday 04:00
0  4 * * 6   backup /usr/local/bin/incremental-backup.sh full >> /var/log/incremental-backup.log 2>&1

# Incremental Backup Tuesday - Friday 04:00
0  4 * * 2-5 backup /usr/local/bin/incremental-backup.sh incr >> /var/log/incremental-backup.log 2>&1

# Incremental Backup Monday - Friday 12:00
0 12 * * 1-5 backup /usr/local/bin/incremental-backup.sh incr >> /var/log/incremental-backup.log 2>&1

Al principio del archivo /etc/cron.d/incremental-backup se puede indicar el interprete de comandos con la variable $SHELL. Por ejemplo se puede usar /bin/bash para poder redirigir la salida estándar y la de errores usando solamente &>>.

SHELL=/bin/bash

Para que el usuario backup pueda escribir en ese archivo "log" debemos crearlo y darle los permisos necesarios de forma similar a la creación del directorio /var/incremental-backup.

# touch /var/log/incremental-backup.log
# chgrp backup /var/log/incremental-backup.log
# chmod g+w /var/log/incremental-backup.log
# ls -ld /var/log/incremental-backup.log

-rw-rw-r-- 1 root backup 99 jul 20 20:34 /var/log/incremental-backup.log

De esta forma cuando se cree otra copia de seguridad los mensajes que se muestran por pantalla al ejecutar el "script" serán grabados en el archivo "log".

# cat /var/log/incremental-backup.log

2020-07-21_18-34-05 - INCREMENTAL BACKUP: data-users
2020-07-21_18-34-05 - INCREMENTAL BACKUP: company-database

Para la fecha y hora de los mensajes que se muestran por pantalla o se redirigen al archivo "log" he utilizado la misma fecha que para los archivos. También se podría modificar el "script" para que en la fecha de los mensajes utilizara el formato usado en otros archivos "log". Al ejecutar date se debe fijar la variable LC_ALL=POSIX o C para que no utilice el idioma del sistema para escribir la abreviatura del nombre del mes.

# LC_ALL=POSIX date +"%b %e %T"

Jul 21 18:44:38

Como solo se van a hacer unas cuantas copias al día el archivo "log" no crecerá mucho pero tenemos la posibilidad de configurar logrotate para que vaya archivando los registros antiguos en otros archivos y los elimine con el tiempo. Para configurarlo podemos crear el archivo incremental-backup en el directorio /etc/logrotate.d con el siguiente contenido:

/var/log/incremental-backup.log {
        monthly
        rotate 12
        compress
        delaycompress
        notifempty
        create 664 root backup
}

Según esta configuración cada mes (monthly) va a renombrar el archivo incremental-backup.log, si no está vacío (notifempty), a incremental-backup.log.1 y no lo va a comprimir (delaycompress). A continuación va a crear un nuevo archivo incremental-backup.log con dueño root, grupo backup y permisos de escritura para el dueño y el grupo (create 664 root backup) para que el usuario backup pueda seguir escribiendo en él.

Antes de eso, si ya existía el archivo incremental-backup.log.1, lo va a renombrar a incremental-backup.log.2.gz y lo va a comprimir con gzip (compress). Si existía el archivo incremental-backup.log.2.gz lo renombrará previamente a incremental-backup.log.3.gz y así sucesivamente. Los archivos van rotando y cuando se han creado doce archivos (rotate 12) el número 12 es eliminado y el 11 es renombrado a 12.

Al cabo de doce meses tendremos los siguientes archivos:

# ls -1 /var/log/incremental-backup.log*

/var/log/incremental-backup.log
/var/log/incremental-backup.log.1
/var/log/incremental-backup.log.10.gz
/var/log/incremental-backup.log.11.gz
/var/log/incremental-backup.log.12.gz
/var/log/incremental-backup.log.2.gz
/var/log/incremental-backup.log.3.gz
/var/log/incremental-backup.log.4.gz
/var/log/incremental-backup.log.5.gz
/var/log/incremental-backup.log.6.gz
/var/log/incremental-backup.log.7.gz
/var/log/incremental-backup.log.8.gz
/var/log/incremental-backup.log.9.gz

A continuación se muestra un resumen de los archivos creados:

  • Programación de copias completas e incrementales en cron: /etc/cron.d/incremental-backup
  • Archivo de registros: /var/log/incremental-backup.log
  • Configuración de rotación del archivo de registros en logrotate: /etc/logrotate.d/incremental-backup

En otro artículo utilizaré los servicios de systemd para realizar las funciones de cron y logrotate.

No hay comentarios:

Publicar un comentario