Automatización de backups de WordPress

Por jueves, 1 diciembre, 2016 0 , Permalink

En este post vamos a seguir con la serie automatización para ver como realizar un backup de la instalación de WordPress. Conviene realizar backups de manera periódica, por lo que seria conveniente planificar con qué frecuencia se realizan, para automatizar también la ejecución del script de backup. Quiero recordar que estos scripts de la serie van en conjunto, es decir, que hay que tener instalado WordPress con el script del primer post de esta serie, que podéis leer aquí.

La copia de seguridad será almacenada en un directorio de un servidor remoto, los cuales serán definidos en un archivo junto con otros parámetros.

Usaremos algunas funciones que ya fueron explicadas en el post sobre el script de la desinstalación con los mismo objetivos:

  • iferror. Utilizada para detener la ejecución el script con un mensaje diciendo en qué parte de la ejecución ha fallado
  • read_root_path.  Utilizada para definir el directorio root de la instalación que respaldamos.
  • get_config_parameters. Utilizada para definir los parámetros para acceder a la base de dato.

Para leer estas tres funciones podéis consultar el post de la desinstalación o visitar mi repositorio en Github desde aquí.

Para la ejecución de este script necesitaremos un archivo con los siguientes parámetros:

  • Nombre de dominio de la instalación a respaldar.
  • Usuario remoto de backup. El usuario que tendrá permisos para escribir en el directorio de almacenamiento.
  • IP o FQDN del host remoto.
  • Directorio remoto para almacenar la copia de respaldo, que será una copia con fecha de la base de datos y archivos.
domain=torestore.org
backup_user=gustavo	
backup_host=192.168.1.254
backup_remote_dir=backup

La primera función específica de este script es mysql_dump. Esta función utiliza los datos leídos con get_config_parameters para acceder a la base de datos con las tablas de la instalación de WordPress y envía una copia al directorio definido en el archivo de parámetros mediante una conexión ssh. El script crea un directorio con nombre igual al nombre de dominio de la instalación en el host remoto de backups:

# function: mysql_dump
# Produces a backup of full database in a tar.gz file

function mysql_dump {
  ssh $backup_user@$backup_host "mkdir -p $backup_remote_dir/$domain"
  mysqldump --user $db_user --password=$db_password  \
  $db_name | gzip -c | ssh $backup_user@$backup_host "cat > \
  $backup_remote_dir/$domain/$(date +%Y%m%d)$db_name.sql.gz" \
  || iferror "Backup for database named $db_name has failed" \
  && wp_simple_backup_files;
}

La función wp_simple_backup_files realiza una copia de todo el directorio raíz de WordPress. «Todo» quiere decir que también hace un respaldo del directorio upload, dónde están las imágenes y otros archivos que pueden tener un gran peso. Los archivos son comprimidos y empaquetados con una nomenclatura que incluye la fecha en el nombre del archivo. La copia será enviada con el comando scp al host remoto:

# function: wp_simple_backup_files
# Produces a tar.gz to a remote host

function wp_simple_backup_files {
  wp_targz="/tmp/$(date +%Y%m%d)$domain.tar.gz";
  if [[ -d $wp_path ]]; then
    tar czfp $wp_targz -C $wp_path . \
    && scp $wp_targz $backup_user@$backup_host:$backup_remote_dir/$domain/. \
    && rm -f $targz_file \
    || iferror "Backup file not sended to $backup_host"
  fi
}

La función nginx_site_backup hace una copia del servidor virtual de Nginx que usa la instalación de WordPress y la envía al directorio del backup:

# function: nginx_site_backup
# Produces a file with Nginx configurarion of the given server

function nginx_site_backup {
  if [[ -e /etc/nginx/sites-enabled/$domain.conf ]]; then
    scp /etc/nginx/sites-enabled/$domain.conf \
    $backup_user@$backup_host:$backup_remote_dir/$domain/.
  fi
}

Como en scripts anteriores de la serie, el script de backup también comprueba que lo haya ejecutado el usuario root y que exista el archivo de parámetros:

if [[ -e ./params/backup.conf ]];then
 		source ./params/backup.conf;
else
    iferror "First you need configure parameters";
fi

if [ "$(id -u)" != "0" ]; then
  echo "This script must be run as root" 1>&2
  exit 1
fi

La funcion start, que es llamada para iniciar el programa:

function start {
 read_root_path \
 && get_config_parameters \
 && mysql_dump \
 && nginx_site_backup
}

El script que he explicado en este post puede lanzarse desde cron para planificar la ejecución de las copias de respaldo. En el siguiente post veremos como restaurar la copia de seguridad. Al haber copiado el blog entero y la configuración servidor virtual, para restaurar la copia no habrá que instalar necesariamente otro WordPress y ambos scripts pueden ser muy útiles para realizar migraciones. Aunque todo eso lo veremos en el próximo post.

Hasta entonces.

Automatización de la desinstalación de WordPress

Por miércoles, 23 noviembre, 2016 0 , Permalink

El segundo post de la serie sobre automatización trata sobre la desinstalación de un servidor WordPress que fue instalado con el script que explicamos en el post anterior de la serie. Con otras instalaciones es muy probable que este script de desinstalación no funcione sin modificaciones.

El script de desinstalación no utiliza ningún archivo de configuración. Tan solo requiere un parámetro al lanzar el script, el cual debe ser el nombre del dominio del servidor que vamos a desinstalar. El script funciona en local.

Como en el script anterior, tenemos las función iferror que, en caso de que sea llamada, sale de script con un mensaje.

# function: iferror
# produces an exit code 1 with message
function iferror {
  if [[ $? -eq 1 ]]; then
    echo $1; exit 1;
  fi
}

Justo al iniciarse la ejecución, comprueba que el administrador haya introducido un parámetro.

if [[ $# -eq 0 ]]; then
  echo "You must enter a FQDN as parameter. \
  Example: ./uninstall_wordpress.sh yourdomain.org"; exit 1;
else
  domain=$1
fi

Esta comprobación aún requiere mejoras. Si el parámetro no es un nombre de dominio, el script terminará su ejecución antes de hacer modificación alguna, cuando no encuentre el dominio para ser desinstalado.

A continuación, comprueba que el usuario que ha lanzado el script sea root.

if [ "$(id -u)" != "0" ]; then
  echo "This script must be run as root" 1>&2
  exit 1
fi

A partir del nombre de dominio introducido como parámetro, el script encuentra el directorio dónde WordPress está instalado:

# function: read_root_path
# Read root path from Nginx server

function read_root_path {
    if [[ -e /etc/nginx/sites-available/$domain.conf ]];then
          wp_path=$(grep -E "root.*$domain" /etc/nginx/sites-available/$domain.conf \
          | awk -F' ' '{print substr($2, 1, length($2)-1)}');
    else
         iferror "Site is not available";
    fi
}

Para ello lee el archivo de configuración del servidor en Ngnix y almacena el directorio en la variable wp_path

Conociendo la ruta en la que se encuentra la instalación, es posible leer el archivo wp-config.php adecuado.

# function: get_config_parameters
# Read wp-config.php to get parameters needed to uninstall

function get_config_parameters {
  wp_cnf=$wp_path/wp-config.php

  db_name=$(grep "DB_NAME" $wp_cnf | awk -F"'" '{print $4}')
  db_user=$(grep "DB_USER" $wp_cnf | awk -F"'" '{print $4}')
  db_password=$(grep "DB_PASSWORD" $wp_cnf | awk -F"'" '{print $4}')
  db_host=$(grep "DB_PASSWORD" $wp_cnf | awk -F"'" '{print $4}')
  if [[ $db_host == '' ]]; then
      db_host=localhost
  fi
}

Define las variables con el nombre de la base de datos, junto usuario y password de la misma, además del host en la que está funcionando.

Con esos datos, podemos proceder. Siguiente paso, el script elimina la base de datos:

# function: mysql_remove_database
# Remove database from mysql

function mysql_remove_database {
   SQL="drop database if exists $db_name;";
   mysql -u$db_user -p$db_password -e "$SQL" || iferror "Database not removed";
}

Ejecuta una sentencia Mysql con las variables que hemos definido antes. Esta función eliminará la base de datos y no será posible recuperarla sin no hay alguna copia en algún otro lugar. En el siguiente post de la serie, publicaré un script para automatizar backups de todo el sitio y enviarlos a un host remoto.

La siguiente función, elimina el directorio raíz del sitio de WordPress:

# function: remove_root_path
# remove path of WordPress installation

function remove_root_path {
  if [[ -d $wp_path ]]; then
    rm -rf $wp_path;
  else
    iferror "Root path does not exists"
  fi
}

La siguientes dos funciones, eliminan el servidor de Nginx. La primera de ellas deshabilita el servidor borrando el enlace simbólico; la segunda, elimina la disponibilidad del servidor.

# function: nginx_disable_site
# disable site from sites-enabled

function nginx_disable_site {
  if [[ -e /etc/nginx/sites-enabled/$domain.conf ]]; then
      rm -f /etc/nginx/sites-enabled/$domain.conf;
      systemctl reload nginx;
  else
      iferror "Site is not enabled"
  fi
}

#function nginx_remove_site
# remove server from sites-available

function nginx_remove_site {
  if [[ -e /etc/nginx/sites-available/$domain.conf ]]; then
      rm -f /etc/nginx/sites-available/$domain.conf;
  else
      iferror "Site is not available "
  fi
}

La función start ejecuta la funciones en serie.  Una función a las que llame esta función no se ejecuta si la función anterior no se ha ejecutado con éxito, a excepción de la primera de ellas.

function start {
  read_root_path \
  && get_config_parameters \
  && mysql_remove_database \
  && remove_root_path \
  && nginx_disable_site \
  && nginx_remove_site
}

Por último, tan sólo hay que llamar a la función start para ejecutar todo el script.

Todos los scripts de esta serie relacionados con WordPress están en mi github.

Saludos 🙂

Automatización de la instalación de WordPress

Por martes, 15 noviembre, 2016 0 , Permalink

Éste será el primero de una serie de posts sobre automatización en varios lenguajes de scripting. En este post expongo una automatización para instalación de WordPress, con un backend de MariaDB y PHP 7.0, en una distribución Debian Jessie. En próximas entregas desgranaré scripts de desinstalación, backup y restauración de la instalación realizada con este script.

Continuar Leyendo…

Cómo publicar calendarios Owncloud en WordPress sin plugin premium

En este artículo explico como me las he ingeniado para importar calendarios Owncloud, versión 9, hacia un WordPress 4.5 en un sistema GNU/Linux, aunque es probable que funcione en otros sistemas. Ningún pluguin gratuito de WordPress importa calendarios de Owncloud y los renderiza a día de hoy. Hasta hace poco lo hacía el pluguin All-in-one Event Calendar, pero una incompatibilidad con las últimas actualizaciones de WordPress han dejado tal característica fuera de combate. Sin embargo, este pluguin sí puede importar archivos ICS desde otro lugar de manera periódica y renderizarlos.

Para importar los calendarios al mismo servidor donde tengo el WordPress, y mantenerlos actualizados y accesibles, he creado un script el cual Cron debe ejecutar cada cierto periodo de tiempo.

En el script que publico, los calendarios importados estarán en la carpeta /uploads/calendarios de la instalación del WordPress, catalogados por usuario y el mismo nombre de calendario del Owncloud. En el plugin All-in-one Event Calendar, será necesario especificar la url de cada calendario importado, por ejemplo:

http://miservidorwordpress.com/wp-contents/uploads/calendarios/usuario/calendario.ics

Cada calendario es importado por el script al que llamo importICS.sh

#!/bin/bash
importICS () {
    URL="http://"$DOMAIN
    dest_dir_root="/var/www/wordpress/wp­-content/uploads/calendarios/"
    dir=$dest_dir_root$CALUSER
    [[ -d $dir ]] || mkdir $dir
    wget ­O $dir/$CALENDAR".ics" ­­auth­-no­-challenge ­­http­-user=$CALUSER ­­http­-password=$CALPASS $URL"/remote.php/dav/calendars/"$CALUSER"/"$CALENDAR"?export";
}
file=$1
while IFS=, read CALUSER CALPASS CALENDAR DOMAIN
do
    importICS
done < $file

El script lee un archivo CSV, delimtiado por comas, del que toma los datos del usuario y calendario a importar del owncloud. Tiene un formato como este:

usuario1,123456,cal1,urlowncloudmidominio.com
usuario1,123456,cal2,urlowncloudmidominio.com
usuario2,123456,tres,urlowncloudmidominio.com

El primer campo es el nombre del usuario del calendario, el segundo su password, el tercero el nombre del calendario y el cuarto el dominio del owncloud.

Este archivo puede editarse fácilmente con una hoja de cálculo y exportarse como CSV delimitado por comas.

Cron ejecuta el script periódicamente para mantener los calendarios actualizados y, en condiciones normales, sólo habrá que hacer cambios esporádicos en el archivo CSV, pero por si se quiere actualizar los calendarios a mano, el script se ha de lanzar con un sólo parámetro: el nombre del archivo CSV. Por ejemplo:

$ sudo bash /opt/ICS/importICS.sh calendarios.csv

Por último, tan sólo hay que añadir la tarea al Cron para que ejecute el script con la frecuencia deseada y con ello ya tenemos los calendarios accesibles para el pluguin All-in-one Event Calendar.

No es imprescindible que los calendarios exportados desde Owncloud tengan como destino la misma máquina donde está instalado Worpress, sino que con algunas modificaciones al script pueden almacenarse en cualquier directorio al que tenga acceso el pluguin. También sería muy deseable añadir certificado SSL, aunque no lo he hecho pues ambas máquinas en mi caso se encuentran en el mismo segmento de red y no viajarán esos datos por Internet. Ténganse en cuenta también que en muchos casos los archivos ICS importados serán de acceso publico, por lo que el servidor donde estén alojados podría requerir configuraciones adicionales para limitar el acceso.

Espero que este artículo sea de utilidad.

Listar archivos de directorio remoto en WordPress con Linux

Por miércoles, 2 marzo, 2016 0 Permalink

Cuando sea necesario listar contenidos de carpetas compartidas en una intranet con WordPress, hay algunas posibilidades. Una de ellas es cargar el recurso compartido con enlaces con un aspecto similar a éste -> file://FileServer/Public

El problema de cargar el directorio remoto con el protocolo file:// es que para muchos navegadores son necesarios instalar plugins en cada uno de ellos. Es una solución válida, pero requiere instalar los plugins en cada navegador de los ordenadores que utilicen la intranet, lo que podría ser un dolor en redes de gran tamaño.

Otra opción es montar el directorio remoto con cifs en un punto de montaje del host virtual dónde está la instalación del WordPress. De ese modo, WordPress podrá acceder a los archivos remotos a través de los enlaces en la máquina local como si estuvieran físicamente en ésta.

Para mostrar el contenido de un directorio local como contenido de un post o página existe el plugin m1DownloadList.

Preparativos

Si no tenemos cifs, lo instalamos:

$ sudo apt install cifs-utils

Tenemos en una máquina remota una carpeta compartida SMB con permisos de solo lectura llamada \\SRVFILE\Public con credenciales para el usuario gato con el password Pajaro

Vayamos primero a instalar los paquetes necesarios en el servidor Linux. Este post está escrito pensando en Debian y derivadas, pero en otras distribuciones será muy, muy parecido.

Supongamos que tenemos el host virtual en la ruta:

/srv/wordpress/intranet

Entonces, creamos un directorio dentro de esa ruta:

$ sudo mkdir /srv/wordpress/intranet/srvfile

Credenciales

Creamos en el servidor donde está alojado el WordPress un archivo con las credenciales cifs, llamado /etc/smbcredentials, con el suguiente contenido:

username=gato
password=Pajaro

Interesa que el contenido de este archivo sea leído por el mínimo número de usuarios posible, lo ideal sería que sólo lo lea root en los sitemas Debian o el usuario con permisos de administración de distribuciones Ubuntu. Como regla general, sería de ayuda establecer estos permisos:

$ sudo chmod 500 /etc/smbcredentials

Montaje automático al arranque

En el archivo /etc/fstab están definidas las particiones que se montarán en el sistema de archivos al inicio del sistema, además de comparticiones remotas.  Las particiones y las shares «se montan» (en el argot linuxero) en cualquier punto del árbol de directorios, lo que equivaldría a decir que las carpetas compartidas pueden mapearse hacia cualquier lugar. Es en la ruta /srv/wordpress/intranet/srvfile donde montaremos el recurso compartido.

Editamos el archivo /etc/fstab con permisos de escritura:

$ sudo vi /etc/fstab

Calma: si no te gusta Vi, puedes usar Emacs, Nano o aquel con el que te sientas mas cómodo 😉

y añadimos la siguiente línea:

//SRVFILE/Public     /srv/wordpress/intranet/srvfile     cifs     credentials=/etc/smbpasswords       0     0

Hay mas opciones, claro; para ello te dejo que consultes las páginas man y lo tunees al pelo según tus necesidades 🙂

Para comprobar que esté todo bien, no es imprescindible reiniciar. Podemos montar la carpeta compartida con el comando:

$ sudo mount -a

Lo que montará toda la tabla de sistemas de archivos del /etc/fstab

Si todo ha ido bien, veremos los archivos compartidos con el comando:

$ ls /srv/wordpress/intranet/srvfile

Plugin de WordPress M1 Download List

Se trata de un plugin para listar directorios locales sin subirlos con la interfaz de WordPress.

Su uso es muy sencillo; tras activar el plugin, basta crear una página o artículo con un shortcode definiendo en él la ruta local a partir del directorio raíz del host virtual.

Como indican las instrucciones del plugin, para visualizar el recurso compartido anteriormente es suficiente con introducir este shortcode:

[m1dll path="srvfile/"]

Y saldrá algo como esto:

m1downloadlist

Es posible que tengas que configurar el juego de caracteres para que se visualicen los acentos y eñes, pero eso vendrá más adelante.