【有偿】脚本大佬进,同时多并发执行curl

96次阅读

共计 9432 个字符,预计需要花费 24 分钟才能阅读完成。

要求同一 0.1s 内把 1 个 post 的 curl 命令多并发 5 次 /10 次同一时间发出请求

脚本要求 bash test.sh

请输入并发次数: 例如 5 次就输入 5

输入需要同时并发执行的 curl 命令: (以下命令只做举例非实际要执行的命令,要求可自定义。)
curl ‘https://otheve.beacon.qq.com/analytics/v2_upload’  -H ‘Host: otheve.beacon.qq.com’  -H ‘Content-Type: jce’  -H ‘Connection: keep-alive’  -H ‘Accept: */*’  -H ‘User-Agent: com.sogou.sogouinput.BaseKeyboard/34674 CFNetwork/1237 Darwin/20.4.0’  -H ‘Content-Length: 469’  -H ‘Accept-Language: zh-cn’  -H ‘Accept-Encoding: gzip, deflate, br’  

然后回车即可

要求同一时刻发出 5 次上述 curl 请求。

网上找的方法好多都不是同一时刻发出这个 post,每个请求有 0.5- 1 秒左右的时差无法满足要求。
最先给出的老板我会给个支付宝口令红包。

网友回复:

注册 使用 ’&’+wait 实现“多线程”

a8866051 直接 xargs –P 5 curl xxxx 不行吗?

mjj666zzz 这是撸腾讯啥接口?

liugogal 白 ** 大厂?

阿里云 不是,只是随便拿一个举例子

大吊 bash + curl 就只能多进程吧..

a8866051 curl –parallel –parallel-immediate –parallel-max 10  

teardrops 私聊我报价吧,用 python 给你写

zxxx 是多进程但是没法同时并发,这个只是执行完一个马上扔后台然后执行下一个

注册 用管道呢,要不就换个性能高的机器

注册 python 不是伪多线程嘛

mjj666zzz 这种就用其它语言实现嘛,脚本语言不适合干这些,你延时需要 0.1s,那就用 cpp,先开几个线程等着,线程每 10ms 检查一次,有请求就立马发送不就完了,这样才能真正的保证延时

heibaihuali 就是 cc 攻击嘛,github 上很多的

heibaihuali for (int i=0;i<10;i++)  pthread_create(xxxx)

好鸭 python 可以 gil 锁并不影响并发

sdqu python 异步 gather 应该是同时执行的

Mr.lin 不是拿来攻击,我需要也就 5 -20 并发执行一次,不是几百

honus 大佬直接报个价吧,因为收益极小特多大的价钱我应该给不了

a8866051 性能高的用这方法也没法 5 -10 次执行在 0.1s 内发起全部执行命令,至少 2,3 秒

注册 好像这样就行了,你可以试一下,最后的 & 要保留 read -p “ 输入并发数: ” num for i in {1..$num};do curl https://www.baidu.com & done 复制代码

注册 执行直接没反应。。。

好鸭 追求性能的话可以 golang,不着急的话明天,一个甲骨文?

a8866051 测试请求无法同一时刻发出

251768938 要求 10ms 以内同时发出么?

a8866051 https://github.com/jneeee/qos_tool 我写过一个 python qos 脚本,并发可以很大。拿去改一改不是很难

zxxx 越短越好,最好同一时刻

jaymi 主要是自己太菜了

a8866051 PHP 是最好的语言。workerman 版本:https://www.workerman.net/doc/workerman/components/workerman-http-client.html swoole 版本:0. https://wiki.swoole.com/#/coroutine/multi_call 1. https://wiki.swoole.com/#/coroutine/wait_group

a8866051 cli 应用,配和 swoole-cli 写一些 shell 脚本,贼爽贼方便

注册 bash 肯定不稳定,一个是每个进程启动时间就在 20 毫秒左右浮动了。然后还有 tcp,tls 过程。送你一个我自己的羊毛脚本。会针对每个链接先发起一个请求做预热 keepalive 或者 http2 链接,然后复用之前的链接来减少握手阶段造成的误差,20 并发测试百度在 20 毫秒以内。把 POST 改成自己需要的就行了 package main import (“fmt”         “io”         “io/ioutil”         “log”         “net”         “net/http”         “net/url”         “strings”         “sync”         “time”) const co = 20 func main() {         wg := sync.WaitGroup{}         wg2 := sync.WaitGroup{}         client := &http.Client{                 Transport: &http.Transport{                         DialContext: (&net.Dialer{                                 Timeout:   30 * time.Second,                                 KeepAlive: 30 * time.Second,}).DialContext,                         ForceAttemptHTTP2:   true,                         MaxIdleConns:        100,                         MaxIdleConnsPerHost: 100,                         IdleConnTimeout:     60 * time.Second,                 },                 Timeout: 20 * time.Second,         }         wg.Add(co)         wg2.Add(co)         for i := 0; i < co; i++ {go func(t int) {defer wg2.Done()                         // 建立链接,Keepalive                         r, err := client.Get(“http://www.baidu.com/recharge.php”)                         _, err = io.Copy(ioutil.Discard, r.Body)                         if err != nil {log.Fatalln(err)                         }                         if t == 0 {fmt.Println(“ 预热完成, 即将执行 ”)                                 time.Sleep(time.Second * 5)                         }                         // 线程同步                         wg.Done()                         wg.Wait()                         // 同步发起请求                         formData := url.Values{“username”: {“x”},                                 “key”:      {“xxx”},                         }                         req, err := http.NewRequest(“POST”, “http://www.baidu.com/recharge.php”, strings.NewReader(formData.Encode()))                         if err != nil {log.Fatalln(err)                         }                         req.Header.Set(“x-requested-with”, “XMLHttpRequest”)                         req.Header.Set(“Content-Type”, “application/x-www-form-urlencoded”)                         req.Header.Set(“cookie”, “account=528250;”)                         resp, err := client.Do(req)                         if err != nil {log.Fatalln(err)                         }                         fmt.Println(“ 完成时间 ”, time.Now().String())                         defer func() {                                 _ = resp.Body.Close()                         }()                         body, err := ioutil.ReadAll(resp.Body)                         if err != nil {log.Fatalln(err)                         }                         fmt.Println(string(body))                 }(i)         }         wg2.Wait()}

注册 c 语言 原生 tcp 小程序 可以吧

host0108 晚上睡不着,用 Go 瞎鸡儿写的一个并发 curl 工具(curl-pnrt)能应付楼主的需求 和原版有点区别 (工具在附件上 编译环境是 centos 7 amd64 版本,mac 是 m1 就没贴了) 附件:https://wwi.lanzoup.com/iYhds09cnokj 使用步骤:可以直接浏览器 [Copy as cURL] 进行改造一下就好了 比如:curl ‘https://static.leetcode.cn/cn-mono-assets/production/main/runtime~main.8725179e.js’   -H ‘sec-ch-ua: “.Not/A)Brand”;v=”99″, “Google Chrome”;v=”103″, “Chromium”;v=”103″‘   -H ‘Referer: https://leetcode.cn/’   -H ‘DNT: 1’   -H ‘sec-ch-ua-mobile: ?0’   -H ‘User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36’   -H ‘sec-ch-ua-platform: “macOS”‘   –compressed 复制代码 需要把 –compressed 去掉,url 的地址部分 前缀需要加个 -t(懒得写位置顺序)-c 后面紧跟的是并发量 ./curl-pnrt -c 900 -t ‘https://static.leetcode.cn/cn-mono-assets/production/main/runtime~main.8725179e.js’   -H ‘sec-ch-ua: “.Not/A)Brand”;v=”99″, “Google Chrome”;v=”103″, “Chromium”;v=”103″‘   -H ‘Referer: https://leetcode.cn/’   -H ‘DNT: 1’   -H ‘sec-ch-ua-mobile: ?0’   -H ‘User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36’   -H ‘sec-ch-ua-platform: “macOS”‘  复制代码 其他的几乎一样 (除非就没写那个功能,哈哈~) -c: 就是想要的并发数 1000 0.3s 左右(可能是同一个地域的服务器,所以快些)-t: 目标 url -X: 默认 get , 比如:-X POST 就是 post -H: 和原版 crul 一样 -d: get 的格式和原版一样 key1=xxx,post 的话和原版一样,不过记得加个 -H ‘Content-Type: xxxx/xxx’ 的类型 -p: 打印响应的信息 效果如下:源码:package main import (“bytes”         “flag”         “fmt”         “io”         “io/ioutil”         “net/http”         “net/url”         “strings”         “sync”         “time”) type httpClient struct {client *http.Client} type stringsValue []string func newStringsValue(val string, p *[]string) *stringsValue {if val != “” {                 *p = append(*p, val)         }         return (*stringsValue)(p) } func (s *stringsValue) Set(val string) error {*s = append(*s, val)         return nil } func (s *stringsValue) Get() interface{} {return []string(*s) } func (s *stringsValue) String() string { return fmt.Sprintln([]string(*s)) } func main() {         ht := &httpClient{}         ht.client = &http.Client{Transport: &http.Transport{                         MaxIdleConns:        900,                         MaxIdleConnsPerHost: 900,                         IdleConnTimeout:     time.Second * 30,},         }         now := time.Now()         httpUrl := “”         headers := &[]string{}         flag.StringVar(&httpUrl, “t”, “”, “Please enter the correct URL: http/https”)         count := flag.Int(“c”, 1, “Number of concurrent runs: Default is 1”)         flag.Var(newStringsValue(“”, headers), “H”, “Example Imitate the curl command -h”)         protocol := flag.String(“X”, “GET”, “-X  POST|GET”)         data := flag.String(“d”, “”, “support  JSON”)         var isPrintResp bool         flag.BoolVar(&isPrintResp, “p”, false, “Whether to output RESP”)         //userAgent := flag.String(“A”, “”, “User-Agent”)         flag.Parse()         if httpUrl == “” {                 fmt.Println(“Please enter the correct URL”)         }         headerMap := map[string]string{}         for _, s := range *headers {                 split := strings.Split(s, “: “)                 if len(split) == 2 {headerMap[split[0]] = split[1]                 } else {fmt.Println(“header fail”)                         return                 }         }         //fmt.Println(*headers)         waitGroup := sync.WaitGroup{}         *protocol = strings.ToUpper(*protocol)         //time.Sleep(3 * time.Second)         for i := 0; i < *count; i++ {fmt.Printf(“”)                 go func() {                         waitGroup.Add(1)                         if *protocol == “GET” {values := url.Values{}                                 if data != nil && *data != “*” {for _, s := range strings.Split(*data, “&”) {split := strings.Split(s, “=”)                                                 if len(split) == 2 {values.Set(split[0], split[1])                                                 }                                         }                                 }                                 if resp, err := ht.GET(httpUrl, values); err != nil {if err == io.EOF {                                                 if isPrintResp {                                                         fmt.Println(string(resp))                                                 }                                         }                                         fmt.Println(err)                                 } else {if isPrintResp {                                                 fmt.Println(string(resp))                                         }                                 }                         } else if *protocol == “POST” {if resp, err := ht.POST(httpUrl, []byte(*data), headerMap); err != nil {if err == io.EOF {                                                 if isPrintResp {                                                         fmt.Println(string(resp))                                                 }                                         }                                         fmt.Println(err)                                 } else {if isPrintResp {                                                 fmt.Println(string(resp))                                         }                                 }                         }                         waitGroup.Done()}()}         waitGroup.Wait()         fmt.Println()         fmt.Printf(“time spent: %v s”, time.Since(now).Seconds())         fmt.Println()} func (ht *httpClient) GET(httpUrl string, queryStr url.Values) (res []byte, err error) {var Url *url.URL         Url, err = url.Parse(httpUrl)         if err != nil {fmt.Printf(“parse fail:%v”, err)                 return nil, err         }         Url.RawQuery = queryStr.Encode()         resp, err := ht.client.Get(Url.String())         if err != nil {fmt.Println(“err:”, err)                 return nil, err         }         defer resp.Body.Close()         return ioutil.ReadAll(resp.Body) } func (ht *httpClient) POST(httpUrl string, jsonByte []byte, headerMap map[string]string) (res []byte, err error) {var Url *url.URL         Url, err = url.Parse(httpUrl)         if err != nil {fmt.Printf(“parse fail:%v”, err)                 return nil, err         }         request, err := http.NewRequest(“POST”, Url.String(), bytes.NewBuffer(jsonByte))         if err != nil {fmt.Println(“err:”, err)                 return nil, err         }         for k, v := range headerMap {request.Header.Set(k, v)         }         //request.Header.Set(“Content-Type”, “application/json”)         resp, err := ht.client.Do(request)         if err != nil {fmt.Println(“err:”, err)                 return nil, err         }         defer resp.Body.Close()         return ioutil.ReadAll(resp.Body) } 复制代码

正文完
 0