【问题标题】:Running a loop bash curl script with GNU Parallel使用 GNU Parallel 运行循环 bash curl 脚本
【发布时间】:2018-03-19 10:08:57
【问题描述】:

最近刚开始使用 bash 进行编程,遇到了 GNU Parallel,这正是我的项目所需要的。 有一个基本的循环脚本,用于循环遍历 ip 列表并 ping 一次。带有 ip 的列表会不断更新,由另一个脚本驱动。

对于多线程,我想使用 GNU Parallel。

我的想法是运行 10 个 Parallel 实例,每个实例将从列表中捕获一个 ip,将其插入 curl 命令并将其从列表中删除,因此其他实例不会拾取它。

#! /bin/bash
while true; do

while read -r ip; do
curl $ip >> result.txt
sed -i '1,1 d' iplist
done < ipslist
done

我不确定,运行 bash 脚本的正确方法是什么,在这种情况下,我能找到的每个解决方案都无法正常工作,事情变得一团糟。 我有一种感觉,这一切都可以用一行来完成,但是,出于我自己的原因,我更喜欢将它作为 bash 脚本运行。 将不胜感激任何帮助!

【问题讨论】:

  • 您是否使用它来检查哪些主机已启动并正在服务?也许使用nmap 更容易,而不是自己编写。我不确定nmap 是否真的可以执行 HTTP 请求,但只需检查 80/TCP 是否打开就足够了。
  • 感谢您的建议,我知道nmap和其他工具的至高无上,对于许多任务,但是,对于这个项目,我需要使用curl

标签: bash curl gnu-parallel


【解决方案1】:

Thomas 的解决方案看起来适合这种特殊情况。但是,如果您需要做的不仅仅是curl,那么我建议您创建一个函数:

#! /bin/bash

doit() {
  ip="$1"
  curl "$ip"
  echo do other stuff here
}
export -f doit

while true; do
  parallel -j10 doit < ipslist >> result.txt
done

如果您希望 ipslist 成为队列,以便以后可以将内容添加到队列中,并且您只希望 curled 一次:

tail -n+0 -f ipslist | parallel doit >> result.txt

现在您以后可以简单地向 ipslist 添加内容,GNU Parallel 也会 curl 这样做。

(使用 GNU 并行作为队列系统/批处理时有一个小问题 经理:您必须提交 JobSlot 数量的作业才可以 开始,然后你可以一次提交一个,作业就会开始 如果有空闲插槽,请立即使用。运行的输出或 已完成的作业会被保留,并且只会在 JobSlots 更多时打印 作业已经开始(除非你使用 --ungroup 或 --line-buffer,在 在这种情况下,作业的输出会立即打印)。例如。如果 你有 10 个工作槽,那么第一个完成的工作的输出将 仅在作业 11 开始时打印,并且第二个的输出 仅当作业 12 开始时才会打印已完成的作业。)

【讨论】:

    【解决方案2】:

    这对我有用:

    #!/bin/bash
    
    while true; do
      parallel -j10 curl '{}' < ipslist >> result.txt
    done
    

    如果这不是您想要的,请更新您的问题以澄清。

    【讨论】:

    • 虽然它看起来优雅而简单,但我宁愿不在脚本中使用并行命令,而是从终端并行运行脚本。由于脚本稍后会增长,最好将其保留为纯 bash。另外,我看不到您的解决方案如何避免一遍又一遍地使用同一行,但我可能错了。我需要类似:parallel -n0 script.sh ::: {1..10} 解决方案,但是,出于某种原因,它对我不起作用。
    • 请编辑您的问题以明确您需要什么,以及为什么该解决方案不起作用。
    • @NikolasK 它不起作用的原因很可能是您从多个进程并行读取和编辑同一个文件。如果没有比赛条件,很难做到正确。 @Thomas 的解决方案也可能更快,因为他不编辑 ipslist
    • @NikolasK 您知道您可以使用--embed 将 GNU Parallel 嵌入到 bash 脚本中吗?从版本 20180222 开始提供。
    【解决方案3】:

    我只会使用xargs。似乎没有多少人知道这一点,但除了将输入的每一行压缩在一行上的标准用法之外,还有更多的东西。也就是这个:

    echo -e "A\nB\nC\nD\nE" | xargs do_something
    

    基本上和这个意思是一样的:

    do_something A B C D E
    

    但是您可以使用-L 选项指定在一个块中处理多少行:

    echo -e "A\nB\nC\nD\nE" | xargs -L2 do_something
    

    将转化为:

    do_something A B
    do_something C D
    

    此外,您还可以使用-P 选项指定这些块中有多少并行运行。因此,要逐个处理行,并行度为 3,您会说:

    echo -e "A\nB\nC\nD\nE" | xargs -L1 -P3 do_something
    

    等等,你有适当的并行执行,使用基本的 unix 工具。

    唯一的问题是,您必须确保将输出分开。我不确定,以前是否考虑过这一点,但curl 案例的解决方案是这样的:

    cat url_list.txt | xargs -L1 -P10 curl -o paralell_#0.html
    

    #0 将被 cURL 替换为正在获取的 URL。详情请参阅手册:

    【讨论】:

      【解决方案4】:

      你可以这样做,它会起作用的:

      #! /bin/bash
      while true; do
      
         while read -r ip; do
            curl $ip >> result.txt &
            sed -i '1,1 d' iplist
         done < ipslist
      wait
      done
      

      【讨论】:

      • 如果我在 iplist 上使用 1000000 个 IP 进行测试,那么我的机器将停止响应。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-04
      • 2021-07-19
      • 1970-01-01
      • 1970-01-01
      • 2018-10-09
      • 2023-04-09
      • 1970-01-01
      相关资源
      最近更新 更多