viernes, 27 de julio de 2012

Linux: como generar un número limitado de subprocesos en segundo plano

Esta situación se me ha dado con bastante frecuencia. Imagínate que tienes que procesar una gran cantidad de archivos en un árbol de directorios, y que por cada archivo tienes que ejecutar un proceso algo pesado (por ejemplo, bzip2).

A voz de pronto, la forma más fácil de hacerlo es:

$ find . -type f -exec bzip2 \{\} \;

Esto ejecutará nuestro  proceso ... de uno en uno. Estamos en el año 2012, nuestros procesadores tienen muchos núcleos, y ya que los pagamos queremos usarlos. Bien, la alternativa podría ser:

$ find . -type f -exec bzip2 \{\} \& \;

¡Olé! Ahora en lugar de un solo proceso, vamos a empezar a crear procesos sin control hasta que el sistema se colapse o alcancemos el límite máximo (ver ulimit), y obtengamos un error. No parece la mejor solución.

Lo que realmente queremos es que el sistema genere 4, 5, ó 20 procesos, y que a medida que vayan acabando se generen otros nuevos que reemplacen a los que han terminado. La solución más simple nos la da xargs :

$ find . -type f -print | xargs -P 5 -d "\n" -n 1 bzip2

La clave está en el parámetro -P , que limita exactamente el número máximo de procesos a crear. De hecho, si hacemos un ps -ef ....


jose      8462  2856  0 13:44 pts/3    00:00:01 xargs -P 5 -d \n -n 1 bzip2
jose     24599  8462 39 13:57 pts/3    00:00:02 bzip2 ./Backups/servers/mail/vhosts/tri.com/egd/cur/1310570188.V811I1ad008cM674902.mail:2,S
jose     24613  8462 53 13:57 pts/3    00:00:01 bzip2 ./Backups/servers/mail/vhosts/tri.com/egd/cur/1310562280.V811I1ad0048M849935.mail:2,S
jose     24615  8462 44 13:57 pts/3    00:00:01 bzip2 ./Backups/servers/mail/vhosts/tri.com/egd/cur/1310569446.V811I1ad0080M942514.mail:2,S
jose     24622  8462 41 13:57 pts/3    00:00:00 bzip2 ./Backups/servers/mail/vhosts/tri.com/egd/cur/1310560224.V811I1ad0024M906849.mail:2,S
jose     24623  8462  0 13:57 pts/3    00:00:00 bzip2 ./Backups/servers/mail/vhosts/tri.com/egd/cur/1310571017.V811I1ad0096M988948.mail:2,S


Por cierto, no te pases mucho con el número de procesos simultáneos, o la carga del sistema subirá demasiado y puede que sea más lenta la solución en paralelo a la solución en serie.