Este artículo muestra cómo correr un script o comando en un cliente de Bacula, justo antes de que comience el trabajo de backup para el mismo. Esto es muy necesario para el caso de los servidores de bases de datos, donde se requiere realizar un volcado (dump) de las bases de datos a disco (por ejemplo mysqldump
o pg_dump
) para que sean parte de la copia de seguridad.
Configuración en el cliente
A modo de ejemplo, se requiere correr un script antes del trabajo de backup en el cliente "fbsd10". Loguearse en el servidor en cuestión y crear un directorio donde almacenar scripts, dentro del directorio de backup:
root@fbsd10:~ # mkdir -p /backup/scripts root@fbsd10:~ # cd /backup/scripts/
Crear un script de prueba llamado bacula_pre.sh
:
root@fbsd10:/backup/scripts # nano bacula_pre.sh
El script realizará una tarea útil justo antes de que comience el trabajo de backup. Por ejemplo un dump de las bases de datos MySQL o Postgres. Inicialmente, y a modo de prueba, sólo crea un archivo llamado "pre.txt" dentro del directorio de backup:
#!/bin/sh # Script de ejecución previa al trabajo de backup de Bacula echo "Probando, probando, probando..." > /backup/pre.txt #mysqldump ... #pg_dump ... #tar cjf ...
Modificar los permisos del script para que sólo root tenga ejecución y nadie fuera del grupo "wheel" tenga lectura:
root@fbsd10:/backup/scripts # chmod 750 bacula_pre.sh
Es importante quitar permisos de lectura para others ya que, si se va a utilizar el script para hacer volcados de bases de datos, es probable que contenga credenciales de acceso en formato plano, las cuales no deben poder ser leídas por nadie.
Configuración en el Director
Luego de configurar el cliente, es necesario modificar el trabajo de backup correspondiente al mismo, dentro de la configuración del Director de Bacula:
root@debian7:~# nano /usr/local/bacula/etc/bacula-dir.conf
El trabajo para el cliente "fbsd10" originalmente posee la siguiente configuración:
Job { Name = "BackupFBSD10" Client = fbsd10-fd JobDefs = "DefaultJob" }
Agregar la configuración RunScript
para que se corra el script /backup/scripts/bacula_pre.sh
, en el cliente, justo antes de que comience el trabajo de backup:
Job { Name = "BackupFBSD10" Client = fbsd10-fd JobDefs = "DefaultJob" RunScript { RunsWhen = Before FailJobOnError = Yes Command = "/backup/scripts/bacula_pre.sh" } }
La variable FailJobOnError
indica que el trabajo de backup debe fallar si el script finaliza con error. De esta forma, como el script se ejecuta antes del trabajo, si el script falla el trabajo directamente se cancela. Es posible modificar este comportamiendo seteando dicha variable en "No".
Para scripts que se deben correr después ("After") del trabajo de backup, Bacula tiene una configuración flexible que permite controlar si el script se debe correr o no en caso de que el trabajo de backup falle. Además es posible que el script se corra en el Director en lugar del cliente, si la variable RunsOnClient
se setea en "No". Si en vez de un comando genérico se desea correr un comando de la consola de Bacula, se debe especificar en la variable Console
(en vez de Command
).
Prueba
Inicialmente no existe el archivo "pre.txt" en el cliente:
root@fbsd10:/backup/scripts # ll /backup/ total 1 -rw-r--r-- 1 root wheel 0 Feb 11 2016 pepe drwxr-xr-x 2 root wheel 3 Nov 24 09:03 scripts/
En el servidor de backup, abrir la consola de Bacula:
root@debian7:~# /usr/local/bacula/sbin/bconsole
Ejecutar el comando run
para lanzar el trabajo de backup manualmente:
*run Automatically selected Catalog: MyCatalog Using Catalog "MyCatalog" A job name must be specified. The defined Job resources are: 1: BackupArchivosLocales 2: BackupFBSD10 3: BackupDebian 4: BackupCatalog 5: RestoreArchivosLocales 6: RestoreFBSD10
Seleccionar el trabajo correspondiente al cliente "fbsd10":
Select Job resource (1-6): 2 Run Backup job JobName: BackupFBSD10 Level: Incremental Client: fbsd10-fd FileSet: Full Set Pool: File (From Job resource) Storage: File1 (From Job resource) When: 2016-11-24 09:28:49 Priority: 10 OK to run? (yes/mod/no): yes Job queued. JobId=122
Se lanza el trabajo 122
. Luego de unos milisegundos, finaliza con éxito:
*list jobid=122 +-------+------------------+---------------------+------+-------+----------+----------+-----------+ | jobid | name | starttime | type | level | jobfiles | jobbytes | jobstatus | +-------+------------------+---------------------+------+-------+----------+----------+-----------+ | 122 | BackupFBSD10 | 2016-11-24 09:28:53 | B | I | 0 | 0 | T | +-------+------------------+---------------------+------+-------+----------+----------+-----------+
En el cliente, el script ha generado el archivo "pre.txt" correctamente:
root@fbsd10:/backup/scripts # cat /backup/pre.txt Probando, probando, probando... root@fbsd10:/backup/scripts # ll /backup/pre.txt -rw-r----- 1 root wheel 32 Nov 24 09:45 /backup/pre.txt
Más pruebas
Todo muy bonito, pero ¿qué pasa si el script falla?
Agregar una línea en el script para que trate de borrar un archivo inexistente:
rm /inexistente.doc
Volver a ejecutar el trabajo de backup:
*run A job name must be specified. The defined Job resources are: 1: BackupArchivosLocales 2: BackupFBSD10 3: BackupDebian 4: BackupCatalog 5: RestoreArchivosLocales 6: RestoreFBSD10 Select Job resource (1-6): 2 Run Backup job JobName: BackupFBSD10 Level: Incremental Client: fbsd10-fd FileSet: Full Set Pool: File (From Job resource) Storage: File1 (From Job resource) When: 2016-11-24 09:46:00 Priority: 10 OK to run? (yes/mod/no): yes Job queued. JobId=123
Se lanza el trabajo 123
, el cual falla:
*list jobid=123 +-------+------------------+---------------------+------+-------+----------+----------+-----------+ | jobid | name | starttime | type | level | jobfiles | jobbytes | jobstatus | +-------+------------------+---------------------+------+-------+----------+----------+-----------+ | 123 | BackupFBSD10 | 2016-11-24 09:46:04 | B | I | 0 | 0 | f | +-------+------------------+---------------------+------+-------+----------+----------+-----------+
Es posible comprobar qué ocurrió revisando los mensajes en la consola:
*messages 24-nov 09:46 debian7-dir JobId 123: Start Backup JobId 123, Job=BackupFBSD10.2016-11-24_09.46.02_04 24-nov 09:46 debian7-dir JobId 123: Using Device "FileStorage" to write. 24-nov 09:45 101amd64-quarterly-job-21-fd JobId 123: DIR and FD clocks differ by -40 seconds, FD automatically compensating. 24-nov 09:45 101amd64-quarterly-job-21-fd JobId 123: shell command: run ClientBeforeJob "/backup/scripts/bacula_pre.sh" 24-nov 09:45 101amd64-quarterly-job-21-fd JobId 123: ClientBeforeJob: rm: /inexistente.doc: No such file or directory 24-nov 09:45 101amd64-quarterly-job-21-fd JobId 123: Error: Runscript: ClientBeforeJob returned non-zero status=1. ERR=Child exited with code 1 24-nov 09:46 debian7-dir JobId 123: Fatal error: Bad response to RunBeforeNow command: wanted 2000 OK RunBeforeNow , got 2905 Bad RunBeforeNow command. 24-nov 09:46 debian7-dir JobId 123: Fatal error: Client "fbsd10-fd" RunScript failed. 24-nov 09:46 debian7-dir JobId 123: Error: Bacula debian7-dir 7.4.4 (28Sep16): Build OS: x86_64-unknown-linux-gnu debian 7.11 JobId: 123 Job: BackupFBSD10.2016-11-24_09.46.02_04 Backup Level: Incremental, since=2016-11-24 09:28:53 Client: "fbsd10-fd" 7.4.4 (28Sep16) amd64-portbld-freebsd10.1,freebsd,10.1-RELEASE-p40 FileSet: "Full Set" 2016-10-27 12:14:13 Pool: "File" (From Job resource) Catalog: "MyCatalog" (From Client resource) Storage: "File1" (From Job resource) Scheduled time: 24-nov-2016 09:46:00 Start time: 24-nov-2016 09:46:04 End time: 24-nov-2016 09:46:04 Elapsed time: 0 secs Priority: 10 FD Files Written: 0 SD Files Written: 0 FD Bytes Written: 0 (0 B) SD Bytes Written: 0 (0 B) Rate: 0.0 KB/s Software Compression: None Snapshot/VSS: no Encryption: no Accurate: no Volume name(s): Volume Session Id: 45 Volume Session Time: 1479161667 Last Volume Bytes: 30,283,033 (30.28 MB) Non-fatal FD errors: 2 SD Errors: 0 FD termination status: Error SD termination status: OK Termination: *** Backup Error ***
En la siguiente línea, se observa claramente el error provocado por el script:
24-nov 09:45 101amd64-quarterly-job-21-fd JobId 123: ClientBeforeJob: rm: /inexistente.doc: No such file or directory
El script finaliza con error:
24-nov 09:46 debian7-dir JobId 123: Fatal error: Client "fbsd10-fd" RunScript failed.
Por ende el trabajo finaliza con error (de acuerdo a la configuración del mismo):
Termination: *** Backup Error ***
Por más obvio que suene, cabe aclarar que cuando un trabajo finaliza con error no se genera una copia de seguridad.
Referencias
Configuring the Director - The Job Resource - Bacula ® Main Reference