You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用autocannon POST命令运行clinic.js?执行报错求助

解决zsh下clinic flame搭配带复杂POST体的autocannon命令时的event not found错误

问题原因

zsh的引号解析和历史事件扩展机制导致的:你用单引号包裹整个--on-port的参数内容,但其中autocannon的-b参数又用了单引号嵌套,这会让zsh提前终止外层单引号的解析,后续的括号等字符被误识别为历史事件查询,从而抛出event not found: )错误。单独运行autocannon时没有这个问题,是因为此时的引号嵌套解析逻辑和嵌套在--on-port参数里的场景不同。

解决方案

方案1:将POST请求体写入文件,避免命令行引号嵌套

  1. 创建request-body.json文件,把原命令中-b后面的JSON内容复制进去:
{"operationName":"getEcosystemAdminSessionSummary","variables":{"input":{"pageNum":1,"limit":25,"sessionStatus":"UPCOMING","selectedFilters":[{"type":"num","values":["25"]}],"dateTimeSort":1}},"query":"query getEcosystemAdminSessionSummary($input: SessionSummaryV3Input!) {\n  getEcosystemAdminSessionSummary(input: $input) {\n    sessions {\n      id\n      subject\n      subjectId\n      sessionDescription\n      status\n      sessionType\n      participants(needsFeedbackInfo: true) {\n        user {\n          id\n          profile {\n            firstName\n            lastName\n            profileId\n            profilePicture {\n              src\n              __typename\n            }\n            phoneNumber\n            status\n            __typename\n          }\n          ... on PAASUser {\n            ecosystemProfile {\n              status\n              __typename\n            }\n            __typename\n          }\n          email {\n            address\n            __typename\n          }\n          __typename\n        }\n        userType\n        joinedTime\n        joinedTimeDelta\n        leftTime\n        sessionPayoutStatus\n        tutorBasePaymentAmount\n        remaining\n        hourlyRate\n        hasPendingFeedback\n        hasAssociatedFeedbackForm\n        feedbackSubmitDate\n        feedbackSubmitBy\n        feedbackEditedBy\n        participantFeedbackForm {\n          id\n          formType\n          __typename\n        }\n        description\n        __typename\n      }\n      numLeaders\n      numLearners\n      maxStudents\n      tutorReviews {\n        revieweeId\n        __typename\n      }\n      date\n      startTime\n      endTime\n      processingTime\n      cancellationPolicyTime\n      timeZoneId\n      recurringDays\n      recurringSessionId\n      weeksRecurring\n      weeksRepeat\n      recurringStartDate\n      recurringEndDate\n      tutoringAmount\n      meetingSolution\n      isInPerson\n      isPaid\n      ecosystemId\n      gradeLevel\n      gradeLevels\n      schools {\n        id\n        name\n        __typename\n      }\n      joinUrl\n      sessionCompletionStatus\n      zoomOptions {\n        tutorflyBookerId\n        meetingId\n        join_url\n        host_id\n        start_url\n        password\n        __typename\n      }\n      lessonspaceOptions {\n        roomId\n        __typename\n      }\n      uploadedFiles {\n        method\n        fileNames\n        __typename\n      }\n      physicalSessionOptions {\n        locationName\n        locationPoint {\n          type\n          coordinates\n          __typename\n        }\n        __typename\n      }\n      program {\n        id\n        name\n        shortName\n        sessions {\n          sessionJoinMinutesPrior\n          sessionRecordingsProfileTypes\n          __typename\n        }\n        subBoard {\n          enabled\n          visibleToTutors\n          __typename\n        }\n        __typename\n      }\n      subRequests {\n        id\n        userId\n        status\n        __typename\n      }\n      courseSection {\n        name\n        maxEnrollments\n        enrolledStudentsAmt\n        programs {\n          id\n          name\n          sessions {\n            sessionJoinMinutesPrior\n            sessionRecordingsProfileTypes\n            zoomEnabled\n            __typename\n          }\n          __typename\n        }\n        perUserRate\n        currentUserIsEnrolled\n        __typename\n      }\n      sessionFiles {\n        id\n        filename\n        url\n        creator\n        __typename\n      }\n      __typename\n    }\n    hasMore\n    totalSessionCount\n    __typename\n  }\n}\n"}
  1. 修改clinic flame命令,用-b @request-body.json读取文件内容:
clinic flame --on-port='autocannon -t 30 -c 100 -m POST -H "Authorization":"Bearer .eyJpZC" -H "review-app-secret-key":"9013a568aaeaa" -H "ecosystem-profile-id":"eco17" -H "Content-Type: application/json" -b @request-body.json http://localhost:7269/api/graphql' -- node ./dist/src/index.js

方案2:转义引号和特殊字符,适配zsh解析

如果不想用文件,需要对原命令中的引号和zsh特殊字符(比如!、$)进行转义:

  • 将外层的单引号改为双引号
  • 转义内部所有双引号(用\")
  • 转义所有$符号(用\$,避免zsh解析为变量)
  • 转义!符号(用\!,避免触发历史事件扩展)

最终命令如下:

clinic flame --on-port="autocannon -t 30 -c 100 -m POST -H \"Authorization\":\"Bearer .eyJpZC\" -H \"review-app-secret-key\":\"9013a568aaeaa\" -H \"ecosystem-profile-id\":\"eco17\" -H \"Content-Type: application/json\" -b \"{\\\"operationName\\\":\\\"getEcosystemAdminSessionSummary\\\",\\\"variables\\\":{\\\"input\\\":{\\\"pageNum\\\":1,\\\"limit\\\":25,\\\"sessionStatus\\\":\\\"UPCOMING\\\",\\\"selectedFilters\\\":[{\\\"type\\\":\\\"num\\\",\\\"values\\\":[\\\"25\\\"]}],\\\"dateTimeSort\\\":1}},\\\"query\\\":\\\"query getEcosystemAdminSessionSummary(\\\$input: SessionSummaryV3Input!) {\\n  getEcosystemAdminSessionSummary(input: \\\$input) {\\n    sessions {\\n      id\\n      subject\\n      subjectId\\n      sessionDescription\\n      status\\n      sessionType\\n      participants(needsFeedbackInfo: true) {\\n        user {\\n          id\\n          profile {\\n            firstName\\n            lastName\\n            profileId\\n            profilePicture {\\n              src\\n              __typename\\n            }\\n            phoneNumber\\n            status\\n            __typename\\n          }\\n          ... on PAASUser {\\n            ecosystemProfile {\\n              status\\n              __typename\\n            }\\n            __typename\\n          }\\n          email {\\n            address\\n            __typename\\n          }\\n          __typename\\n        }\\n        userType\\n        joinedTime\\n        joinedTimeDelta\\n        leftTime\\n        sessionPayoutStatus\\n        tutorBasePaymentAmount\\n        remaining\\n        hourlyRate\\n        hasPendingFeedback\\n        hasAssociatedFeedbackForm\\n        feedbackSubmitDate\\n        feedbackSubmitBy\\n        feedbackEditedBy\\n        participantFeedbackForm {\\n          id\\n          formType\\n          __typename\\n        }\\n        description\\n        __typename\\n      }\\n      numLeaders\\n      numLearners\\n      maxStudents\\n      tutorReviews {\\n        revieweeId\\n        __typename\\n      }\n      date\\n      startTime\\n      endTime\\n      processingTime\\n      cancellationPolicyTime\\n      timeZoneId\\n      recurringDays\\n      recurringSessionId\\n      weeksRecurring\\n      weeksRepeat\\n      recurringStartDate\\n      recurringEndDate\\n      tutoringAmount\\n      meetingSolution\\n      isInPerson\\n      isPaid\\n      ecosystemId\\n      gradeLevel\\n      gradeLevels\\n      schools {\\n        id\\n        name\\n        __typename\\n      }\n      joinUrl\\n      sessionCompletionStatus\\n      zoomOptions {\\n        tutorflyBookerId\\n        meetingId\\n        join_url\\n        host_id\\n        start_url\\n        password\\n        __typename\\n      }\n      lessonspaceOptions {\\n        roomId\\n        __typename\\n      }\n      uploadedFiles {\\n        method\\n        fileNames\\n        __typename\\n      }\n      physicalSessionOptions {\\n        locationName\\n        locationPoint {\\n          type\\n          coordinates\\n          __typename\\n        }\n        __typename\\n      }\n      program {\\n        id\\n        name\\n        shortName\\n        sessions {\\n          sessionJoinMinutesPrior\\n          sessionRecordingsProfileTypes\\n          __typename\\n        }\n        subBoard {\\n          enabled\\n          visibleToTutors\\n          __typename\\n        }\n        __typename\\n      }\n      subRequests {\\n        id\\n        userId\\n        status\\n        __typename\\n      }\n      courseSection {\\n        name\\n        maxEnrollments\\n        enrolledStudentsAmt\\n        programs {\\n          id\\n          name\\n          sessions {\\n            sessionJoinMinutesPrior\\n            sessionRecordingsProfileTypes\\n            zoomEnabled\\n            __typename\\n          }\n          __typename\\n        }\n        perUserRate\\n        currentUserIsEnrolled\\n        __typename\\n      }\n      sessionFiles {\\n        id\\n        filename\\n        url\\n        creator\\n        __typename\\n      }\n      __typename\\n    }\n    hasMore\\n    totalSessionCount\\n    __typename\\n  }\n}\\n\"}\" http://localhost:7269/api/graphql" -- node ./dist/src/index.js

方案3:用脚本封装autocannon命令

  1. 创建load-test.sh脚本,内容如下:
#!/bin/bash
autocannon -t 30 -c 100 -m POST \
  -H "Authorization":"Bearer .eyJpZC" \
  -H "review-app-secret-key":"9013a568aaeaa" \
  -H "ecosystem-profile-id":"eco17" \
  -H "Content-Type: application/json" \
  -b '{"operationName":"getEcosystemAdminSessionSummary","variables":{"input":{"pageNum":1,"limit":25,"sessionStatus":"UPCOMING","selectedFilters":[{"type":"num","values":["25"]}],"dateTimeSort":1}},"query":"query getEcosystemAdminSessionSummary($input: SessionSummaryV3Input!) {\n  getEcosystemAdminSessionSummary(input: $input) {\n    sessions {\n      id\n      subject\n      subjectId\n      sessionDescription\n      status\n      sessionType\n      participants(needsFeedbackInfo: true) {\n        user {\n          id\n          profile {\n            firstName\n            lastName\n            profileId\n            profilePicture {\n              src\n              __typename\n            }\n            phoneNumber\n            status\n            __typename\n          }\n          ... on PAASUser {\n            ecosystemProfile {\n              status\n              __typename\n            }\n            __typename\n          }\n          email {\n            address\n            __typename\n          }\n          __typename\n        }\n        userType\n        joinedTime\n        joinedTimeDelta\n        leftTime\n        sessionPayoutStatus\n        tutorBasePaymentAmount\n        remaining\n        hourlyRate\n        hasPendingFeedback\n        hasAssociatedFeedbackForm\n        feedbackSubmitDate\n        feedbackSubmitBy\n        feedbackEditedBy\n        participantFeedbackForm {\n          id\n          formType\n          __typename\n        }\n        description\n        __typename\n      }\n      numLeaders\n      numLearners\n      maxStudents\n      tutorReviews {\n        revieweeId\n        __typename\n      }\n      date\n      startTime\n      endTime\n      processingTime\n      cancellationPolicyTime\n      timeZoneId\n      recurringDays\n      recurringSessionId\n      weeksRecurring\n      weeksRepeat\n      recurringStartDate\n      recurringEndDate\n      tutoringAmount\n      meetingSolution\n      isInPerson\n      isPaid\n      ecosystemId\n      gradeLevel\n      gradeLevels\n      schools {\n        id\n        name\n        __typename\n      }\n      joinUrl\n      sessionCompletionStatus\n      zoomOptions {\n        tutorflyBookerId\n        meetingId\n        join_url\n        host_id\n        start_url\n        password\n        __typename\n      }\n      lessonspaceOptions {\n        roomId\n        __typename\n      }\n      uploadedFiles {\n        method\n        fileNames\n        __typename\n      }\n      physicalSessionOptions {\n        locationName\n        locationPoint {\n          type\n          coordinates\n          __typename\n        }\n        __typename\n      }\n      program {\n        id\n        name\n        shortName\n        sessions {\n          sessionJoinMinutesPrior\n          sessionRecordingsProfileTypes\n          __typename\n        }\n        subBoard {\n          enabled\n          visibleToTutors\n          __typename\n        }\n        __typename\n      }\n      subRequests {\n        id\n        userId\n        status\n        __typename\n      }\n      courseSection {\n        name\n        maxEnrollments\n        enrolledStudentsAmt\n        programs {\n          id\n          name\n          sessions {\n            sessionJoinMinutesPrior\n            sessionRecordingsProfileTypes\n            zoomEnabled\n            __typename\n          }\n          __typename\n        }\n        perUserRate\n        currentUserIsEnrolled\n        __typename\n      }\n      sessionFiles {\n        id\n        filename\n        url\n        creator\n        __typename\n      }\n      __typename\n    }\n    hasMore\n    totalSessionCount\n    __typename\n  }\n}\n"}' \
  http://localhost:7269/api/graphql
  1. 给脚本添加执行权限:
chmod +x load-test.sh
  1. 运行clinic flame命令调用脚本:
clinic flame --on-port='./load-test.sh' -- node ./dist/src/index.js

内容的提问来源于stack exchange,提问作者Matt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 19:20:27