2011-09-30 19 views
9

Estoy tratando de usar GNU parallel para publicar muchos archivos en un servidor web. En mi directorio, tengo algunos archivos:"buscar" y "ls" con GNU paralelo

file1.xml 
file2.xml 

y tengo un script de shell que tiene este aspecto:

#! /usr/bin/env bash 

CMD="curl -X POST [email protected]$1 http://server/path" 

eval $CMD 

Hay algunas otras cosas en el guión, pero este fue el ejemplo más simple. Traté de ejecutar el siguiente comando:

ls | parallel -j2 script.sh {} 

que es lo que los GNU parallel páginas muestran como la forma "normal" para operar en los archivos en un directorio. Esto parece pasar el nombre del archivo en mi guión, pero rizo se queja de que no puede cargar el archivo de datos que se pasa en Sin embargo, si lo hago:.

find . -name '*.xml' | parallel -j2 script.sh {} 

funciona bien. ¿Hay alguna diferencia entre cómo ls y find pasan argumentos a mi script? ¿O necesito hacer algo adicional en ese script?

+1

¡ha intentado correr con #!/ bin/bash -x que te mostrará si tus argumentos no son lo que crees que deberían ser. –

+0

Siempre estoy avergonzado cuando sucede esto, pero cuando traté de reproducir este problema al día siguiente (y uso el -x como se sugiere) no pude reproducirlo y todo estaba funcionando bien. He podido usar ls o encontrar con éxito todo el tiempo. Me pregunto si, de alguna manera, reventé mi entorno y un cierre/sesión borró algo. – Dave

Respuesta

2

No he usado parallel pero hay otro diferente entre ls & find . -name '*.xml'. ls mostrará los archivos y directorios donde find . -name '*.xml' enumerará solo los archivos (y directorios) que terminan con .xml.
Según lo sugerido por Paul Rubel, simplemente imprima el valor de $ 1 en su secuencia de comandos para verificar esto. Además, es posible que desee considerar filtrar la entrada a los archivos solo en find con la opción -type f.
Espero que esto ayude!

1

Neat.

Nunca antes había usado paralelo. Parece, sin embargo, que hay dos de ellos. Uno es el Gnu Parrallel, y el que se instaló en mi sistema tiene Tollef Fog Heen como el autor en las páginas man.

Como Pablo mencionó, se debe utilizar set -x

Además, el paradigma de que usted ha mencionado más arriba no parece trabajar en mi paralelos, más bien, tengo para hacer lo siguiente:

$ cat ../script.sh 
+ cat ../script.sh 
#!/bin/bash 
echo [email protected] 
$ parallel -ij2 ../script.sh {} -- $(find -name '*.xml') 
++ find -name '*.xml' 
+ parallel -ij2 ../script.sh '{}' -- ./b.xml ./c.xml ./a.xml ./d.xml ./e.xml 
./c.xml 
./b.xml 
./d.xml 
./a.xml 
./e.xml 
$ parallel -ij2 ../script.sh {} -- $(ls *.xml) 
++ ls --color=auto a.xml b.xml c.xml d.xml e.xml 
+ parallel -ij2 ../script.sh '{}' -- a.xml b.xml c.xml d.xml e.xml 
b.xml 
a.xml 
d.xml 
c.xml 
e.xml 

find provee una entrada diferente, Prepede la ruta relativa al nombre. Quizás eso es lo que está estropeando su script?

5

GNU parallel es una variante de xargs. Ambos tienen interfaces muy similares, y si buscas ayuda en parallel, puede que tengas más suerte buscando información sobre xargs.

Dicho esto, la forma en que ambos funcionan es bastante simple. Con su comportamiento predeterminado, ambos programas leen la entrada de STDIN, luego dividen la entrada en tokens basados ​​en espacios en blanco. Cada uno de estos tokens se pasa luego a un programa proporcionado como argumento. El valor predeterminado para xargs es pasar tantos tokens como sea posible al programa, y ​​luego iniciar un nuevo proceso cuando se alcanza el límite. No estoy seguro de cómo funciona el valor predeterminado para paralelo.

Aquí se muestra un ejemplo:

> echo "foo bar \ 
    baz" | xargs echo 
foo bar baz 

Hay algunos problemas con el comportamiento por defecto, por lo que es común ver algunas variaciones.

El primer problema es que debido a que se usa el espacio en blanco para tokenizar, cualquier archivo con espacios en blanco provocará la ruptura de paralelo y xargs. Una solución es tokenizar alrededor del carácter NULL en su lugar. find incluso proporciona una opción para hacer esto es fácil de hacer:

> echo "Success!" > bad\ filename 
> find . "bad\ filename" -print0 | xargs -0 cat 
Success! 

La opción -print0 dice find para separar los archivos con el carácter nulo en lugar de espacios en blanco.
La opción -0 dice xargs para usar el carácter NULO para tokenizar cada argumento.

Tenga en cuenta que parallel es un poco mejor que en que su comportamiento predeterminado es el tokenizar alrededor de las nuevas líneas, por lo que hay menos necesidad de cambiar el comportamiento predeterminado.

Otro problema común es que es posible que desee controlar cómo se pasan los argumentos a xargs o parallel. Si necesita tener una ubicación específica de los argumentos pasados ​​al programa, puede usar {} para especificar dónde se colocará el argumento.

> mkdir new_dir 
> find -name *.xml | xargs mv {} new_dir 

Esto moverá todos los archivos en el directorio actual y los subdirectorios al directorio new_dir. En realidad se descompone en los siguientes:

> find -name *.xml | xargs echo mv {} new_dir 
> mv foo.xml new_dir 
> mv bar.xml new_dir 
> mv baz.xml new_dir 

por lo que teniendo en cuenta cómo xargs y parallel trabajo, que es de esperar debería ser capaz de ver el asunto con su comando. find . -name '*.xml' generará una lista de archivos xml para pasar al programa script.sh.

> find . -name '*.xml' | parallel -j2 echo script.sh {} 
> script.sh foo.xml 
> script.sh bar.xml 
> script.sh baz.xml 

Sin embargo, ls | parallel -j2 script.sh {} generará una lista de todos los archivos en el directorio actual al ser pasado al programa de script.sh.

> ls | parallel -j2 echo script.sh {} 
> script.sh some_directory 
> script.sh some_file 
> script.sh foo.xml 
> ... 

Una variante más correcto de la versión ls sería de la siguiente manera:

> ls *.xml | parallel -j2 script.sh {} 

Sin embargo, e importante diferencia entre esta y la versión hallazgo es que la hallan será buscar a través de todos los subdirectorios para archivos, mientras Solo buscará en el directorio actual. La versión equivalente find del comando anterior ls sería de la siguiente manera:

> find -maxdepth 1 -name '*.xml' 

Esto sólo buscará en el directorio actual.

3

Dado que funciona con find, probablemente desee ver qué comando ejecuta GNU Parallel (usando -v o --dryrun) y luego intente ejecutar los comandos anómalos manualmente.

ls *.xml | parallel --dryrun -j2 script.sh 
find -maxdepth 1 -name '*.xml' | parallel --dryrun -j2 script.sh 
Cuestiones relacionadas