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