在bash中使用xargs进行并行处理

问题描述 投票:4回答:2

我有一个小脚本,我将在每个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
2个回答
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覆盖(比如说,有些租户的变量需要为其他一些租户设置?)会使事情变得复杂,但如果qaxswpoi可能会发布一个单独的问题,如果你真的需要帮助来解决这个问题;或者只是回到第一个变量,其中每个租户都在一个单独的shell实例中运行。


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个作业。

© www.soinside.com 2019 - 2024. All rights reserved.