Networking Automation
Automating connectivity checks, port scans, and API calls from Bash using curl, nc, and the standard networking commands.
Waiting for a Service to Become Available
#!/usr/bin/env bash
wait_for_port() {
local host="$1" port="$2" timeout="${3:-30}"
local elapsed=0
while ! nc -z "$host" "$port" 2>/dev/null; do
if [ "$elapsed" -ge "$timeout" ]; then
echo "Timed out waiting for $host:$port" >&2
return 1
fi
sleep 1
((elapsed++))
done
echo "$host:$port is now reachable"
}
wait_for_port "db.internal" 5432 60
This pattern is common before starting an application that depends on a database or another service being ready first (a “wait for dependency” script in CI or entrypoints).
HTTP Health Checks
check_health() {
local url="$1"
local status
status=$(curl -o /dev/null -s -w "%{http_code}" "$url")
if [ "$status" -eq 200 ]; then
echo "Healthy: $url"
return 0
else
echo "Unhealthy: $url returned $status" >&2
return 1
fi
}
check_health "https://api.example.com/health"
Calling a REST API and Parsing JSON
RESPONSE=$(curl -s -X POST https://api.example.com/deployments \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"environment":"production","version":"1.2.3"}')
# jq is the standard tool for parsing JSON in Bash — install it, don't try to grep/sed JSON
DEPLOY_ID=$(echo "$RESPONSE" | jq -r '.id')
STATUS=$(echo "$RESPONSE" | jq -r '.status')
echo "Deployment $DEPLOY_ID status: $STATUS"
Polling an API Until a Condition Is Met
DEPLOY_ID="abc123"
MAX_ATTEMPTS=30
for ((i = 1; i <= MAX_ATTEMPTS; i++)); do
STATUS=$(curl -s "https://api.example.com/deployments/$DEPLOY_ID" | jq -r '.status')
echo "Attempt $i: status=$STATUS"
case "$STATUS" in
completed) echo "Deployment succeeded"; exit 0 ;;
failed) echo "Deployment failed" >&2; exit 1 ;;
esac
sleep 10
done
echo "Timed out waiting for deployment to complete" >&2
exit 1
Checking DNS and Connectivity Before Deploying
preflight_checks() {
echo "Running pre-deployment checks..."
if ! getent hosts db.internal > /dev/null; then
echo "DNS resolution failed for db.internal" >&2
return 1
fi
if ! curl -sf -o /dev/null https://registry.example.com; then
echo "Cannot reach container registry" >&2
return 1
fi
echo "All pre-flight checks passed"
}
preflight_checks || exit 1
Downloading Files With Retries
download_with_retry() {
local url="$1" output="$2" max_attempts=3
for ((i = 1; i <= max_attempts; i++)); do
if curl -sf -o "$output" "$url"; then
echo "Downloaded successfully on attempt $i"
return 0
fi
echo "Attempt $i failed, retrying..." >&2
sleep $((i * 2))
done
echo "Failed to download after $max_attempts attempts" >&2
return 1
}
download_with_retry "https://releases.example.com/app-v1.2.3.tar.gz" "app.tar.gz"
Production Considerations
- Always use
curl -sf(silent + fail-on-HTTP-error) in scripts — plaincurlreturns exit 0 even on a 404/500 response, since the HTTP request itself technically “succeeded.” - Use
jqfor any real JSON parsing — regex/grep-based JSON parsing is fragile and breaks on formatting changes or nested structures. - Bound every network retry loop with a maximum attempt count or timeout — an unconditional retry against a permanently-down dependency will hang a deploy/CI pipeline indefinitely.
Quick Interview Answer
“Networking automation in Bash centers on
curlfor HTTP/API calls (with-sfto correctly fail on HTTP error codes) andnc -z/getent hostsfor lower-level connectivity and DNS checks. JSON responses should be parsed withjq, not regex. Common patterns include ‘wait for a dependency to become reachable’ loops before starting an app, and ‘poll an API until a job completes’ loops with a bounded attempt count and exponential-ish backoff.”
Common Mistakes
- Using plain
curlwithout-fand assuming a non-2xx HTTP response counts as a script failure — it doesn’t, by default. - Parsing JSON with grep/sed/awk instead of
jq, breaking the moment the API’s formatting changes slightly. - Writing an unbounded polling/retry loop against an external service with no timeout or max-attempt cap.
Add More Questions to This Guide
Know a question that should be here? Share it and help the community!
Open Google Form