Como Hacer Buenos Backups Usando Un Simple Script
Transcript of Como Hacer Buenos Backups Usando Un Simple Script
06/09/13 #!/bin/bash: De como hacer buenos backups usando un simple script(o KISS bakcup)
bourneagainshell.blogspot.mx/2009/02/to-backup.html 1/14
viernes, 20 de febrero de 2009
De como hacer buenos backupsusando un simple script(o KISSbakcup)
Supongamos un server recién instalado, llevó horas configurarlo,
dejarlo afinado como un violín, pero cuando creemos haber
terminado aún hay como una sensación, algo que no está bien,
pero... que será?
"Puede fallar" decía Tusam, y todos comprobamos la verdad de
estas sabias palabras alguna vez en la vida.
Pero...qué pude fallar?
short answer: "todo puede fallar"
Lo bueno es que muchas de las cosas son reemplazables, mother,
memorias, fuentes, discos se consiguen a buen precio hoy, pero
que hay de las horas de configuración?, los datos acumulados?, los
emails?, las bases de datos?
La posibilidad de que esa información valiosa se pierdan siempre ha
sido un itch to scratch.
-Indice
1- Objetivos
2- Requisitos
3- Desarrollo
3.1- Configuración
3.2- Setup inicial
3.3- Creando el backup
3.4- A prueba de errores
3.5- Mirror remoto
3.6- Check final
3.7- El script completo(backup.sh)
4- Invocando el script desde crontab
#!/bin/bashbash bits/random hacks
06/09/13 #!/bin/bash: De como hacer buenos backups usando un simple script(o KISS bakcup)
bourneagainshell.blogspot.mx/2009/02/to-backup.html 2/14
5- Ejemplo de salida
6- Conclusión
1- Objetivos
Hacer un script de backup que
sea tan simple de usar como poner una linea en cron
permita backup versionado en el tiempo
optimice el espacio de los backups
pueda hacer mirror remoto de los mismos
borre automaticamente los viejos para hacer espacio a los
nuevos
salga limpiamente de los errores que se puedan producir y
garantice la integridad
avise a alguien del error enviandole un detalle del fallo
que mientras funcione bien sea silencioso y pase
desapercibido
2- Requisitos
bash
tar
lftp
3- Desarrollo
Tener un itch to scratch nunca es garantía de que llegará el
scratch, ahí es cuando el cliente exijente aparece y de alguna
manera fuerza y/o financia el scratch:
cliente- muy bueno como quedó todo, ahora tengo
una pregunta, de esto hay backup?
geek- eh... sí, naturalmente, como no va a haber
backup!
Todo comenzó con un simple script para salir del paso, y a medida
que pasaron los años las necesidades de backup se volvieron cada
vez más complejas.
Varios checkpoints en el tiempo, mirror remoto, aviso en caso de
fallos, backups incremental fueron algunas de las exigencias, y el
pequeño script fue creciendo y evolucionando cada vez más.
3.1- Configuración
La primera parte del script está dedicada la configuración, esto es
lo que da al script flexibilidad.
06/09/13 #!/bin/bash: De como hacer buenos backups usando un simple script(o KISS bakcup)
bourneagainshell.blogspot.mx/2009/02/to-backup.html 3/14
Lo primero es elegir el directorio en donde se van a guardar los
backups, la ventaja de esto es que ese directorio puede caer en
un disco diferente al principal, o incluso puede ser una unidad de
red montada via smbfs o nfs por ejemplo.
view plain print ?
01. #!/bin/bash 02. # directorio donde van a parar los backups 03. backup_dir="/backup"
Luego viene la parte de remote mirror de los bakcups, el script usa
ftp para mantener en syncro el directorio de backups local con el
remoto. Si dejamos en blanco estas variables el script realiza solo
el backup en el directorio local.
view plain print ?
01. # datos ftp, si están en blanco el backup es sólo local
02. ftp_host=10.0.0.1 03. ftp_user=backup 04. ftp_pass=******
La siguiente variable nos pide el nombre de un usuario o un email
al cual enviar un aviso en caso de que el script falle en alguno de
sus pasos.
view plain print ?
01. # mail a donde avisar si algo sale mal, puede ser un usuario del sistema
02. mail_for_errors="root"
backup_days representa el numero de días de los cuales vamos a
tener backups, a mayor cantidad de días, más espacio en disco
necesitaremos.
view plain print ?
01. # tiempo en dias que conserva copia de los backups
02. backup_days=15
A continuación configuramos que cosas vamos a incluir y excluir
dentro del bakcup. En un backup completo tradicional incluiremos
el directorio raiz "/" y excluiremos cosas como /tmp,/proc y /sys
entre otros.
Hay que acordarse de excluir cualquier directorio que contenga
mucha información que pueda inflar innecesariamente los backups,
por ejemplo el cache de squid o el fuente de un kernel en /usr/src,
en fin,cosas que no vale la pena tener por duplicado.
Obviamente se excluye el $backup_dir para no crear una
06/09/13 #!/bin/bash: De como hacer buenos backups usando un simple script(o KISS bakcup)
bourneagainshell.blogspot.mx/2009/02/to-backup.html 4/14
recursividad tratando de backupear el propio directorio de
backups.
view plain print ?
01. exclude=$(mktemp) 02. include=$(mktemp) 03. cat > $include <<EOF 04. / 05. EOF 06. cat > $exclude <<EOF 07. /tmp/* 08. /sys/* 09. /proc/* 10. /var/spool/squid/* 11. $backup_dir 12. EOF
Después de esto comienza realmente el script, así que llegamos a
la linea divisoria, si estás buscando una solución Copy and Paste,
podés saltar todo esto y descargar el script completo
3.2- Setup inicial
Voy a explicar la solución paso a paso, en el orden de ejecución.
Para esto me voy a tomar la libertad de explicar las funciones
cuando son llamadas y no en el orden en que aparecen en el script
original.
Comenzamos creando un logfile donde redireccionar la stderr de
los programas que usamos a lo largo del script, para poder recopilar
los errores de los mismos y despues enviarlos por mail.
También creamos un directorio .tar, dentro de nuestro directorio
de bakcups. Este directorio lo usaremos para guardar el archivo
para backups incremental y unos lock que me aseguraran de que el
script pueda recuperarse de un fallo.
view plain print ?
01. # Scripts Begins Here 02. logfile=$(mktemp) 03. inc_dir="${backup_dir}/.tar" 04. inc_file="${inc_dir}/incremental.info" 05. [ -d "$backup_dir" ] || mkdir -p "$backup_dir" 06. [ -d "$inc_dir" ] || mkdir -p "$inc_dir"
El pŕoximo paso es borrar los backups que ya son viejos segun
$backup_days
view plain print ?
01. # borro los backups vencidos 02. find $backup_dir -name "backup-$(hostname)-*" -
ctime +$backup_days -a -type f -exec rm -f {} \;
06/09/13 #!/bin/bash: De como hacer buenos backups usando un simple script(o KISS bakcup)
bourneagainshell.blogspot.mx/2009/02/to-backup.html 5/14
En esta linea hago la primera comprobación de error. Cuando
comienzo a crear un backup completo, creo un archivo .lock, que
se borrará al final si todo sale exitosamente.
Pero si algo falla, entonces el archivo .lock permanece creado hasta
la próxima ejecución del script. Si encuentro ese archivo es porque
algo salío mal y sé que debo hacer nuevamente el backup completo
(full).
view plain print ?
01. # si encuentro .lock es porque fallo el full backup, borro inc_file para que se haga de nuevo
02. [ -f "${inc_file}.lock" -a -f "$inc_file" ] && rm -f "$inc_file"
El script maneja dos tipos de backup, full e incremental.
El backup full se realiza una vez a la semana, y es un backup de tar
autocontenido, que contiene toda la información necesaria para
ser usado y extraido en cualquier lugar.
El backup incremental se realiza a diario, y se usa como referencia
siempre el último backup full. Esto quiere decir que el lunes se
realiza un backup incremental teniendo en cuenta el último backup
full que es el del domingo. Y si quiciera restaurar el sistema al día
lunes debería primero extraer el backup full del domingo y luego
arriba de ese usar el del lunes.
Los backups incrementales son independientes, esto quiere decir
que están siempre hechos contra el último backup full, por lo que
si tengo un backup incremental del viernes y quiero restaurar el
sistema a ese día, entonces sólo necesito el último backup full
(domingo) más el incremental del viernes.
Esto está hecho así para asegurar la efectividad de los backups, ya
que si para poder recuperar el viernes dependiera de que el lunes,
martes, miércoles y jueves se hayan realizado con éxito estoy
siendo muy optimista por default.
Cada backup tiene su nombre, que incluye el hostname, indica si
es full o incremental y la fecha a la cual corresponde. En el caso de
los incrementales se usa unicamente el día de la semana para que
se vayan pisando con los anteriores y así tener sólo la última
semana en formato incremental.
view plain print ?
01. #setup full or incremental 02. if [ $(date +%u) -eq 7 -o ! -f "$inc_file" ];then 03. #backup-full 04. backup_name="${backup_dir}/backup-$(hostname)-
full-$(date +%Y-%m-%d).tar.gz" 05. #borro inc_file para que el backup sea full 06. [ -f "$inc_file" ] && rm -f "$inc_file" 07. touch "${inc_file}.lock"
06/09/13 #!/bin/bash: De como hacer buenos backups usando un simple script(o KISS bakcup)
bourneagainshell.blogspot.mx/2009/02/to-backup.html 6/14
08. else 09. #backup-inc 10. backup_name="${backup_dir}/backup-$(hostname)-
inc-$(date +%A).tar.gz" 11. cp $inc_file ${inc_file}.temp 12. inc_file=${inc_file}.temp 13. fi
3.3- Creando el backup
Finalmente una vez que todo está listo, hago el backup
view plain print ?
01. #finally, do the backup 02. tarme "$inc_file" "$backup_name"
tarme es una función, veamosla en detalle, lo que hace es invocar
a tar con ciertos parámetros especiales, como que archivos incluir
y excluir del backup, que preserve owners y permisos o que envíe
stderr a logfile.
view plain print ?
01. tarme() { 02. local inc_file=$1 file=$2 03. tar --listed-incremental="$inc_file" \ 04. --files-from="$include" \ 05. --exclude-from="$exclude" \ 06. --ignore-failed-read \ 07. --absolute-names \ 08. -
zpcf "$file" 2>$logfile || do_exit "tar" $? $file
09. return 0 10. }
3.4- A prueba de errores
Como se puede ver al final de la invocación de tar, hay un "||
do_exit ..."
do_exit es otra función, que la vamos a utlizar en caso de que algo
salga mal, en bash cuando un comando devuelve 0 es que todo fue
bien en su ejecución, en cambio si el valor es != de cero es que
algo salió mal. Al poner "|| do_exit" me estoy asegurando que si
algo sale mal la función do_exit se ejecute.
do_exit va a ser usado por tar pero también por otros comandos
que fallen, la idea es que haga un clenaup si el backup quedó
inconsistente y que envíe un mail al administrador avisando que
algo salío mal.
view plain print ?
01. do_exit() { 02. local app=$1 exit_status=$2 file=$3
06/09/13 #!/bin/bash: De como hacer buenos backups usando un simple script(o KISS bakcup)
bourneagainshell.blogspot.mx/2009/02/to-backup.html 7/14
03. case $app in 04. tar) #exit status 1 en tar no es un error fatal:
05. #If tar was given ‘--create’, ‘--
append’ or ‘--update’ option, 06. #this exit code means that some files were c
hanged while being 07. #archived and so the resulting archive does
not contain the 08. #exact copy of the file set. 09. [ $exit_status -eq 1 ] && return 10. #borro el backup que fallo xq esta incomplet
o 11. [ -n "$file" -a -f "$file" ] && rm -
f "$file" 12. ;; 13. esac 14. cat $logfile | mail -
s "Backup error host:$(hostname) app:$app exit_status:$exit_status file:$file" $mail_for_errors
15. exit 1 16. }
3.5- Mirror remoto
Luego de que tar corrio exitosamente, hacemos el upload remoto
si es que corresponde
view plain print ?
01. [ -n "$ftp_host" ] && uploadme "$backup_name"
uploadme es otra función, lo que hace es hacer un mirror del
directorio local de backups contra un ftp remoto, en este sentido
el comando mirror de lftp es de gran ayuda.
Lo bueno de esto es que la sincronía puede fallar un día, pero en
cuanto el script vuelva a correr el directorio local y remoto de
backups terminaran perfectamente sincronizados.
view plain print ?
01. uploadme() { 02. local file=$1 03. lftp -
c "open ftp://$ftp_user:$ftp_pass@$ftp_host;mirror -R --delete-first $backup_dir (hostname)" 2>>$logfile || do_exit "lftp" $? $file
04. return 0 05. }
3.6- Check final
Una vez subido el backup, entonces estamos en condices de borrar
el .lock file, si es que lo habiamos creado (sólo se usa para los full
backups)
view plain print ?
06/09/13 #!/bin/bash: De como hacer buenos backups usando un simple script(o KISS bakcup)
bourneagainshell.blogspot.mx/2009/02/to-backup.html 8/14
01. # si todo fue bien borro el .lock 02. [ -f "${inc_file}.lock" ] && rm -
f "${inc_file}.lock"
3.7- El script completo(backup.sh)
Descargar el script completo: backup.sh
4- Invocando el script desde crontab
Generalmente coloco el script en /usr/local/bin/backu.sh y luego
agrego esta linea a alguan crontab, puede ser la de root(crontab -
e) o en /etc/cron.d/ en alguan crontab personal.
La linea de cron es simplemente para ejecutarlo una vez al día
preferentemente en un horario de poco impacto para el servidor,
como son las horas de la madrugada
view plain print ?
01. 0 2 * * * root /usr/local/bin/backup.sh
5- Ejemplo de salida
Pego la salida de ls sobre un directorio de bakcups, en donde se
han acumlado tres semanas.
Como se puede observar hay una gran diferencia de tamaño entre
un backup full y uno incremental. También se ve como los
incrementales solo cubren la primer semana y luego quedan sólo
full 3 semanas hacia atras.
view plain print ?
01. -rw-r--r-- 1 root root 1.4G 2009-04-19 03:16 backup-sequre-0001-full-2009-04-19.tar.gz
02. -rw-r--r-- 1 root root 1.3G 2009-04-26 03:15 backup-sequre-0001-full-2009-04-26.tar.gz
03. -rw-r--r-- 1 root root 16M 2009-04-27 03:02 backup-sequre-0001-inc-Monday.tar.gz
04. -rw-r--r-- 1 root root 16M 2009-04-28 03:02 backup-sequre-0001-inc-Tuesday.tar.gz
05. -rw-r--r-- 1 root root 30M 2009-04-29 03:02 backup-sequre-0001-inc-Wednesday.tar.gz
06. -rw-r--r-- 1 root root 30M 2009-04-30 03:02 backup-sequre-0001-inc-Thursday.tar.gz
07. -rw-r--r-- 1 root root 30M 2009-05-01 03:02 backup-sequre-0001-inc-Friday.tar.gz
08. -rw-r--r-- 1 root root 50M 2009-05-02 03:02 backup-sequre-0001-inc-Saturday.tar.gz
09. -rw-r--r-- 1 root root 1.3G 2009-05-03 03:16 backup-sequre-0001-full-2009-05-03.tar.gz
6- Conclusión
Tener backups es garantía de buen sueño para un sys-admin y, es
además, una marca de calidad en lo que a infraestructura respecta.
06/09/13 #!/bin/bash: De como hacer buenos backups usando un simple script(o KISS bakcup)
bourneagainshell.blogspot.mx/2009/02/to-backup.html 9/14
Si bien hay soluciones de backup muy interesantes como bacula o
backuppc, hay escenarios en donde no se justifica hacer
semejante despliegue de configuración e infraestructura.
Escenarios donde lo único que necesitamos es tener una copia
fresca y con archivo de un servidor, en donde dedicar más de 5
miutos de setup sería perder tiempo y dinero.
Este script hace que tener backups sea algo sencillo de
implementar, sin descuidar la calidad de los resultados, así que ya
no hay más excusas para tener un sólo server sin backup.
Good luck and good backups :)
Etiquetas: backup , incremental , linux , mirror , script , tar
Publicadas por luciano This entry was posted on viernes, 20 de febrero de
2009 a la/s 12:38 You can skip to the end and leave a response.
13 comentarios:
Alejandro L dijo... 14 de junio de 2009 19:28
Hola Amigo.. muy bune post.. voy aimplementarlo te cuento
Modemhead dijo... 23 de junio de 2009 12:36
Muy bueno! Es mas de lo que estaba buscando:O
Segui así con el blog q esta muy groso!
saludos
Eduard4D dijo... 6 de julio de 2009 07:32
Buenas , primero de todo, muchas gracias, eraexactamente lo que buscaba, pero me aguarda
06/09/13 #!/bin/bash: De como hacer buenos backups usando un simple script(o KISS bakcup)
bourneagainshell.blogspot.mx/2009/02/to-backup.html 10/14
una duda, la primera vez q he ejecutado elscript, este me hace uno completo. SI quiero qvaya haciendome incrementales como debollamar al script?
GraciasEduard
luciano dijo... 8 de julio de 2009 10:35
@Eduard4D la primera vez siempre hace unbackup full porque es imposible hacerincrementales si no hay uno completo dereferencia.El script se llama siempre igual, sin ningunparametro especial. La inteligencia internadel mismo hará backups incrementales hastallegar al día 7 de la semana(domingo) donderealizara un nuevo backup completo y asíempezar de nuevo.
kbs dijo... 20 de julio de 2009 16:27
muy buen script amigo
una pregunta, el backup incremental se basasolamente en si el archivo existe o no? se dacuenta si yo modifico el archivo para meterloen el nuevo backup?
Por ejemplo, yo tengo un directorio con elarchivo "hola" está vacio, el dia 1 hago unbackup full, el segundo dia yo escribo algo enel archivo "hola", el backup incremental se dacuenta que el archivo es diferente?
Ing. Sabas Medina Morales dijo... 13 de diciembre de 2011 14:19
Excelente el script. Me gustaria saber que
06/09/13 #!/bin/bash: De como hacer buenos backups usando un simple script(o KISS bakcup)
bourneagainshell.blogspot.mx/2009/02/to-backup.html 11/14
variaciones debo hacerle si quiero hacerbackups de los switches cisco de la empresadonde trabajo. De antemano gracias
luciano dijo... 13 de diciembre de 2011 17:05
@SabasEs muy distinto hacer backups de switchs orouters ya que cada uno tendrá una maneradistinta de acceder al dump. Para ciscoespecificamente google siempre te dara unamano
Anónimo dijo... 22 de junio de 2012 00:28
buenas noches. la verdad me gusto el codigopreo tengo 2 pregunta :
una es que no me envia notificaciones a micorreo}y la otra es que quisiera saver si sepuede reducir la comprencion mas
Javier Lleo Tomás dijo... 28 de septiembre de 2012 06:11
Estaba buscando algo sencillo y efectivo, estescript encaja a la perfección.
Muchas gracias por el articulo y lasexplicaciones, muy bueno.
un saludo.
Daniel Diaz dijo... 29 de noviembre de 2012 21:15
06/09/13 #!/bin/bash: De como hacer buenos backups usando un simple script(o KISS bakcup)
bourneagainshell.blogspot.mx/2009/02/to-backup.html 12/14
Muy bueno lo implemente y me va demaravillas.Ahora soy muy limitado en linux, mi duda es.Como restauro uno de estos backups??ejemplo, tengo como el ls que muestras, estoyen el dia viernes y quiero restaurar el backupdel dia miercoles, como hago eso?Saludos a la distancia!
luciano dijo... 29 de noviembre de 2012 22:03
Para resutaurar usas el comando tar.Siempre debes restaurar primero uno de losbackup full, y luego basta con un únicoincremental del día al que quieras llegar. Elcomando sería algo asítar --numeric-owner -zxpvf backup.tar.gz
Daniel Diaz dijo... 4 de diciembre de 2012 17:50
sigo sin entender perdon, podrias ser masgrafico? tengo estos archivos: backup-mdh-full-2012-12-02.tar.gzbackup-mdh-inc-sábado.tar.gzbackup-mdh-inc-lunes.tar.gzbackup-mdh-inc-martes.tar.gzbackup-mdh-inc-miercoles.tar.gz
Supongamos que estoy a viernes y quierorestaurar el incremental del dia martes. Comohago esta operacion?Gracias y disculpa las molestias.
Anónimo dijo... 11 de marzo de 2013 18:55
hola como puedo hacer un scrips linux, que mepermita copiar el contenido de varios archivoslogs. y ubicarlos en uno solo....automaticamente cada 5 minutos ......
06/09/13 #!/bin/bash: De como hacer buenos backups usando un simple script(o KISS bakcup)
bourneagainshell.blogspot.mx/2009/02/to-backup.html 13/14
Entrada antiguaEntrada más reciente
tomando en cuent que los archivos semodifican constantemente ....
Publicar un comentario
Página Principal
Suscribirse a: Comentarios de la entrada (Atom)
Luciano Ruete's Profile
Create Your Badge
Work
Labels
linux (2)
adsl (1)
backup (1)
failover (1)
incremental (1)
load balancing (1)
mirror (1)
06/09/13 #!/bin/bash: De como hacer buenos backups usando un simple script(o KISS bakcup)
bourneagainshell.blogspot.mx/2009/02/to-backup.html 14/14
multipath (1)
script (1)
tar (1)