Cuando empecé a estudiar informática, una de las tareas que menos me atraían era la de desarrollo web, me estoy refiriendo al desarrollo web a palo seco (HTML, javascript, CSS y algo de PHP). Siempre me ha gustado más programar en C/C++ o incluso acostumbrarme a la “facilidad” de hacer las cosas en Java. Tener un IDE completo que te ayude a desarrollar tus aplicaciones, con un buen System.out.println(variable); debugger, un sistema de documentación completo como javadoc o doxygen. Sin embargo, una vez que estás trabajando te tienes que amoldar a las situaciones que te vas encontrando. Al final me ha tocado mantener/desarrollar un portal web basado en Joomla junto con otros compañeros.

Para desarrollar tranquilo, me parece una buena práctica hacer tus modificaciones en el software de una máquina de pruebas y luego desplegarlo en el entorno final de producción. Además, al no desarrollar solo, no sabes si algo de lo que estás tocando puede estropear el código de otros compañeros…

Creo que la mejor forma de conseguir un entorno de desarrollo productivo sin muchas complicaciones del que se puedan extraer snapshots o backups automáticos es hacer uso de varias herramientas de las que disponemos en GNU/Linux: los scripts en Bash, el SSH y CRON. Voy a pegar y comentar el script que utilizo para desplegar periódicamente el portal web de la máquina de desarrollo y pruebas al entorno de producción. Pero antes, he de comentar cómo hacer un ssh sin necesidad de teclear la contraseña.

La idea es que hay que copiar la clave pública del usuario que queremos utilizar (está en $HOME/.ssh/id_*.pub, siendo * el algoritmo utilizado en la creación de la clave, comúnmente RSA o DSA) en el archivo $HOME/.ssh/authorized_keys de la máquina destino. Dicha clave pública se puede pasar por SCP o utilizando un disco duro externo al ordenador de destino. En este caso hipotético, voy a utilizar la clave del ordenador de desarrollo del usuario root para poder hacer ssh sin contraseña a la máquina “servidor” con el usuario abian:

root@desarrollo:~# scp /root/.ssh/id_dsa.pub abian@serverhosting:/home/abian/

abian@serverhosting:~$ cat id_dsa.pub >> .ssh/authorized_keys

Ahí va el script. Lo podéis guardar en un archivo de texto plano llamado “backup_automatico.sh“. No hay que olvidarse de dar los permisos de ejecución a este nuevo archivo utilizando chmod +x backup_automatico.sh:

#!/bin/bash
#Directorio en el que se irán guardando los backups
BACKUPS_FOLDER=/home/abian/bakcups_web/
#si el directorio no existe lo creamos
[ -d “$BACKUPS_FOLDER” ] || mkdir $BACKUPS_FOLDER
#borrar los backup viejunos para no ocupar tanto espacio en el servidor destino
ssh abian@hostingserver ‘rm -rf /home/abian/backups_web/*’
#Paro el apache
/etc/init.d/apache2 stop
#me quedo con la fecha de hoy
DATE=$(date +%d_%m_%Y)
#creo el backup
tar cfj $BACKUPS_FOLDER/web_$DATE.tar.bz2 /var/www/web/
#arranco de nuevo el apache
/etc/init.d/apache2 start
#copiar este último backup al hosting y descomprimirlo
scp $BACKUPS_FOLDER/web_$DATE.tar.bz2 abian@hostingserver:/home/abian/backups_web/
ssh abian@hostingserver ‘cd /home/abian/backups_web/ && tar xfj web_*.tar.bz2’
#algunos datos de la configuración del MySQL
HOST=localhost
USER=root
PASS=changeme
DB=database
#utilizo mysqldump para hacer el volcado de la base de datos a un fichero
mysqldump –add-drop-database -h $HOST -u $USER -p$PASS –databases $DB > $BACKUPS_FOLDER/web_$DATE\_$DB\_full_schema.sql
#el archivo sql puede ocupar mucho a sí que lo comprimo

bzip2 -f $BACKUPS_FOLDER/web_$DATE\_$DB\_full_schema.sql
#lo copio al hosting
scp $BACKUPS_FOLDER/web_$DATE\_$DB\_full_schema.sql.bz2 abian@hostingserver:/home/abian/backups_web/
#Parar el apache remoto
ssh
abian@hostingserver ‘/etc/init.d/httpd stop’
#restaurar los archivos del portal web
ssh
abian@hostingserver ‘rm -rf /var/www/web/*’
ssh
abian@hostingserver ‘mv /home/abian/backups_web/var/www/web/* /var/www/web/’
#arreglar el owner de los archivos por si acaso
ssh
abian@hostingserver ‘chown -R www-data.www-data /var/www/web/’
#restaurar el backup del mysql
ssh abian@hostingserver ‘bunzip2 /home/abian/backups_web/*.sql.bz2’
ssh abian@hostingserver ‘mysql -h 127.0.0.1 -u root -pchangeme schema_destino < /home/abian/backups_web/*.sql &’
#reiniciar el servidor web remoto
ssh abian@hostingserver ‘/etc/init.d/httpd start’
exit

Ahora que tenemos el script preparado, hay que añadirlo al cron para que lo ejecute cada cierto tiempo utilizando el comando crontab -e añadiendo la siguiente línea:

#Minuto hora dia_del_mes mes dia_de_la_semana   comando
0 4 * * 5 /root/backup_automatico.sh

Al hacer un crontab -l se puede ver qué trabajos tenemos en agenda. En mi caso tan solo tengo este trabajo que se ejecutará todos los viernes a las 4:00 de la madrugada:

root@server:~# crontab -l
# m h  dom mon dow   command
#ejecutar el backup todos los viernes a las 4:00 de la mañana
0 4 * * 5 /root/backup_automatico.sh

¿Algunas consideraciones extras?

  • Para no tener problemas de privilegios o configuraciones raras de usuarios y no hacer este post más largo. La clave pública que realmente hipotéticamente exporto al hosting es la clave pública del root (noto como Ramiro está gritando “Noooooooooooooo…”).
  • La máquina de pruebas es un ubuntu server, por lo que se utiliza el comando /etc/init.d/apache2 stop|start mientras que la máquina destino es un CentOS, por lo que se utiliza el comando /etc/init.d/httpd stop|start.
  • El directorio en el servidor remoto /home/abian/backups_web/ debe existir para que el script funcione.
  • Con unas cuantas modificaciones personales se puede adaptar este script para que haga el backup de lo que cada uno quiera.
  • Me queda un poco la sensación de que he mezclado muchas cosas en este post. Tal vez lo podría haber partido en varios para hacerlo más digerible. Pero si habéis seguido mis entradas anteriores, he explicado muchas cosillas que os pueden venir bien. Configuración de un servidor MySQL, SSH o utilidades del cliente ssh. Seguro que con algo de ayuda de la Wikipedia o Google todo el mundo puede entenderlo.

Espero que os haya gustado. Un saludo.