gpt4 book ai didi

bash - 并行化 bash 脚本

转载 作者:行者123 更新时间:2023-11-29 08:55:30 27 4
gpt4 key购买 nike

我需要几个网页中包含的整数的总和。 getPages() 解析整数并将其设置为 $subTotalgetPages() 在后台的 for 循环中被调用,但是如何获得 $subTotal 的总和?这是一个子脱壳问题吗?

这是我迄今为止尝试过的。

#!/bin/bash
total=0
getPages(){
subTotal=$(lynx -dump http://"$(printf "%s:%s" $1 $2)"/file.html | awk -F, 'NR==1 {print $1}' | sed 's/\s//g')
total=$(($total+$subTotal))
echo "SubTotal: " $subTotal "Total: " $total
}
# /output/ SubTotal: 22 Total: 22
# /output/ SubTotal: 48 Total: 48 //Note Total should be 70

ARRAY=(
'pf2.server.com:6599'
'pf5.server.com:1199'
...
)

for server in ${ARRAY[@]} ; do
KEY=${server%%:*}
VALUE=${server##*:}
getPages $KEY $VALUE &
done
wait
echo $total
exit 0

# /output/ 0

感谢任何建议。

最佳答案

是的,这是一个子脱壳问题。在 ... & 中执行的所有内容列表(即您的 getPages $KEY $VALUE & )在子 shell 中执行,这意味着那里的变量更改不会影响父 shell。

我认为可以使用协同进程(即通过流进行通信)或使用 GNU parallel 来做一些事情或 pexec .


这是一个 pexec 的例子,使用默认输出从单个进程进行通信。我使用了一个更简单的命令,因为您无法从此处访问您列出的服务器。这会计算某些网页上的行数并将它们相加。

ARRAY=(
'www.gmx.de:80'
'www.gmx.net:80'
'www.gmx.at:80'
'www.gmx.li:80'
)


(( total = 0 ))
while read subtotal
do
(( total += subtotal ))
echo "subtotal: $subtotal, total: $total"
done < <(
pexec --normal-redirection --environment hostname --number ${#ARRAY[*]} \
--parameters "${ARRAY[@]}" --shell-command -- '
lynx -dump http://$hostname/index.html | wc -l'
)

echo "total: $total"

我们在这里使用了一些技巧:

  • 我们将并行进程的输出通过管道返回到主进程,在那里循环读取它。
  • 为避免为 while 循环创建子 shell,我们使用 bash 的进程替换功能 (<( ... )) 和输入重定向 (<) 而不是简单的管道。
  • 我们在 (( ... )) 中做算术运算算术表达式命令。我本可以使用 let , 而不是,但那时我将不得不引用所有内容或避免使用空格。 (你的 total=$(( total + subtotal )) 也可以。)
  • pexec 的选项:
    • --normal-redirection意味着将所有子进程的输出流一起重定向到 pexec 的输出流中. (如果两个进程想同时写入,我不确定这是否会导致一些困惑。)
    • --environment hostname将每次执行的不同参数作为环境变量传递。否则,它将是一个简单的命令行参数。
    • --number ${#ARRAY[*]} (在我们的例子中得到 --number 4)确保所有进程将并行启动,而不是只有我们有 CPU 或其他一些启发式的那么多。 (这是针对网络往返绑定(bind)的工作。对于 CPU 绑定(bind)或带宽绑定(bind)的东西,较小的数字会更好。)
    • --shell-command确保命令将由 shell 评估,而不是尝试直接执行它。这是必要的,因为那里有管道。
    • --parameters "${ARRAY[@]}"列出实际参数 - 即数组的元素。对于它们中的每一个,将启动一个单独版本的命令。
    • 决赛后--命令来了 - 作为一个 ' - 引号字符串,以避免过早解释 $hostname在外壳旁边。该命令简单地下载文件并将其通过管道传输到 wc -l , 计算行数。

示例输出:

subtotal: 1120, total: 1120
subtotal: 968, total: 2088
subtotal: 1120, total: 3208
subtotal: 1120, total: 4328
total: 4328

这是 ps -f 的(部分)输出运行时:

 2799 pts/1    Ss     0:03  \_ bash
5427 pts/1 S+ 0:00 \_ /bin/bash ./download-test.sh
5428 pts/1 S+ 0:00 \_ /bin/bash ./download-test.sh
5429 pts/1 S+ 0:00 \_ pexec --number 4 --normal-redirection --environment hostname --parame...
5430 pts/1 S+ 0:00 \_ /bin/sh -c ? lynx -dump http://$hostname/index.html | wc -l
5434 pts/1 S+ 0:00 | \_ lynx -dump http://www.gmx.de:80/index.html
5435 pts/1 S+ 0:00 | \_ wc -l
5431 pts/1 S+ 0:00 \_ /bin/sh -c ? lynx -dump http://$hostname/index.html | wc -l
5436 pts/1 S+ 0:00 | \_ lynx -dump http://www.gmx.net:80/index.html
5437 pts/1 S+ 0:00 | \_ wc -l
5432 pts/1 S+ 0:00 \_ /bin/sh -c ? lynx -dump http://$hostname/index.html | wc -l
5438 pts/1 S+ 0:00 | \_ lynx -dump http://www.gmx.at:80/index.html
5439 pts/1 S+ 0:00 | \_ wc -l
5433 pts/1 S+ 0:00 \_ /bin/sh -c ? lynx -dump http://$hostname/index.html | wc -l
5440 pts/1 S+ 0:00 \_ lynx -dump http://www.gmx.li:80/index.html
5441 pts/1 S+ 0:00 \_ wc -l

我们可以看到,实际上一切都在我的单处理器系统上尽可能地并行运行。

关于bash - 并行化 bash 脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6575492/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com