Automation با curl و jq

چرا curl و jq؟

در دنیای امروز بسیاری از سرویس‌ها و ابزارها از طریق REST API با هم ارتباط برقرار می‌کنند. شما ممکن است بخواهید:

  • وضعیت یک deployment را از CI/CD سیستم بگیرید
  • یک notification به Slack بفرستید
  • اطلاعات یک سرور را از Cloud Provider بخوانید
  • یک webhook را trigger کنید

این کارها همه با HTTP request انجام می‌شوند و پاسخ معمولاً JSON است. دو ابزار کلیدی برای این کار:

  • curl — ارسال HTTP request
  • jq — خواندن و پردازش JSON

curl: ارسال HTTP Request

curl یکی از رایج‌ترین ابزارهای خط فرمان برای کار با APIها است. در هفته‌ی سوم با آن آشنا شدید، اما اینجا روی استفاده در automation تمرکز می‌کنیم.

GET Request

ساده‌ترین حالت، خواندن داده:

1curl -s https://api.github.com/users/torvalds
  • -s: silent mode — progress bar را نشان نمی‌دهد

خروجی یک JSON است. برای دیدن فقط status code:

1curl -s -o /dev/null -w "%{http_code}" https://api.github.com/users/torvalds

POST Request با JSON

برای ارسال داده به API:

1curl -X POST https://httpbin.org/post \
2  -H "Content-Type: application/json" \
3  -H "Authorization: Bearer $API_TOKEN" \
4  -d '{"version": "v1.2.3", "environment": "production"}'
  • -X POST: متد HTTP
  • -H: اضافه کردن header
  • -d: بدنهٔ request (data)

Error Handling در curl

به‌طور پیش‌فرض، curl حتی اگر سرور 404 یا 500 برگرداند، exit code 0 می‌دهد. برای automation باید این رفتار را تغییر دهید:

1# با -f، کدهای خطا باعث exit code غیرصفر می‌شوند
2if curl -fsSL https://api.example.com/health -o /dev/null; then
3  echo "Service is healthy"
4else
5  echo "ERROR: Service health check failed" >&2
6  exit 1
7fi
  • -f: fail on HTTP errors (4xx, 5xx)
  • -S: در صورت خطا، پیام را نشان بده
  • -L: redirect را دنبال کن

jq: پردازش JSON

وقتی یک API پاسخ JSON می‌دهد، نیاز دارید بخش‌های خاصی از آن را استخراج کنید. jq دقیقاً برای این کار ساخته شده.

نصب jq

در هفته‌ی دوم احتمالاً آن را نصب کردید، اما اگر نه:

1command -v jq || sudo apt install -y jq

استخراج یک فیلد

فرض کنید این JSON را دارید:

1{
2  "name": "nginx",
3  "version": "1.24.0",
4  "status": "running"
5}

برای گرفتن فقط version:

1echo '{"name":"nginx","version":"1.24.0","status":"running"}' | jq -r '.version'

خروجی:

11.24.0
  • .version: مسیر فیلد در JSON
  • -r: raw output (بدون quote)

کار با Array

فرض کنید لیست deploymentها را می‌خواهید:

1[
2  {"id": 1, "status": "success"},
3  {"id": 2, "status": "failed"},
4  {"id": 3, "status": "success"}
5]

گرفتن همهٔ idها:

1echo '[{"id":1,"status":"success"},{"id":2,"status":"failed"}]' | jq -r '.[].id'

خروجی:

11
22

فیلتر کردن فقط موفق‌ها:

1jq -r '.[] | select(.status == "success") | .id'

مثال عملی: چک کردن وضعیت CI

فرض کنید می‌خواهید وضعیت آخرین GitHub Actions workflow را بررسی کنید:

 1#!/usr/bin/env bash
 2set -euo pipefail
 3
 4REPO="owner/repo"
 5TOKEN="${GITHUB_TOKEN:?GITHUB_TOKEN not set}"
 6
 7# گرفتن آخرین workflow run
 8response=$(curl -fsSL \
 9  -H "Authorization: Bearer $TOKEN" \
10  -H "Accept: application/vnd.github+json" \
11  "https://api.github.com/repos/$REPO/actions/runs?per_page=1")
12
13# استخراج status با jq
14status=$(echo "$response" | jq -r '.workflow_runs[0].status')
15conclusion=$(echo "$response" | jq -r '.workflow_runs[0].conclusion')
16
17echo "Workflow status: $status"
18echo "Conclusion: $conclusion"
19
20if [[ "$conclusion" != "success" ]]; then
21  echo "ERROR: Last workflow did not succeed" >&2
22  exit 1
23fi
24
25echo "All checks passed"

مثال عملی: ارسال Notification به Slack

Slack webhook را می‌توان برای ارسال پیام استفاده کرد:

 1#!/usr/bin/env bash
 2set -euo pipefail
 3
 4WEBHOOK_URL="${SLACK_WEBHOOK_URL:?SLACK_WEBHOOK_URL not set}"
 5MESSAGE="$1"
 6
 7payload=$(jq -n --arg text "$MESSAGE" '{text: $text}')
 8
 9if curl -fsSL -X POST "$WEBHOOK_URL" \
10  -H "Content-Type: application/json" \
11  -d "$payload" > /dev/null; then
12  echo "Notification sent"
13else
14  echo "ERROR: Failed to send notification" >&2
15  exit 1
16fi

استفاده:

1export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
2./notify.sh "Deployment to production completed successfully"

توجه کنید که payload را با jq -n ساختیم — این روش امن‌تر از string interpolation است چون jq خودش escape می‌کند.

ساختن JSON با jq

به‌جای نوشتن JSON به‌صورت دستی، می‌توانید با jq بسازید:

 1#!/usr/bin/env bash
 2
 3version="v1.2.3"
 4environment="production"
 5timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
 6
 7payload=$(jq -n \
 8  --arg ver "$version" \
 9  --arg env "$environment" \
10  --arg ts "$timestamp" \
11  '{
12    version: $ver,
13    environment: $env,
14    deployed_at: $ts
15  }')
16
17echo "$payload"

خروجی:

1{
2  "version": "v1.2.3",
3  "environment": "production",
4  "deployed_at": "2026-09-17T10:30:00Z"
5}

این روش امن‌تر است چون نیازی به escape کردن دستی quote یا newline ندارید.

تمرین

  1. یک درخواست به https://api.github.com/users/YOUR_USERNAME بفرستید و با jq فقط فیلدهای name و public_repos را نمایش دهید
  2. همان API را فراخوانی کنید و اگر public_repos بیشتر از 10 بود، پیام موفقیت چاپ کنید، در غیر این صورت با exit code 1 خارج شوید
  3. یک اسکریپت بنویسید که یک health check endpoint را فراخوانی کند و اگر status code چیزی غیر از 200 بود، با curl retry کند (حداکثر 3 بار)
    1curl -i https://ec2.us-east-1.amazonaws.com/ping

منابع یادگیری

مستندات و مقالات

ویدیو