在 bash 中使用 xargs 进行并行处理
Parallel processing with xargs in bash
我有一个小脚本,我可以在其中获取每个 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 中以进行并行执行。
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/"[=10=]"
python ../tools/openstack_resource_list.py > ./reports/openstack_reports/"[=10=]".html' {}
有些晦涩,bash -c '...'
之后的参数在脚本中暴露为 [=14=]
。
如果您想将租户保存在一个文件中,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 个实例),尽管参数数量很少,性能上的差异可能可以忽略不计。
因为我们现在实际上收到了一个参数列表,所以我们将 _
作为填充 [=14=]
的值传递(只是因为它需要设置为某些东西,以便获得真正的论点适当地。
如果 source
可能做出的修改并不总是保证在下一次迭代中被 source
覆盖(比如,一些租户有需要为其他租户取消设置的变量?)这使事情变得复杂,但如果您真的需要帮助解决这个问题,也许 post 是一个单独的问题;或者只是回到第一个变体,其中每个租户 运行 在一个单独的 shell 实例中。
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/""
python ../tools/openstack_resource_list.py > ./reports/openstack_reports/"".html
}
env_parallel doit ::: {A..T}
lftp -f ./lftp_script
env_parallel
将环境复制到每个命令中 - 包括函数。然后它 运行s parallel
其中 运行s 每个核心并行一个作业。
根据任务的不同,并行地 运行 可能更快或更慢。调整 -j8
并行 8 个作业或 -j200%
每个核心 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 中以进行并行执行。
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/"[=10=]"
python ../tools/openstack_resource_list.py > ./reports/openstack_reports/"[=10=]".html' {}
有些晦涩,bash -c '...'
之后的参数在脚本中暴露为 [=14=]
。
如果您想将租户保存在一个文件中,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 个实例),尽管参数数量很少,性能上的差异可能可以忽略不计。
因为我们现在实际上收到了一个参数列表,所以我们将 _
作为填充 [=14=]
的值传递(只是因为它需要设置为某些东西,以便获得真正的论点适当地。
如果 source
可能做出的修改并不总是保证在下一次迭代中被 source
覆盖(比如,一些租户有需要为其他租户取消设置的变量?)这使事情变得复杂,但如果您真的需要帮助解决这个问题,也许 post 是一个单独的问题;或者只是回到第一个变体,其中每个租户 运行 在一个单独的 shell 实例中。
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/""
python ../tools/openstack_resource_list.py > ./reports/openstack_reports/"".html
}
env_parallel doit ::: {A..T}
lftp -f ./lftp_script
env_parallel
将环境复制到每个命令中 - 包括函数。然后它 运行s parallel
其中 运行s 每个核心并行一个作业。
根据任务的不同,并行地 运行 可能更快或更慢。调整 -j8
并行 8 个作业或 -j200%
每个核心 2 个作业。