¿Por qué GNU no funciona en paralelo con "bash -c"?

9
% echo -e '1\n2' | parallel "bash -c 'echo :\$1' '' {}"
:1
:2
% echo -e '1\n2' | parallel bash -c 'echo :\$1' '' {}


%

Esperaría que la segunda línea actúe igual.

Raitis Veinbahs
fuente

Respuestas:

11

parallelEjecuta el comando en una cáscara ya (que la cáscara es está determinado por parallelel uso de la heurística (con la intención de invocar el mismo shell como el que parallelse invocó de ). Puede establecer la $PARALLEL_SHELLvariable para fijar la cáscara).

No es un comando al que está pasando parallelcomo lo haría para el comando envo xargs, sino una línea de comando de shell (como lo haría para el evalcomando).

Al igual que for eval, in parallel arg1 arg2, parallelconcatena esos argumentos con espacios intermedios (por lo que se convierte arg1 arg2) y esa cadena se pasa a <the-shell> -c.

Para los argumentos que se transmiten en parallella entrada estándar, parallelcítelos en el formato esperado por ese shell en particular (una tarea difícil y propensa a errores, por eso encontrará que se han solucionado muchos errores en parallelel Registro de cambios ( algunos todavía no se corrigieron a partir del 2017-03-06)) y lo agrega a esa línea de comando.

Entonces, por ejemplo, si se llama desde adentro bash,

echo "foo'bar" | parallel echo foo

Tendría llamada en paralelo bash -ccon el echo foo foo\'barque la línea de comandos. Y si se llama desde dentro rc(o con PARALLEL_SHELL=rc) rc -ccon echo foo foo''''bar.

En tus:

parallel bash -c 'echo :\$1' '' {}

parallel concatena esos argumentos que da:

bash -c echo :$1  {}

Y con el {}expandido y citado en el formato correcto para el shell desde el que está llamando parallel, pasa aquello a <that-shell> -clo que llamará bash -c echocon :$1in $0y el argumento actual en $1.

No es así como parallelfunciona. Aquí, probablemente quieras:

printf '1\n2\n' | PARALLEL_SHELL=bash parallel 'echo :{}'

Para ver qué parallelhace, puede ejecutarlo strace -fe execve(o el equivalente en su sistema si no es Linux).

Aquí, puede usar GNU en xargslugar de parallelobtener un procesamiento más simple más cercano a lo que espera:

printf '1\n2\n' | xargs -rn1 -P4 bash -c 'echo ":$1"' ''

Consulte también la discusión en https://lists.gnu.org/archive/html/bug-parallel/2015-05/msg00005.html

Tenga en cuenta que en bash -c 'echo foo' '' foo, está haciendo $0la cadena vacía para ese script en línea. Evitaría eso, ya que $0también se usa en mensajes de error. Comparar:

$ bash -c 'echo x > "$1"' '' /
: /: Is a directory

con.

$ bash -c 'echo x > "$1"' bash /
bash: /: Is a directory

También tenga en cuenta que dejar variables sin comillas tiene un significado muy especial bashy que echogeneralmente no se puede usar para datos arbitrarios.

Stéphane Chazelas
fuente
44
Mon dieu! Esta es una mejor respuesta que la que el autor de GNU Parallel podría haber escrito.
Ole Tange