When automating infrastructure tasks, we often need to wait for a host to become available before proceeding with subsequent operations. The standard ping command in Linux doesn't have a built-in "ping until available" feature, but we can implement this logic in a bash script.
Here's a simple yet effective approach using a while loop:
while ! ping -c 1 target_host &> /dev/null
do
echo "Host unreachable - retrying in 2 seconds..."
sleep 2
done
echo "Host is now reachable!"
For production scripts, we should add a timeout mechanism to prevent infinite loops:
MAX_ATTEMPTS=30
ATTEMPT=0
while ! ping -c 1 -W 1 target_host &> /dev/null
do
ATTEMPT=$((ATTEMPT+1))
echo "Attempt $ATTEMPT/$MAX_ATTEMPTS - host not responding"
if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then
echo "Maximum attempts reached - aborting"
exit 1
fi
sleep 2
done
echo "Host is now reachable!"
Sometimes you need to wait for DNS resolution first. This modified version checks both DNS and ping:
while ! getent hosts target_host > /dev/null 2>&1 || \
! ping -c 1 -W 1 target_host > /dev/null 2>&1
do
sleep 1
done
For more robust checking of specific services (not just ICMP), consider using nc (netcat):
until nc -zv target_host 22 2>/dev/null
do
sleep 1
done
echo "SSH port is now open"
Always include proper error handling in your scripts:
ping_host() {
local host=$1
local max_attempts=${2:-30}
for ((i=1; i<=max_attempts; i++)); do
if ping -c 1 -W 1 "$host" &> /dev/null; then
echo "Host $host is reachable"
return 0
fi
sleep 1
done
echo "ERROR: Host $host not reachable after $max_attempts attempts" >&2
return 1
}
# Usage example:
ping_host "example.com" || exit 1
When automating processes in Linux, we often need to wait for a host to become available before proceeding with subsequent operations. A common scenario is waiting for a server to finish booting before running configuration scripts or deployment processes.
The simplest approach uses a while loop with ping:
while ! ping -c 1 hostname &> /dev/null
do
echo "Host not available, waiting..."
sleep 1
done
echo "Host is now reachable!"
For production scripts, we should add a timeout to prevent infinite waiting:
#!/bin/bash
HOST="example.com"
TIMEOUT=60
INTERVAL=1
COUNT=0
while ! ping -c 1 $HOST &> /dev/null
do
sleep $INTERVAL
COUNT=$((COUNT+1))
echo "Waiting for $HOST to become reachable ($COUNT seconds elapsed)..."
if [ $COUNT -ge $TIMEOUT ]; then
echo "Timeout reached while waiting for $HOST"
exit 1
fi
done
echo "$HOST is now reachable"
# Continue with your script here
For enterprise environments, consider this more robust version with error handling:
#!/bin/bash
set -euo pipefail
TARGET_HOST=${1:-localhost}
MAX_ATTEMPTS=120
SLEEP_INTERVAL=5
wait_for_host() {
local attempts=0
until ping -c 1 -W 1 "$TARGET_HOST" &> /dev/null; do
attempts=$((attempts + 1))
if [ $attempts -ge $MAX_ATTEMPTS ]; then
echo "Error: $TARGET_HOST not reachable after $MAX_ATTEMPTS attempts" >&2
return 1
fi
sleep $SLEEP_INTERVAL
done
echo "$TARGET_HOST is now reachable"
}
if wait_for_host; then
# Proceed with your operations
echo "Starting main operations..."
else
exit 1
fi
For more sophisticated host availability checks, consider these alternatives:
# Using nc (netcat) for port checking until nc -zv hostname 22 &> /dev/null; do sleep 1; done # Using curl for web services until curl --silent --fail http://hostname/ &> /dev/null; do sleep 1; done
When working with systemd services, you can use ExecStartPre to implement host waiting:
[Unit] Description=My Service After=network.target [Service] ExecStartPre=/bin/bash -c 'until ping -c 1 hostname; do sleep 1; done' ExecStart=/path/to/your/script Restart=on-failure [Install] WantedBy=multi-user.target