When building monitoring systems like Graphite/Diamond collectors, accurately measuring the time required to establish a TCP connection to a remote port is a common requirement. While telnet is often the first tool that comes to mind, its interactive nature makes it suboptimal for scripting.
Linux provides several built-in alternatives that offer better scriptability than telnet:
# Using timeout + bash's special $SECONDS variable
SECONDS=0
timeout 5 bash -c "echo > /dev/tcp/host.example.com/1234"
echo "Connection time: ${SECONDS}s"
# Using nc (netcat) with timeout
time nc -w 5 -zv host.example.com 1234
Bash's built-in /dev/tcp device provides the cleanest solution:
#!/bin/bash
host="example.com"
port="1234"
start_time=$(date +%s%N)
timeout 5 bash -c "exec 3<>/dev/tcp/${host}/${port}" 2>/dev/null
exit_code=$?
end_time=$(date +%s%N)
if [ $exit_code -eq 0 ]; then
latency=$(( (end_time - start_time) / 1000000 ))
echo "Connection established in ${latency}ms"
else
echo "Connection failed or timed out"
fi
For more comprehensive monitoring, consider these approaches:
# Multiple connection attempts with statistics
attempts=5
results=()
for i in $(seq 1 $attempts); do
start=$(date +%s%N)
timeout 1 bash -c "exec 3<>/dev/tcp/${host}/${port}" 2>/dev/null
[ $? -eq 0 ] && results+=($(( ($(date +%s%N) - start) / 1000000 )))
done
# Calculate statistics
printf '%s\n' "${results[@]}" | awk '{sum+=$1; sumsq+=$1*$1} END {
printf "Avg: %.2fms | Min: %dms | Max: %dms | StdDev: %.2fms\n",
sum/NR, min, max, sqrt(sumsq/NR - (sum/NR)**2)
}'
When /dev/tcp isn't available, consider these alternatives:
# Using Python
python3 -c "import socket, time; s = socket.socket(); start = time.time(); s.connect(('host', port)); print(f'{(time.time()-start)*1000:.2f}ms')"
# Using curl for HTTP services
curl -o /dev/null -s -w 'Connect: %{time_connect}\n' http://example.com:1234
When building monitoring systems like Graphite/Diamond collectors, we often need to measure pure TCP connection establishment time without protocol overhead. The standard telnet approach presents several challenges:
# Manual telnet won't work for scripting:
$ telnet example.com 80
Trying 93.184.216.34...
Connected to example.com.
Escape character is '^]'.
^] # Requires manual interaction
telnet> close
Linux provides several built-in alternatives that work better for scripting:
Method 1: Using timeout + nc (netcat)
timeout 5 bash -c "
Method 2: Using /dev/tcp with time
$ time (exec 3<>/dev/tcp/example.com/80; exec 3<&-)
real 0m0.045s
user 0m0.001s
sys 0m0.003s
For precise measurements, combine bash's built-ins with the time command:
$ cat measure_latency.sh
#!/bin/bash
host=$1
port=$2
{ time -p bash -c "/dev/null 2>&1; } 2>&1 | \
grep real | awk '{print $2}'
# Usage:
$ ./measure_latency.sh example.com 80
0.042
For production monitoring, consider these improvements:
#!/bin/bash
# Enhanced version with timeout and error handling
TIMEOUT=5
host=$1
port=$2
result=$( { time -p timeout $TIMEOUT bash -c "/dev/null 2>&1; } 2>&1 )
status=$?
if [ $status -eq 0 ]; then
echo $result | grep real | awk '{print $2}'
elif [ $status -eq 124 ]; then
echo "timeout"
else
echo "connection_failed"
fi
Tool | Advantage | Disadvantage |
---|---|---|
nc (netcat) | Widely available | May need -w timeout flag |
/dev/tcp | No dependencies | Bash-specific |
socat | Very flexible | Not always installed |
For Diamond collector integration, you might use:
# diamond.conf snippet
[[TCPLatencyCollector]]
enabled = True
hosts = web1:80, db1:3306, cache1:11211
interval = 60
timeout = 5