【问题标题】:Adding extra argument to xargs向 xargs 添加额外参数
【发布时间】:2018-04-16 05:30:22
【问题描述】:

我正在尝试启动多个进程以完成一些测试套件。在我的 bash 脚本中,我有以下内容

printf "%s\0" "${SUITE_ARRAY[@]}" | xargs -P 2 -0 bash -c 'run_test_suite "$@" ${EXTRA_ARG}'

以下是定义的脚本,只涉及基本内容。

SUITE_ARRAY 将是可能有 1 个或多个套件的列表,{Suite 1, Suite 2, ..., Suite n} EXTRA_ARG 将像一个特定的名称一样将值存储在另一个脚本中

#!/bin/bash

run_test_suite(){
    suite=$1
    someArg=$2
    someSaveDir=someArg"/"suite
    # some preprocess work happens here, but isn't relevant to running
    runSomeScript.sh suite someSaveDir
}

export -f run_test_suite

SUITES=$1
EXTRA_ARG=$2

IFS=','
SUITECOUNT=0
for csuite in ${SUITES}; do
    SUITE_ARRAY[$SUITECOUNT]=$csuite
    SUITECOUNT=$(($SUITECOUNT+1))
done
unset IFS

printf "%s\0" "${SUITE_ARRAY[@]}" | xargs -P 2 -0 bash -c 'run_test_suite "$@" ${EXTRA_ARG}'

我遇到的问题是如何将${EXTRA_ARG} 传递给 xargs。根据我的理解, xargs 将采用管道传输的任何内容,因此我拥有它的方式似乎不正确。

关于如何正确传递值的任何建议?提前致谢

【问题讨论】:

  • 请指定${SUITE_ARRAY[@]} 中通常有多少个值,以及${EXTRA_ARG} 是否打算被使用一次是否是$someArg 的重复值。
  • ${SUITE_ARRAY[@]} 可能因运行而异;少至 2 至多至 20+。 $someArg 对于每次调用都将保持不变,但是当调用 xargs 所在的主脚本时,${EXTRA_ARG} 可能会有所不同。
  • 稍微编辑了问题和代码以反映您的 cmets。
  • 我之前评论中的错字,特此更正:请指定${SUITE_ARRAY[@]} 中通常有多少个值,以及${EXTRA_ARG} 是打算使用一次,还是作为重复值对于$someArg
  • export EXTRA_ARG

标签: shell xargs


【解决方案1】:

如果你想让EXTRA_ARG 对子shell 可用,你需要export 它。您可以使用export 关键字显式执行此操作,也可以将var=value 赋值放在与xargs 本身相同的简单命令中:

#!/bin/bash

run_test_suite(){
    suite=$1
    someArg=$2
    someSaveDir=someArg"/"suite
    # some preprocess work happens here, but isn't relevant to running
    runSomeScript.sh suite someSaveDir
}
export -f run_test_suite

# assuming that the "array" in $1 is comma-separated:
IFS=, read -r -a suite_array <<<"$1"

# see the EXTRA_ARG="$2" just before xargs on the same line; this exports the variable
printf "%s\0" "${suite_array[@]}" | \
  EXTRA_ARG="$2" xargs -P 2 -0 bash -c 'run_test_suite "$@" "${EXTRA_ARG}"' _

_ 防止从xargs 传递到bash 的第一个参数变为$0,因此不包含在"$@" 中。

还请注意,我将"${suite_array[@]}" 更改为通过用逗号分隔$1 来分配。这个或类似的东西(例如,您可以使用 IFS=$'\n' 在换行符上拆分)是必要的,因为 $1 不能 包含文字数组;每个 shell 命令行参数都只是一个字符串。

【讨论】:

  • 您对$1 的分配是正确的。在我匆忙发布我的代码时,我遗漏了我打破$1的部分,这是一个逗号分隔的参数“套件1,套件2,套件3,...,套件n”到一个数组.老实说,我对 shell 的了解不足以轻易分解,所以我使用了 for 循环。我会再次更新问题。
  • 这里的代码使用read -a是把字符串解析成数组的正确方法。
  • 看起来这种方法效果最好,但是我发现如果我只传入数组中的 1 个值,-P 将使用相同的一个参数启动 2 个进程。我原以为它只会启动 1。我通过检查数组是否为 2 或更大来解决此问题,如果是,则让 -P 为 2,否则使用 1。
  • @EmmanuelF, ...哪个版本的 xargs?我无法重现它;例如,printf '%s\n' 1 2 | xargs -P 2 -n 2 bash -c 'echo "$$: $*"' _ 符合我的预期。
  • Charles,我最初是这样设置的printf "%s\0" "${suite_array[@]}" | ARG="$EXTRA_ARG" xargs -P 2 -n 1 -0 bash -c 'run_test_suite "$@" "${ARG}"' _,由于某种原因,当我只传入 1 个参数时,run_test_suite 运行了两次。我在上面运行了你的 sn-p,发现它只运行了一次。我想知道我在那里做错了什么。
【解决方案2】:

这是一个猜测:

#!/bin/bash

run_test_suite(){
    suite="$1"
    someArg="$2"
    someSaveDir="${someArg}/${suite}"
    # some preprocess work happens here, but isn't relevant to running
    runSomeScript.sh "${suite}" "${someSaveDir}"
}

export -f run_test_suite

SUITE_ARRAY="$1"
EXTRA_ARG="$2"

printf "%s\0" "${SUITE_ARRAY[@]}" | 
xargs -n 1 -I '{}' -P 2 -0 bash -c 'run_test_suite {} '"${EXTRA_ARG}"

【讨论】:

  • 内引号关闭外引号。 -n 1-I 在这里是不好的做法——这意味着 xargs 为每个项目运行一个新的 bash 副本,而原始代码没有这样做。
  • ...通过“关闭外部的”,我的意思是字符串 {} 在这里没有被引用。
  • @CharlesDuffy,谢谢,糟糕的引用是一个仓促的错字,现在更正了,也许...-n 1 是故意的,并且 guess 关于 OPs 实际意图基于代码和his comment
  • 呃,now we learn“数组”是一个逗号分隔的字符串,存储为实际的bash 数组?嗯,我的代码要求数组只是一个数组,不包含分隔逗号。
  • 我知道,对不起。我试图用我认为与手头问题最相关的部分来解决这个问题。再次道歉。
【解决方案3】:

使用 GNU Parallel 它看起来像这样:

#!/bin/bash

run_test_suite(){
    suite="$1"
    someArg="$2"
    someSaveDir="$someArg"/"$suite"
    # some preprocess work happens here, but isn't relevant to running                        
    echo runSomeScript.sh "$suite" "$someSaveDir"
}
export -f run_test_suite

EXTRA_ARG="$2"
parallel -d, -q run_test_suite {} "$EXTRA_ARG" ::: "$1"

称为:

mytester 'suite 1,suite  2,suite "three"' 'extra "quoted" args here'

如果你有一个数组中的套件:

parallel -q run_test_suite {} "$EXTRA_ARG" ::: "${SUITE_ARRAY[@]}"

额外的好处:工作的任何输出都不会混合,因此您不必处理http://mywiki.wooledge.org/BashPitfalls#Using_output_from_xargs_-P

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-01
    • 2012-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多