【问题标题】:Parallel processing with xargs in bash在 bash 中使用 xargs 进行并行处理
【发布时间】:2023-04-02 14:47:01
【问题描述】:

我有一个小脚本,我将在其中获取每个 openstack 的租户并在 python 的帮助下获取一些输出。生成报告的时间太长,建议我使用xargs。我之前的代码如下所示。

#!/bin/bash
cd /scripts/cloud01/floating_list

rm -rf ./reports/openstack_reports/
mkdir -p ./reports/openstack_reports/

source ../creds/base
for tenant in A B C D E F G H I J K L M N O P Q R S T
do
  source ../creds/$tenant
  python ../tools/openstack_resource_list.py > ./reports/openstack_reports/$tenant.html

done
lftp -f ./lftp_script

现在我已将 xargs 放入脚本中,脚本看起来像这样。

#!/bin/bash
cd /scripts/cloud01/floating_list

rm -rf ./reports/openstack_reports/
mkdir -p ./reports/openstack_reports/

source ../creds/base

# Need xargs idea below
cat tenants_list.txt | xargs -P 8 -I '{}' # something that takes the tenant name and source
TENANT_NAME={}
python ../tools/openstack_resource_list.py > ./reports/openstack_reports/$tenant.html
lftp -f ./lftp_script

在这个脚本中我应该如何实现source ../creds/$tenant?因为在处理每个租户时,它也需要被采购,我不确定如何将它包含在 xargs 中以进行并行执行。

【问题讨论】:

    标签: python bash openstack xargs


    【解决方案1】:

    xargs 不能轻易运行 shell 函数……但它可以运行 shell。

    # If the tenant names are this simple, don't put them in a file
    printf '%s\n' {A..T} |
    xargs -P 8 -I {} bash -c 'source ../creds/"$0"
          python ../tools/openstack_resource_list.py > ./reports/openstack_reports/"$0".html' {}
    

    有点晦涩,bash -c '...' 之后的参数在脚本中暴露为 $0

    如果您想将租户保存在文件中,xargs -a filename 是避免useless use of cat 的好方法,尽管它不能移植到所有xargs 实现。 (使用xargs ... <filename 重定向显然是完全可移植的。)

    为了提高效率,您可以重构脚本以循环尽可能多的参数:

    printf '%s\n' {A..T} |
    xargs -n 3 -P 8 bash -c 'for tenant; do
          source ../creds/"$tenant"
          python ../tools/openstack_resource_list.py > ./reports/openstack_reports/"$tenant".html
      done' _
    

    这将运行最多 8 个并行 shell 实例,每个实例最多分配 3 个租户(因此实际上只有 7 个实例),尽管使用这么少的参数,性能差异可能可以忽略不计。

    因为我们现在实际上接收的是参数列表,所以我们将 _ 作为填充 $0 的值传递(只是因为需要将其设置为某个值,以便正确获取真正的参数) .

    如果source 可能会进行修改,这些修改并不总是保证在下一次迭代中被source 覆盖(例如,某些租户有需要为其他租户取消设置的变量?)这会使事情复杂化,但如果你真的需要帮助解决这个问题,也许可以发布一个单独的问题;或者只是回退到第一个变体,每个租户都在单独的 shell 实例中运行。

    【讨论】:

    • 非常感谢。我得到了预期的结果。接受你的回答。这确实让我陷入了来自我的 python 文件的其他一些问题,但现在这是另一个故事了。 :)
    • 添加 xargs 会增加我从中请求数据的服务器上的 CPU 负载。我添加了 10 秒的睡眠时间来创建一个小的延迟。您对此有什么建议吗?
    • 根据定义并行处理会增加负载。如果远程服务器没有准备好处理这种负载,请减少并行度,也许只减少一点(可能是 4 而不是 8?)但如果这对整个系统更方便,最终会回到序列化。
    • 如果您的 Python 脚本访问远程服务器并且 Python API 允许您设置优先级或“nice”级别,这将允许您与服务器通信这是允许采取的如果负载高,则需要更长的时间;但这在投机国家已经走得很远了。
    • 我没有设置优先级的权限。而且我还需要更快地生成报告,但将负载保持在最低限度。这就像一个僵局。 :(
    【解决方案2】:

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

    #!/bin/bash
    cd /scripts/cloud01/floating_list
    
    rm -rf ./reports/openstack_reports/
    mkdir -p ./reports/openstack_reports/
    
    source ../creds/base
    doit() {
      source ../creds/"$1"
      python ../tools/openstack_resource_list.py > ./reports/openstack_reports/"$1".html
    }
    env_parallel doit ::: {A..T}
    lftp -f ./lftp_script
    

    env_parallel 将环境复制到每个命令中——包括函数。然后它运行parallel,每个内核并行运行一个作业。

    根据任务的不同,并行运行更多或更少可能更快或更慢。使用 -j8 调整 8 个并行作业或使用 -j200% 调整每个核心 2 个作业。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-21
      • 2015-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 2015-02-13
      • 2017-06-02
      相关资源
      最近更新 更多