Modern infrastructure scripts constantly interact with networks — checking service health, calling APIs, downloading files, and verifying connectivity. curl is the Swiss Army knife here, while nc (netcat) and ping handle lower-level checks. Combine them with jq for JSON and you can automate nearly any REST API workflow from bash.
1
curl — HTTP requests and API calls
BASH
# ── Basic requests ────────────────────────────────────────
curl https://api.example.com/status # GET
curl -s https://api.example.com/status # silent (no progress bar)
curl -sf https://api.example.com/status # silent + fail on HTTP error
curl -o output.json https://api.example.com/data # save to file
# ── With authentication ───────────────────────────────────
curl -H "Authorization: Bearer ${TOKEN}" https://api.example.com/users
curl -u "user:password" https://api.example.com/admin
curl -H "X-API-Key: ${API_KEY}" https://api.example.com/data
# ── POST with JSON body ───────────────────────────────────
curl -s -X POST https://api.example.com/alerts \
-H "Content-Type: application/json" \
-d "{\"level\": \"critical\", \"message\": \"Disk full\"}"
# ── POST with variable data ───────────────────────────────
HOSTNAME=$(hostname)
MESSAGE="CPU spike detected"
curl -s -X POST "${SLACK_WEBHOOK}" \
-H "Content-Type: application/json" \
-d "$(printf '{"text": "[%s] %s"}' "${HOSTNAME}" "${MESSAGE}")"
# ── Error handling ────────────────────────────────────────
response=$(curl -sf -w "%{http_code}" \
-o /tmp/response.json \
https://api.example.com/data)
if [[ "${response}" != "200" ]]; then
echo "API returned HTTP ${response}" >&2
cat /tmp/response.json >&2
exit 1
fi
# ── Retry with backoff ────────────────────────────────────
curl_with_retry() {
local url="${1}"
local max="${2:-3}"
local attempt=1
while (( attempt <= max )); do
curl -sf "${url}" && return 0
echo "Attempt ${attempt}/${max} failed — retrying..." >&2
sleep $(( attempt * 2 ))
(( attempt++ ))
done
return 1
}
2
jq — parse and build JSON
BASH
# ── Extract values from JSON API response ─────────────────
json='{"status":"ok","data":{"host":"prod-01","cpu":85,"mem":72}}'
echo "${json}" | jq '.status' # "ok"
echo "${json}" | jq -r '.status' # ok (no quotes)
echo "${json}" | jq -r '.data.host' # prod-01
echo "${json}" | jq -r '.data.cpu' # 85
# ── Assign to variables ───────────────────────────────────
cpu=$(echo "${json}" | jq -r '.data.cpu')
mem=$(echo "${json}" | jq -r '.data.mem')
echo "CPU: ${cpu}%, MEM: ${mem}%"
# ── Parse array of objects ───────────────────────────────
servers='[{"name":"web-01","status":"up"},{"name":"web-02","status":"down"}]'
echo "${servers}" | jq -r '.[].name' # all names
echo "${servers}" | jq -r '.[] | select(.status=="down") | .name'
# ── Real API call with jq processing ─────────────────────
curl -sf "https://api.github.com/repos/bash/bash/releases/latest" \
| jq -r '.tag_name' # latest bash release tag
# ── Build JSON for API call ───────────────────────────────
alert_json=$(jq -n \
--arg host "$(hostname)" \
--arg msg "Disk ${disk_pct}% full" \
--argjson pct "${disk_pct}" \
'{"host":$host,"message":$msg,"disk_percent":$pct}')
curl -sf -X POST "${ALERT_API}" \
-H "Content-Type: application/json" \
-d "${alert_json}"
3
Network connectivity checks
BASH
# ── ping — ICMP connectivity ──────────────────────────────
ping -c 1 -W 2 8.8.8.8 >/dev/null 2>&1 \
&& echo "Internet OK" || echo "No internet"
# ── nc (netcat) — TCP port check ─────────────────────────
nc -z -w 3 prod-db-01 3306 && echo "DB port open"
nc -z -w 3 prod-web-01 443 && echo "HTTPS open"
# ── Check multiple services ───────────────────────────────
check_service() {
local host="${1}" port="${2}" name="${3:-${host}:${port}}"
if nc -z -w 3 "${host}" "${port}" 2>/dev/null; then
printf " ✔ %-20s UP\n" "${name}"
return 0
else
printf " ✘ %-20s DOWN\n" "${name}" >&2
return 1
fi
}
check_service prod-db-01 3306 "MySQL"
check_service prod-cache-01 6379 "Redis"
check_service prod-mq-01 5672 "RabbitMQ"
check_service api.example.com 443 "External API"
# ── HTTP health check ─────────────────────────────────────
check_http() {
local url="${1}"
local code
code=$(curl -sf -o /dev/null -w "%{http_code}" \
--max-time 5 "${url}" 2>/dev/null)
[[ "${code}" == "200" ]] && return 0 || return 1
}
check_http "http://localhost:8080/health" \
&& echo "App healthy" || echo "App unhealthy"
vriddh@prod-01:~/scripts$./check_services.sh
✔ MySQL UP
✔ Redis UP
✘ RabbitMQ DOWN
✔ External API UP
vriddh@prod-01:~/scripts$curl -sf https://api.github.com/repos/bash/bash/releases/latest | jq -r '.tag_name'
bash-5.2.21
█
✔ Network scripting rules — Always use
curl -sf to fail silently on HTTP errors. Always set --max-time to prevent hanging indefinitely. Use nc -z -w 3 for TCP port checks. Use jq -r (raw) when assigning to bash variables — removes the surrounding quotes. Build JSON with jq -n --arg not string concatenation to avoid injection issues.