openwrt: copia de seguridad y actualización

Dos scripts que he creado con mucho esfuerzo y que empleo para realizar copias semanales de la configuración y para actualizar con el mínimo de problemas.

Siguiendo lo descrito en la publicación anterior decidí dar forma al proceso de actualización y he escrito un pequeño programa que puede realizarla sin que salten errores por problemas de memoria y similares.

Ha sido costoso porque está escrito en un shell muy simple (busybox y ash) y como siempre en estos casos paso más tiempo asegurándome de que las variables tengan el valor adecuado (o un valor al menos) y de que los test sobre éstas y sobre los archivos funciones, así como que las redirecciones sean las necesarias y no termine con cualquier basura o texto vacío.

Es más, creo que cuando tengo que escribir un script en lenguaje de shell paso la mayor parte del tiempo asegurándome de que no se me puede ir por libre que por la propia lógica en sí. Pero en este caso es lo que hay y bastante es que funcione de manera regular.

El programa es el que muestro a continuación y que he instalado en el directorio /usr/local/bin junto con el de copias.

#/usr/bin/sh

VERSION=0.2
UPGRADABLE=/tmp/upgradable.$$.list
UPDATE_LOG=/tmp/upgradable.$$.log
HOST=portico.home
EMAIL_TO=root@taquiones.net
BACKUP=/usr/local/bin/backup.sh

#       Ajustes en uso de memoria
sysctl -w vm.overcommit_memory=1 2>&1 >/dev/null

#       Actualizamos lista de paquetes 
echo "Actualizando listas de paquetes ..."
opkg update

#       Lista de paquetes actualizables
echo "Comprobando si hay paquetes actualizables ..."
opkg list-upgradable | cut -d" " -f 1 > $UPGRADABLE

if [ $? -ne 0 ]; then
        echo "ERROR: opkg list-upgradable failed"
fi

#       Si hay alguno
TOTAL=$(wc -l $UPGRADABLE | cut -d" " -f 1)
if [ "$TOTAL" -gt 0 ]; then 
        # Antes de actualizar hacemos copia si podemos
        echo "Hay actualizaciones: copia de seguridad primero ..."
        if [ -x $BACKUP ]; then
                $BACKUP
        fi 

        # Procedemos a actualizar 
        echo "Actualizamos uno por uno ..."
        (
                for pkg in $(cat $UPGRADABLE)
                do
                        opkg upgrade $pkg
                done 
        )
        > $UPDATE_LOG
        echo "Enviando informe por correo a $EMAIL_TO ..." 
        ( 
                echo -e "Subject: [UPGRADE $HOST] $(date +%F)\n\n" 
                cat $UPGRADABLE
                echo -e "\n\n"
                cat $UPDATE_LOG
        ) | msmtp $EMAIL_TO

        rm -f $UPGRADABLE $UPDATE_LOG
else
        echo "No hay actualizaciones pendientes ..." 
fi

exit 0

Y su lógica es la siguiente:

  1. Modifica la gestión de memoria en el núcleo. No tengo muy claro si no estaré creando efectos secundarios pero no tengo otra manera todavía de que el resto no se mueran.
  2. Actualiza la lista de paquetes.
  3. Obtiene los paquetes actualizables.
  4. En caso de tenerlo y si tiene acceso al programa de copias realiza una. Este programa empaqueta y transfiere las copias a un servidor externo.
  5. Procede a actualizar uno a uno los paquetes y va guardando un registro de lo que ocurre en un archivo temporal.
  6. Envía el archivo temporal al administrador de la red explicando qué tenía que hacer y qué ha ocurrido.
  7. Limpia y finaliza.

El programa de copias está explicado ya en la entrada relativa al router. Aquí me limito a transcribir una versión parametrizada del mismo como referencia también:

#!/bin/sh

VERSION=0.2
BACKUP_FILE="/tmp/backup-$(cat /proc/sys/kernel/hostname)-$(date +%F).tgz"
HOST=portico.home
EMAIL_TO=root@taquiones.net 
COPY_TO="ocs@backup.home:domus/portico.home/"
TMP=/tmp/backup-$$.log

(
        # Lista de paquetes instalados
        opkg list-installed > /etc/config/installed.packages

        # Crear copia 
        sysupgrade -v --create-backup $BACKUP_FILE

        # Enviar copia a servidor 
        echo "Enviando copia a servidor externo ..." 
        scp $BACKUP_FILE $COPY_TO

        # Borrar copia 
        echo "Borrando copia $BACKUP_FILE"
        rm -f $BACKUP_FILE
) > $TMP

(
echo -e "Subject: [BACKUP $HOST] $(date +%F)\n\n" 


cat $TMP
) | msmtp $EMAIL_TO

rm -f $TMP

Me he asegurado de que el script upgrade.sh esté incluido en la lista de archivos extra que el programa de copias de openwrt y se llama /etc/sysupgrade.conf.

3 thoughts on “<span>openwrt: copia de seguridad y actualización</span>”

  1. Si usas {} en lugar de () para agrupar la salida de las operaciones, te evitas que se ejecuten en una subshell y eso ahorrará un pelín de memoria. Lo que no sé es si en una shell tan restringida como la de busybox eso está soportado (sí que es estándar POSIX).

Comments are closed.