Функции GNU Parallel и Bash: как запустить простой пример из руководства

Я пытаюсь изучить GNU Parallel, потому что у меня есть случай, когда я думаю, что могу легко распараллелить функцию bash. Поэтому, пытаясь учиться, я пошел в GNU Parallel manual где находится пример...но я даже не могу заставить его работать! А именно:

(232) $ bash --version
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
(233) $ cat tpar.bash
#!/bin/bash

echo `which parallel`
doit() {
  echo Doing it for 
  sleep 2
  echo Done with 
}
export -f doit
parallel doit ::: 1 2 3
doubleit() {
  echo Doing it for  
  sleep 2
  echo Done with  
}
export -f doubleit
parallel doubleit ::: 1 2 3 ::: a b

(234) $ bash tpar.bash
/home/mathomp4/bin/parallel
doit: Command not found.
doit: Command not found.
doit: Command not found.
doubleit: Command not found.
doubleit: Command not found.
doubleit: Command not found.
doubleit: Command not found.
doubleit: Command not found.
doubleit: Command not found.

Как вы можете видеть, я даже не могу запустить простой пример. Таким образом, я, вероятно, делаю что-то удивительно глупое и основное...но я в растерянности.

ETA: как предложено комментаторы (chmod +x, set-vx):

(27) $ ./tpar.bash

echo `which parallel`
which parallel
++ which parallel
+ echo /home/mathomp4/bin/parallel
/home/mathomp4/bin/parallel

doit() {
  echo Doing it for 
  sleep 2
  echo Done with 
}
export -f doit
+ export -f doit
parallel doit ::: 1 2 3
+ parallel doit ::: 1 2 3
doit: Command not found.
doit: Command not found.
doit: Command not found.
doubleit() {
  echo Doing it for  
  sleep 2
  echo Done with  
}
export -f doubleit
+ export -f doubleit
parallel doubleit ::: 1 2 3 ::: a b
+ parallel doubleit ::: 1 2 3 ::: a b
doubleit: Command not found.
doubleit: Command not found.
doubleit: Command not found.
doubleit: Command not found.
doubleit: Command not found.
doubleit: Command not found.

ETA2: обратите внимание, я могу в скрипте просто вызвать "doit 1", скажем, и он это сделает. Таким образом, функция действительна, это просто не так...на экспорт?

2 ответов


вы не можете вызвать функцию оболочки извне оболочки, где она была определена. Функция оболочки-это концепция внутри оболочки. The parallel сама команда не имеет доступа к ней.

вызов export -f doit в bash экспортирует функцию через среду, чтобы она была подобрана дочерними процессами. Но только Баш понимает функции Баша. (Grand)*дочерний процесс bash может вызвать его, но не другие программы, например, не другие оболочки.

идем в сообщении "Команда не найдена", похоже, что ваша предпочтительная оболочка (t)csh. Вы должны сказать parallel для вызова bash вместо этого. parallel вызывает оболочку, указанную SHELL среда variable1, поэтому установите ее в точку bash.

export SHELL=$(type -p bash)
doit () { … }
export -f doit
parallel doit ::: 1 2 3

если вы только хотите установить SHELL для исполнения parallel команда, а не для остальной части скрипта:

doit () { … }
export -f doit
SHELL=$(type -p bash) parallel doit ::: 1 2 3

я не уверен, как бороться с удаленными заданиями, вам может потребоваться пройти --env=SHELL в дополнение к --env=doit (заметим, что это предполагает, что путь к bash везде одинаков).

и да, эта странность должна быть упомянута более заметно в руководстве. В описании command аргумент, но это не очень ясно (он должен объяснить, что command слова объединяются с пробелом в качестве разделителя, а затем передаются в $SHELL -c), и SHELL даже не указан в переменные среды. (Я призываю вас сообщить об этом как об ошибке; я не делаю этого, потому что я почти никогда не использую эту программу.)

1 это плохой дизайн, так как SHELL должен указывать предпочтения пользовательского интерфейса для интерактивной оболочки командной строки, а не изменять поведение программ.


С версии 20160722 вы можете вместо этого использовать env_parallel:

doit() { echo "$@"; }
echo world | env_parallel doit Hello

вам просто нужно активировать env_parallel добавив его в .bashrc:

env_parallel --install