web-dev-qa-db-ja.com

xargsを使用してシェル関数を呼び出す

Xargsを使用して、より複雑な関数を並行して呼び出そうとしています。

#!/bin/bash
echo_var(){
    echo $1
    return 0
}
seq -f "n%04g" 1 100 |xargs -n 1 -P 10 -i echo_var {} 
exit 0

これはエラーを返します

xargs: echo_var: No such file or directory

Xargsを使用してこれを達成する方法、またはその他の解決策に関するアイデアは歓迎します。

144
fac3

関数をエクスポートすることで実行できます(未テスト):

export -f echo_var
seq -f "n%04g" 1 100 | xargs -n 1 -P 10 -I {} bash -c 'echo_var "$@"' _ {}

外部printfの代わりに組み込みseqを使用できます。

printf "n%04g\n" {1..100} | xargs -n 1 -P 10 -I {} bash -c 'echo_var "$@"' _ {}

また、そのようなreturn 0およびexit 0を使用すると、その前のコマンドによって生成される可能性のあるエラー値がマスクされます。また、エラーがない場合はデフォルトであるため、多少冗長です。

@phobicは、Bashコマンドcould

bash -c 'echo_var "{}"'

{}をその中に直接移動します。 しかしそれはコマンドインジェクションに対して脆弱 @Sashaが指摘したとおりです。

使用しない埋め込み形式の理由の例を次に示します。

$ echo '$(date)' | xargs -I {} bash -c 'echo_var "{}"'
Sun Aug 18 11:56:45 CDT 2019

why notの別の例:

echo '\"; date\"' | xargs -I {} bash -c 'echo_var "{}"'

これが出力です安全な形式を使用

$ echo '$(date)' | xargs -I {} bash -c 'echo_var "$@"' _ {}
$(date)

これは、 パラメータ化 SQL クエリ を使用して インジェクション を回避することに匹敵します。

ここでは、非破壊的であるため、Sashaのコメントで使用されているdateコマンドの代わりに、コマンド置換またはエスケープされた引用符でrmを使用しています。

147

GNU Parallelの使用は次のようになります。

#!/bin/bash
echo_var(){
    echo $1
    return 0
}
export -f echo_var
seq -f "n%04g" 1 100 | parallel -P 10 echo_var {} 
exit 0

バージョン20170822を使用する場合、これを実行している限り、export -fである必要さえありません:

. `which env_parallel.bash`
seq -f "n%04g" 1 100 | env_parallel -P 10 echo_var {} 
16
Ole Tange

このようなものも動作するはずです:

function testing() { sleep $1 ; }
echo {1..10} | xargs -n 1 | xargs -I@ -P4 bash -c "$(declare -f testing) ; testing @ ; echo @ "
8
Eremite

たぶんこれは悪い習慣ですが、.bashrcまたは他のスクリプトで関数を定義している場合は、allexportの設定でファイルまたは少なくとも関数定義をラップできます。

set -o allexport

function funcy_town {
  echo 'this is a function'
}
function func_rock {
  echo 'this is a function, but different'
}
function cyber_func {
  echo 'this function does important things'
}
function the_man_from_funcle {
  echo 'not gonna lie'
}
function funcle_wiggly {
  echo 'at this point I\'m doing it for the funny names'
}
function extreme_function {
  echo 'goodbye'
}

set +o allexport
0
xdhmoore