Perché GNU parallel non funziona con "bash -c"?


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


%

Mi aspetto che la seconda riga si comporti allo stesso modo.

Risposte:


11

parallelesegue il comando in una shell già (che shell è è determinato parallelutilizzando euristiche (l'intenzione è quello di richiamare la stessa shell come quello parallelè stato invocato da ). È possibile impostare la $PARALLEL_SHELLvariabile per fissare la shell).

Non è un comando a cui stai passando parallelcome faresti per il comando envo xargs, ma una riga di comando della shell (come faresti per il evalcomando).

Like for eval, in parallel arg1 arg2, parallelsta concatenando quegli argomenti con spazi in mezzo (così diventa arg1 arg2) e quella stringa viene passata a <the-shell> -c.

Per gli argomenti che vengono passati allo parallelstdin, parallelcitali nel formato previsto da quella particolare shell (un'attività difficile e soggetta a errori, motivo per cui troverai che ci sono stati molti bug corretti attorno a quello nel parallelChangelog ( alcuni non sono ancora stati corretti a partire dal 06-03-2017)) e lo aggiunge a quella riga di comando.

Ad esempio, se chiamato dall'interno bash,

echo "foo'bar" | parallel echo foo

Avrebbe chiamata parallela bash -ccon echo foo foo\'barcome riga di comando. E se chiamato dall'interno rc(o con PARALLEL_SHELL=rc) rc -ccon echo foo foo''''bar.

Nella tua:

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

parallel concatena quegli argomenti che danno:

bash -c echo :$1  {}

E con l' {}espansione e la citazione nel formato giusto per la shell da cui stai chiamando parallel, passa quello a <that-shell> -ccui chiamerà bash -c echocon :$1in $0e l'argomento corrente in $1.

Non è come parallelfunziona. Qui, probabilmente vorresti:

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

Per vedere cosa parallelsuccede, puoi eseguirlo sotto strace -fe execve(o l'equivalente sul tuo sistema se non Linux).

Qui, puoi usare GNU xargsinvece di parallelottenere un'elaborazione più semplice più vicina a ciò che ti aspetti:

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

Vedi anche la discussione su https://lists.gnu.org/archive/html/bug-parallel/2015-05/msg00005.html

Nota che in bash -c 'echo foo' '' foo, stai creando $0la stringa vuota per quello script in linea. Lo eviterei poiché $0viene utilizzato anche nei messaggi di errore. Confrontare:

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

con.

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

Si noti inoltre che lasciare variabili non quotate ha un significato molto speciale bashe che echogeneralmente non può essere utilizzato per dati arbitrari.


4
Mon dieu! Questa è una risposta migliore di quella che l'autore di GNU Parallel avrebbe potuto scrivere.
Ole Tange
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.