加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

并行化bash脚本

发布时间:2020-12-16 01:13:31 所属栏目:安全 来源:网络整理
导读:我需要几个网页中包含的整数之和. getPages()解析整数并将其设置为$subTotal. getPages()在后台的for循环中调用,但是如何获得$subTotal的总和?这是一个替代问题吗? 这是我到目前为止所尝试的. #!/bin/bashtotal=0getPages(){ subTotal=$(lynx -dump http:/
我需要几个网页中包含的整数之和. getPages()解析整数并将其设置为$subTotal. getPages()在后台的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

任何建议表示赞赏

是的,这是一个替代问题.一切都在…& list(即你的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,但是我必须引用所有内容或避免使用空格. (你的总数= $((总小计))也会有用.)
> pexec的选项:

> – normal-redirection意味着将所有输出流从子进程重定向到pexec的输出流. (如果两个进程想要同时写入,我不确定这会导致一些混淆.)
> –environment hostname将每次执行的不同参数作为环境变量传递.否则它将是一个简单的命令行参数.
> –number ${#ARRAY [*]}(在我们的例子中得到–number 4)确保所有进程将并行启动,而不是只有我们有CPU或其他一些启发式启动. (这适用于网络往返工作.对于CPU绑定或带宽限制的东西,较小的数字会更好.)
> –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

我们可以看到,在我的单处理器系统上,所有内容都尽可能并行运行.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读