Apartamento En Familia

Apartamento En Familia
Apartamento de playa para vacaciones. http://www.apartamentoenfamilia.es. Número registro HUTT-005768

jueves, 17 de abril de 2014

Ejecutando en paralelo en bash (ejemplo con rsync)


xargs es un programa incluido en el paquete findutils. Con xargs podemos construir y ejecutar lineas de comando provinientes de la entranda estandard.
xargs nos permite lanzar procesos en paralelo mediante su parámetro -P, el cual nos permite definir el número de procesos paralelos a lanzar al mismo tiempo (equivalente a --max-procs).
Este programa ya viene instalado por defecto en la mayoría de distribuciones y suele resultar muy útil.

Por otro lado tenemos a GNU parallel. La definición de las manpages es muy similar a la de xargs, si bien ya nos deja claro de inicio que es un programa diseñado para ejecutar comandos en paralelo. No vienen instalado por defecto en Ubuntu.

Hay muchas diferencias entre uno y otro pero las más notables las podéis encontrar en el siguiente enlace:

Diferencias entre xargs y parallel
https://www.gnu.org/software/parallel/man.html#differences_between_xargs_and_gnu_parallel

Ahora veamos un ejemplo de como lanzar sincronización de archivos mediante rsync en paralelo con uno y otro programa:

xargs

Para entender mejor el xargs, yo lo veo como un sustituto de :

for i in `ls`
do
     echo -- $i
done 

en el mundo xargs seria el equivalente one-liner:

ls | xargs -I% echo -- %


Script de ejemplo para lanzar rsync en paralelo:

#! /bin/bash
LIST=$1
DEST_DIR=$2
RSYNC_OPTS=$3
#echo "rsyncing From=$SRC_DIR To=$DEST_DIR RSYNC_OPTS=$RSYNC_OPTS"
echo $LIST|xargs -n1 -d, echo|xargs -n1 -P 0 -I% rsync --rsync-path='sudo rsync' ${RSYNC_OPTS} % ${DEST_DIR}


Este script recibe tres argumentos. El primero un listado de directorios a sincronizar separados por comas. El segundo el directorio de destino. El tercer parámetro son las opciones rsync.

El problema que obtengo con este script es que si deseo saber el código de salida de los rsync que lanzo no tengo manera. Como mucho puedo saber mediante pipestatus el código de salida del último xargs. Dicho de otra manera, hace el paralelismo pero pierdo información que me podría ser útil.

GNU parallel


Como parallel no viene instalado por defecto, lo instalamos:

apt-get install parallel

Ahora os aconsejo borrar el flag --tollef del archivo de configuración /etc/parallel/config ya que sino muchas de las 'virtudes' de parallel no os funcionaran y os darán errores como este:

ls | parallel echo            # Outputs single new line
ls | parallel echo echo echo  # Outputs three new lines.
ls | parallel echo {}         # /bin/bash: {}: command not found
ls | parallel echo '{}'       # /bin/bash: {}: command not found
ls | parallel 'echo {}'       # Outputs: {}
ls | parallel -IMM 'echo MM'  # Outputs: MM


(Fuente StackOverflow)

Una vez instalado ya podemos hacer un script para lanzar rsync en paralelo:

parallel -q -d"," --joblog /etc/scripts/rsync_hercules_parallel.log rsync ${OPCIONES[@]} {} ${DEST} ::: `echo "${ORIGENES%?}"`

En donde $OPCIONES $DEST y $ORIGENES son arrays con los argumentos del rsync. Este script es muy similar al que hacemos con xargs pero con una GRAN diferencia: No perdemos los códigos de salida (exitval) del rsync. De esta manera, pese a lanzar todos los rsync en paralelo, tenemos control total de lo que tarda el proceso y su retorno (sequence number, sshlogin, start time as seconds since epoch, run time in seconds, bytes in files transferred, bytes in files returned, exit status, and command)


That u don't know what you've got 'til it's gone