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.