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


Tal vez pueda interesarte


Compartí este artículo