[bash] xargsでシェル関数を並列処理

2020年10月19日月曜日

bash linux unix シェルスクリプト

シェル関数を並列実行したい

シェル関数を並列実行したい時にxargsで関数をそのまま呼んでもうまくいかない。

parallel.sh
#!/bin/sh
function func()
{
  sleep 1
  echo $1
}

echo $1 | tr -s ',' '\n' | head -n6 | xargs -n1 -P6 -I% func %
$ ./parallel.sh 1,2,3,4,5,6,7,8,9
xargs: func: No such file or directory

xargs自身はシェルではないので、シェル関数は認識できない。
つまり、xargsには外部コマンドを渡す必要がある。

なので、次に考えるのはシェルにコマンド文字列を渡して起動するやり方

parallel.sh
#!/bin/sh
function func()
{
  sleep 1
  echo $1
}

echo $1 | tr -s ',' '\n' | head -n6 | xargs -n1 -P6 -I% sh -c 'func %'
$ ./parallel.sh 1,2,3,4,5,6,7,8,9
sh: func: command not found
sh: func: command not found
sh: func: command not found
sh: func: command not found
sh: func: command not found
sh: func: command not found

残念ながら、これもうまくいかない。起動したシェル側に外側のシェルで定義した関数がうまく渡っていないからだ。
こういう時は -f オプション付きで関数を export する必要がある。

parallel.sh
#!/bin/sh
function func()
{
  sleep 1
  echo $1
}
export -f func

echo $1 | tr -s ',' '\n' | head -n6 | xargs -n1 -P6 -I% sh -c 'func %'
$ ./parallel.sh 1,2,3,4,5,6,7,8,9
3
1
4
2
5
6

これで、ようやく1秒後に一斉に数字が表示されるようになった。