Skip to content

Instantly share code, notes, and snippets.

@tranphuquy19
Last active January 2, 2025 15:33
Show Gist options
  • Save tranphuquy19/b722725039ed61fe821fcc6299003a5c to your computer and use it in GitHub Desktop.
Save tranphuquy19/b722725039ed61fe821fcc6299003a5c to your computer and use it in GitHub Desktop.
speedtest.sh
#!/bin/bash
# Default configuration from environment variables
THRESHOLD_DOWNLOAD=${THRESHOLD_DOWNLOAD:-300}
THRESHOLD_UPLOAD=${THRESHOLD_UPLOAD:-200}
IFS=',' read -ra SERVER_IDS <<<"${SERVER_IDS:-44677,9903,26853,1536,3865,22207,50467,13623}"
# Telegram configuration
TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN:-""}
TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID:-"-"}
TELEGRAM_THREAD_ID=${TELEGRAM_THREAD_ID:-""}
# Function to send message via Telegram
send_telegram_message() {
local message="$1"
local status="$2"
# Prepare message for Telegram
local telegram_message=""
# Add alert header if needed
[ "$status" != "success" ] && telegram_message+=$'πŸ”” @all\n\n'
# Add title and timestamp
telegram_message+=$'πŸš€ Speed Test Results\n'
telegram_message+=$"πŸ“… $(date '+%Y-%m-%d %H:%M:%S')"
telegram_message+=$'\n'
telegram_message+=$'━━━━━━━━━━━━━━━━━━━━\n\n'
# Process the test results line by line
while IFS= read -r line; do
# Skip header lines
[[ "$line" =~ ^===.*===$ ]] && continue
[[ "$line" =~ ^πŸ“….*$ ]] && continue
# Replace ASCII separator with Unicode
if [[ "$line" =~ ^-+$ ]]; then
telegram_message+=$'━━━━━━━━━━━━━━━━━━━━\n'
continue
fi
# Add other lines
telegram_message+="$line"$'\n'
done <<<"$message"
# Prepare payload
local payload
if [ -n "$TELEGRAM_THREAD_ID" ]; then
payload=$(jq -n \
--arg chat_id "$TELEGRAM_CHAT_ID" \
--arg thread_id "$TELEGRAM_THREAD_ID" \
--arg text "$telegram_message" \
'{
chat_id: $chat_id,
message_thread_id: $thread_id,
text: $text,
parse_mode: "HTML",
disable_web_page_preview: true
}')
else
payload=$(jq -n \
--arg chat_id "$TELEGRAM_CHAT_ID" \
--arg text "$telegram_message" \
'{
chat_id: $chat_id,
text: $text,
parse_mode: "HTML",
disable_web_page_preview: true
}')
fi
# Send message with retry
local max_retries=3
local retry_count=0
while [ $retry_count -lt $max_retries ]; do
if response=$(curl -s -X POST \
"https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-H 'Content-Type: application/json' \
-d "$payload"); then
if echo "$response" | jq -e '.ok == true' >/dev/null; then
echo "βœ… Telegram message sent successfully"
return 0
fi
fi
((retry_count++))
[ $retry_count -lt $max_retries ] && sleep 5
done
echo "❌ Failed to send Telegram message after $max_retries attempts"
return 1
}
# Install speedtest CLI
install_speedtest() {
echo "πŸ”„ Installing speedtest CLI..."
rm -f speedtest*
if ! wget -q https://install.speedtest.net/app/cli/ookla-speedtest-1.2.0-linux-x86_64.tgz; then
echo "❌ Failed to download speedtest CLI"
exit 1
fi
if ! tar xzf ookla-speedtest-1.2.0-linux-x86_64.tgz; then
echo "❌ Failed to extract speedtest files"
rm ookla-speedtest-1.2.0-linux-x86_64.tgz
exit 1
fi
rm ookla-speedtest-1.2.0-linux-x86_64.tgz
chmod +x speedtest
mkdir -p ~/.config/ookla
cat >~/.config/ookla/speedtest-cli.json <<EOF
{
"Settings": {
"LicenseAccepted": "604ec27f828456331ebf441826292c49276bd3c1bee1a2f65a6452f505c4061c",
"GDPRAccepted": true
}
}
EOF
echo "βœ… Speedtest CLI installed successfully"
}
# Check speedtest binary
check_speedtest() {
if [ ! -f "./speedtest" ]; then
echo "❌ Speedtest binary not found in current directory"
echo "πŸ”„ Attempting to install speedtest..."
install_speedtest
fi
chmod +x ./speedtest
}
# Test speed for a single server
test_speed() {
local server_id=$1
local result
echo "πŸ”„ Testing server ID: $server_id..." >&2
result=$(./speedtest -f json -s "$server_id" 2>/dev/null)
if [ $? -ne 0 ] || [ -z "$result" ]; then
echo "❌ Failed to test server $server_id" >&2
return 1
fi
echo "$result"
return 0
}
# Analyze JSON result
analyze_result() {
local json_result=$1
local has_alert="false"
# Get values from JSON
local download_bytes=$(echo "$json_result" | jq -r '.download.bandwidth')
local upload_bytes=$(echo "$json_result" | jq -r '.upload.bandwidth')
local ping=$(echo "$json_result" | jq -r '.ping.latency')
local server_name=$(echo "$json_result" | jq -r '.server.name')
local server_location=$(echo "$json_result" | jq -r '.server.location')
local server_country=$(echo "$json_result" | jq -r '.server.country')
local server_id=$(echo "$json_result" | jq -r '.server.id')
# Convert bytes/s to Mbps
local download_mbps=$(echo "scale=2; $download_bytes * 8 / 1000000" | bc)
local upload_mbps=$(echo "scale=2; $upload_bytes * 8 / 1000000" | bc)
# Format output
echo "πŸ“ Server ID: $server_id - $server_name ($server_location, $server_country)"
# Check download threshold
if (($(echo "$download_mbps < $THRESHOLD_DOWNLOAD" | bc -l))); then
echo "⬇️ Download: $download_mbps Mbps ⚠️"
has_alert="true"
else
echo "⬇️ Download: $download_mbps Mbps"
fi
# Check upload threshold
if (($(echo "$upload_mbps < $THRESHOLD_UPLOAD" | bc -l))); then
echo "⬆️ Upload: $upload_mbps Mbps ⚠️"
has_alert="true"
else
echo "⬆️ Upload: $upload_mbps Mbps"
fi
echo "πŸ”„ Ping: $ping ms"
echo "━━━━━━━━━━━━━━━━━━━━"
[ "$has_alert" = "true" ] && return 1 || return 0
}
# Main function
main() {
if [ ${#SERVER_IDS[@]} -eq 0 ]; then
echo "❌ Error: No server IDs defined"
exit 1
fi
local output=""
local overall_alert=false
local test_results=()
local failed_servers=()
# Add threshold info at the beginning
output+="πŸ“Š Threshold - Download: $THRESHOLD_DOWNLOAD Mbps, Upload: $THRESHOLD_UPLOAD Mbps"$'\n'
output+="━━━━━━━━━━━━━━━━━━━━"$'\n\n'
for server_id in "${SERVER_IDS[@]}"; do
local result
if result=$(test_speed "$server_id"); then
test_results+=("$result")
output+="$(analyze_result "$result")"$'\n'
[ $? -eq 1 ] && overall_alert=true
else
failed_servers+=("$server_id")
output+="❌ Failed to test server $server_id"$'\n\n'
fi
done
output+="πŸ“Š Summary
Total servers tested: ${#SERVER_IDS[@]}
Successful tests: ${#test_results[@]}"$'\n'
if [ ${#failed_servers[@]} -gt 0 ]; then
output+="❌ Failed servers: ${failed_servers[*]}"$'\n'
fi
local status="success"
if $overall_alert; then
output+="⚠️ Alert: One or more servers below threshold!"$'\n'
status="alert"
else
if [ ${#test_results[@]} -eq 0 ]; then
output+="❌ Error: All tests failed"$'\n'
status="error"
else
output+="βœ… All successful tests are above thresholds"$'\n'
fi
fi
echo -e "$output"
if [ -n "$TELEGRAM_BOT_TOKEN" ] && [ -n "$TELEGRAM_CHAT_ID" ]; then
send_telegram_message "$output" "$status"
fi
[ "$status" != "success" ] && exit 1 || exit 0
}
# Check dependencies
check_dependencies() {
local missing_deps=()
if ! command -v jq &>/dev/null; then
missing_deps+=("jq")
fi
if ! command -v bc &>/dev/null; then
missing_deps+=("bc")
fi
if [ ${#missing_deps[@]} -ne 0 ]; then
echo "❌ Error: Missing required dependencies:"
printf '%s\n' "${missing_deps[@]}"
echo "Please install them using:"
echo "sudo apt-get install ${missing_deps[*]}"
exit 1
fi
}
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--install)
install_speedtest
exit 0
;;
--help)
echo "Usage: $0 [--install] [--help]"
echo " --install: Force reinstall speedtest CLI"
echo " --help: Show this help message"
echo ""
echo "Environment variables:"
echo " THRESHOLD_DOWNLOAD: Download threshold in Mbps (default: 300)"
echo " THRESHOLD_UPLOAD: Upload threshold in Mbps (default: 200)"
echo " SERVER_IDS: Comma-separated list of server IDs (default: 44677,22207)"
echo " TELEGRAM_BOT_TOKEN: Telegram bot token"
echo " TELEGRAM_CHAT_ID: Telegram chat ID"
echo " TELEGRAM_THREAD_ID: Telegram thread ID (optional)"
exit 0
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
shift
done
# Run checks and main function
# check_dependencies
check_speedtest
main
πŸ”” @all
πŸš€ Speed Test Results
πŸ“… 2025-01-02 20:55:32
━━━━━━━━━━━━━━━━━━━━
πŸ“Š Threshold - Download: 300 Mbps, Upload: 200 Mbps
━━━━━━━━━━━━━━━━━━━━
πŸ“ Server ID: 44677 - FPT Telecom (Da Nang, Vietnam)
⬇️ Download: 942.29 Mbps
⬆️ Upload: 940.62 Mbps
πŸ”„ Ping: 4.115 ms
━━━━━━━━━━━━━━━━━━━━
πŸ“ Server ID: 9903 - Viettel Network (Ha Noi, Vietnam)
⬇️ Download: 937.18 Mbps
⬆️ Upload: 941.11 Mbps
πŸ”„ Ping: 13.796 ms
━━━━━━━━━━━━━━━━━━━━
πŸ“ Server ID: 26853 - Viettel Network (Ho Chi Minh, Vietnam)
⬇️ Download: 948.27 Mbps
⬆️ Upload: 941.48 Mbps
πŸ”„ Ping: 23.259 ms
━━━━━━━━━━━━━━━━━━━━
πŸ“ Server ID: 1536 - STC (Hong Kong, Hong Kong)
⬇️ Download: 943.13 Mbps
⬆️ Upload: 939.17 Mbps
πŸ”„ Ping: 43.794 ms
━━━━━━━━━━━━━━━━━━━━
πŸ“ Server ID: 3865 - KABEL-TV-BINZ (Binz, Germany)
⬇️ Download: 942.79 Mbps
⬆️ Upload: 7.89 Mbps ⚠️
πŸ”„ Ping: 230.977 ms
━━━━━━━━━━━━━━━━━━━━
πŸ“ Server ID: 22207 - BCNET (Vancouver, BC, Canada)
⬇️ Download: 651.33 Mbps
⬆️ Upload: 450.36 Mbps
πŸ”„ Ping: 268.36 ms
━━━━━━━━━━━━━━━━━━━━
πŸ“ Server ID: 50467 - Verizon (Tokyo, Japan)
⬇️ Download: .80 Mbps ⚠️
⬆️ Upload: 275.24 Mbps
πŸ”„ Ping: 131.43 ms
━━━━━━━━━━━━━━━━━━━━
πŸ“ Server ID: 13623 - Singtel (Singapore, Singapore)
⬇️ Download: 948.96 Mbps
⬆️ Upload: 533.02 Mbps
πŸ”„ Ping: 73.599 ms
━━━━━━━━━━━━━━━━━━━━
πŸ“Š Summary
Total servers tested: 8
Successful tests: 8
⚠️ Alert: One or more servers below threshold!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment