Bash 多个 cURL 请求问题

Bash Multiple cURL request Issue

脚本提交文件和Post提交,提交样本的API服务returns"task_id"#task.csv

#file_submitter.sh

#!/bin/bash

for i in $(find   -type f);do
        task_id="$(curl -s -F file=@$i http://X.X.X.X:8080/api/abc/v1/upload &)"
        echo "$task_id" >> task.csv
done

运行 方法:

$./submitter.sh /home/files/

结果:(这里的 761 和 762 是 API 服务提交样本的 task_id )

#task.csv

{"task_url": "http://X.X.X.X:8080/api/abc/v1/task/761"}
{"task_url": "http://X.X.X.X:8080/api/abc/v1/task/762"}

我给出了整个文件夹路径(find -type f)来查找目录中的所有文件以上传文件。现在,我正在使用“&”运算符 submit/upload 文件夹中的文件,这些文件将从 API 服务(stdout)生成 'task_id',我想要 'task_id'( stdout) 将其存储在 'task.csv' 中。但是上传带 "&" 和不带 "&" 的文件所花费的时间是相同的。有没有更多的提交方法parallel/faster?有什么建议吗?

命令替换中的命令,$(),在子shell中运行;所以在这里你在子 shell 的后台发送 curl 命令,而不是父 shell.

摆脱命令替换,只需执行:

curl -s -F file=@$i http://X.X.X.X:8080/api/abc/v1/upload >task.csv &

您是在告诉 shell 在命令替换 ($()) 内部并行化。那不会做你想要的。试试这个:

#!/bin/bash

for i in $(find   -type f);do
        curl -s -F file=@$i http://X.X.X.X:8080/api/abc/v1/upload &
done > task.csv
#uncomment next line if you want the script to pause until the last curl is done
#wait

这会将 curl 置于后台并将其输出保存到 task.csv

您可以将 xargs-P 选项一起使用:

find "" -type f -print0 |
xargs -0 -P 5 -I{} curl -s -F file='@{}' http://X.X.X.X:8080/api/abc/v1/upload >> task.csv

这将通过并行启动 5 个 curl 进程来减少总执行时间。

anubhava 建议使用 xargs-P 选项:

find "" -type f -print0 |
xargs -0 -P 5  curl -s -F file=@- http://X.X.X.X:8080/api/abc/v1/upload >> task.csv

但是,并行附加到同一个文件通常不是一个好主意:您确实需要了解很多有关此版本 OS 缓冲输出的信息,以确保安全。这个例子说明了原因:

#!/bin/bash

size=3000

myfile=/tmp/myfile$$
rm $myfile

echo {a..z} | xargs -P26 -n1 perl -e 'print ((shift)x'$size')' >> $myfile

cat $myfile | perl -ne 'for(split//,$_){
  if($_ eq $l) {
    $c++
  } else {
    /\n/ and next;
    print $l,1+$c," "; $l=$_; $c=0;
  }
}'
echo

使用 size=10 您将始终获得(顺序可能不同):

1 d10 i10 c10 n10 h10 x10 l10 b10 u10 w10 t10 o10 y10 z10 p10 j10 q10 s10 v10 r10 k10 e10 m10 f10 g10

这意味着该文件包含 10 个 d,然后是 10 个 i,然后是 10 个 c,依此类推。 IE。 26 个作业的输出没有混合。

但将其更改为 size=30000,您会得到如下内容:

1 c30000 d30000 l8192 g8192 t8192 g8192 t8192 g8192 t8192 g5424 t5424 a8192 i16384 s8192 i8192 s8192 i5424 s13616 f16384 k24576 p24576 n8192 l8192 n8192 l13616 n13616 r16384 u8192 r8192 u8192 r5424 u8192 o16384 b8192 j8192 b8192 j8192 b8192 j8192 b5424 a21808 v8192 o8192 v8192 o5424 v13616 j5424 u5424 h16384 p5424 h13616 x8192 m8192 k5424 m8192 q8192 f8192 m8192 f5424 m5424 q21808 x21808 y30000 e30000 w30000

首先是 30K c,然后是 30K d,然后是 8k l,然后是 8K g,8K t,然后是另一个 8k g,依此类推。 IE。 26 个输出混合在一起。非常不好。

出于这个原因,我建议不要并行附加到同一个文件:存在竞争条件的风险,而且通常可以避免。

在你的情况下,你可以简单地使用 GNU Parallel 而不是 xargs,因为 GNU Parallel 可以防止这种竞争条件:

find "" -type f -print0 |
parallel -0 -P 5  curl -s -F file=@{} http://X.X.X.X:8080/api/abc/v1/upload >> task.csv