27

bash関数を簡単に並列化できると思うケースがあるので、GNU Parallelを学ぼうとしています。それで、学習しようとして、例があるGNU Parallelマニュアルに行きました...しかし、それを機能させることさえできません! ウィット:

(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」を呼び出すだけで、それが実行されます。関数は有効ですが、エクスポートされていませんか?

4

2 に答える 2

40

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

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

「コマンドが見つかりません」というメッセージを見ると、優先シェルは (t)csh のようです。parallel代わりに bash を呼び出すように指示する必要があります。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です。対話型コマンド ライン シェルのユーザー インターフェイス設定を示し、プログラムの動作を変更しないことになっているためです。

于 2014-05-22T19:33:05.580 に答える