web-dev-qa-db-ja.com

GNU並列関数とBash関数:マニュアルから簡単な例を実行する方法

GNU Parallelは、bash関数を簡単に並列化できると思う場合があるので、学習しようとしています。そこで、学習しようとして、 GNUParallelマニュアル あるところ ...しかし、私はそれを機能させることさえできません!

(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 $1
  sleep 2
  echo Done with $1
}
export -f doit
parallel doit ::: 1 2 3
doubleit() {
  echo Doing it for $1 $2
  sleep 2
  echo Done with $1 $2
}
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 $1
  sleep 2
  echo Done with $1
}
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 $1 $2
  sleep 2
  echo Done with $1 $2
}
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」と呼ぶだけで、それが実行されます。したがって、関数は有効ですが、エクスポートされませんか?

17
Fortran

定義されたシェルの外部からシェル関数を呼び出すことはできません。シェル関数は、シェル内の概念です。 parallelコマンド自体にはアクセスする方法がありません。

Bashでexport -f doitを呼び出すと、環境を介して関数がエクスポートされ、子プロセスによって取得されます。しかし、bash関数を理解できるのはbashだけです。 (グランド)*子bashプロセスはそれを呼び出すことができますが、他のプログラム、たとえば他のシェルは呼び出すことができません。

「コマンドが見つかりません」というメッセージを見ると、優先シェルは(t)cshのようです。代わりにbashを呼び出すようにparallelに指示する必要があります。 parallelは、Shell環境変数¹で示されるシェルを呼び出すため、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環境変数 セクションにもリストされません。 (これをバグとして報告することをお勧めします。このプログラムをほとんど使用しないため、報告していません。)

¹ Shellは、対話型コマンドラインシェルのユーザーインターフェイス設定を示し、プログラムの動作を変更しないことになっているため、これは不適切な設計です。

バージョン20160722以降、代わりにenv_parallelを使用できます。

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

env_parallelに追加して.bashrcをアクティブ化する必要があります。これを1回実行すると、.bashrcに追加できます。

env_parallel --install
5
Ole Tange