Shell Scripting Bash Networking Intermediate May 2026

Shell Scripting Network Operations

Master curl for HTTP requests and REST API calls, wget for downloads, ping and nc for connectivity checks, JSON parsing with jq, and building robust network-aware automation scripts.

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.

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
}
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}"
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"
bash — network health check
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.