mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-07-27 17:01:53 +08:00
338 lines
8.8 KiB
Bash
338 lines
8.8 KiB
Bash
#!/bin/bash
|
|
# Copyright (C) 2019-2026 sirpdboy
|
|
# Fixed version - correct image URL handling
|
|
|
|
RESULT_FILE='/tmp/netspeedtest_result'
|
|
LOG_FILE='/tmp/netspeedtest.log'
|
|
LOCK_FILE='/var/run/netspeedtest.lock'
|
|
PID_FILE='/var/run/netspeedtest.pid'
|
|
TIMEOUT=120
|
|
|
|
# 默认设置
|
|
PREFERRED_VERSION="auto"
|
|
SELECTED_SERVER="auto"
|
|
|
|
# 日志函数
|
|
log() {
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
|
|
}
|
|
|
|
# 检查进程锁
|
|
check_running() {
|
|
if [ -f "$PID_FILE" ]; then
|
|
local old_pid=$(cat "$PID_FILE" 2>/dev/null)
|
|
if kill -0 "$old_pid" 2>/dev/null; then
|
|
log "Another speedtest is already running (PID: $old_pid)"
|
|
echo "Testing" > "$RESULT_FILE"
|
|
exit 1
|
|
else
|
|
rm -f "$PID_FILE"
|
|
fi
|
|
fi
|
|
|
|
exec 200>"$LOCK_FILE"
|
|
if ! flock -n 200; then
|
|
log "Another speedtest is already running (flock)"
|
|
echo "Testing" > "$RESULT_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
echo $$ > "$PID_FILE"
|
|
}
|
|
|
|
# 清理函数
|
|
cleanup() {
|
|
rm -f "$PID_FILE"
|
|
flock -u 200 2>/dev/null
|
|
exec 200>&-
|
|
}
|
|
|
|
trap cleanup EXIT INT TERM
|
|
|
|
# 检测可用的speedtest版本
|
|
detect_speedtest() {
|
|
local preferred="$1"
|
|
local available_versions=""
|
|
|
|
# 检查Ookla官方版
|
|
if [ -f '/usr/bin/ookla-speedtest' ] && [ -x '/usr/bin/ookla-speedtest' ]; then
|
|
available_versions="ookla:/usr/bin/ookla-speedtest"
|
|
fi
|
|
|
|
# 检查Python版
|
|
if [ -f '/usr/bin/speedtest' ] && [ -x '/usr/bin/speedtest' ]; then
|
|
if [ -n "$available_versions" ]; then
|
|
available_versions="$available_versions|python:/usr/bin/speedtest"
|
|
else
|
|
available_versions="python:/usr/bin/speedtest"
|
|
fi
|
|
fi
|
|
|
|
# 如果没有找到任何版本
|
|
if [ -z "$available_versions" ]; then
|
|
log "No speedtest versions found"
|
|
return 1
|
|
fi
|
|
|
|
# 如果指定了偏好版本
|
|
if [ "$preferred" != "auto" ]; then
|
|
IFS='|' read -ra versions <<< "$available_versions"
|
|
for ver in "${versions[@]}"; do
|
|
if [[ "$ver" == "$preferred:"* ]]; then
|
|
echo "$ver"
|
|
return 0
|
|
fi
|
|
done
|
|
fi
|
|
|
|
echo "$available_versions" | cut -d'|' -f1
|
|
return 0
|
|
}
|
|
|
|
# 运行Ookla版测试
|
|
run_ookla_test() {
|
|
local speedtest_bin=$1
|
|
local server_id=$2
|
|
|
|
local cmd="$speedtest_bin --accept-gdpr --accept-license --progress=no"
|
|
[ -n "$server_id" ] && [ "$server_id" != "auto" ] && cmd="$cmd --server-id=$server_id"
|
|
# 使用临时文件存储输出
|
|
local tmp_output=$(mktemp)
|
|
|
|
if command -v timeout >/dev/null 2>&1; then
|
|
timeout $TIMEOUT $cmd > "$tmp_output" 2>&1
|
|
local exit_code=$?
|
|
if [ $exit_code -eq 124 ]; then
|
|
log "Error: Test timed out"
|
|
rm -f "$tmp_output"
|
|
return 1
|
|
fi
|
|
else
|
|
$cmd > "$tmp_output" 2>&1
|
|
fi
|
|
|
|
cat "$tmp_output"
|
|
rm -f "$tmp_output"
|
|
return 0
|
|
}
|
|
|
|
# 运行Python版测试
|
|
run_python_test() {
|
|
local speedtest_bin=$1
|
|
local server_id=$2
|
|
|
|
local cmd="$speedtest_bin --share --simple"
|
|
if [ -n "$server_id" ] && [ "$server_id" != "auto" ]; then
|
|
cmd="$speedtest_bin --server $server_id --share --simple"
|
|
fi
|
|
|
|
|
|
local tmp_output=$(mktemp)
|
|
|
|
if command -v timeout >/dev/null 2>&1; then
|
|
timeout 90 $cmd > "$tmp_output" 2>&1
|
|
local exit_code=$?
|
|
if [ $exit_code -eq 124 ]; then
|
|
log "Error: Python test timed out"
|
|
|
|
# 尝试使用常用服务器
|
|
timeout 90 $speedtest_bin --server 59016 --share --simple > "$tmp_output" 2>&1
|
|
if [ $? -eq 124 ]; then
|
|
log "Error: Second attempt also timed out"
|
|
rm -f "$tmp_output"
|
|
return 1
|
|
fi
|
|
fi
|
|
else
|
|
$cmd > "$tmp_output" 2>&1
|
|
fi
|
|
|
|
cat "$tmp_output"
|
|
rm -f "$tmp_output"
|
|
return 0
|
|
}
|
|
|
|
# 解析Python版结果
|
|
parse_python_result() {
|
|
local result="$1"
|
|
|
|
# 检查是否包含错误信息
|
|
if echo "$result" | grep -q -i "error\|failed\|cannot\|timeout"; then
|
|
return 1
|
|
fi
|
|
|
|
# 提取分享链接
|
|
local share_url=$(echo "$result" | grep -o 'http://www.speedtest.net/result/[0-9]*\.png' | head -1)
|
|
if [ -n "$share_url" ]; then
|
|
echo "$share_url"
|
|
return 0
|
|
fi
|
|
|
|
# 提取速度数据
|
|
local download=$(echo "$result" | grep -i "download" | head -1)
|
|
local upload=$(echo "$result" | grep -i "upload" | head -1)
|
|
local latency=$(echo "$result" | grep -i "latency" | head -1)
|
|
|
|
if [ -n "$download" ] && [ -n "$upload" ]; then
|
|
{
|
|
echo "$download"
|
|
echo "$upload"
|
|
[ -n "$latency" ] && echo "$latency"
|
|
}
|
|
return 0
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
parse_ookla_result() {
|
|
local result="$1"
|
|
|
|
# 提取结果URL
|
|
local result_url=$(echo "$result" | grep -i "result url" | grep -o 'https\?://[^ ]*' | head -1)
|
|
|
|
if [ -n "$result_url" ]; then
|
|
echo "$result_url.png"
|
|
return 0
|
|
fi
|
|
local download=$(echo "$result" | grep -i "download" | grep -o "[0-9.]\+ [Mk]bits" | head -1)
|
|
local upload=$(echo "$result" | grep -i "upload" | grep -o "[0-9.]\+ [Mk]bits" | head -1)
|
|
local latency=$(echo "$result" | grep -i "latency" | grep -o "[0-9.]\+ ms" | head -1)
|
|
|
|
if [ -n "$download" ] && [ -n "$upload" ]; then
|
|
{
|
|
echo "Download: $download"
|
|
echo "Upload: $upload"
|
|
[ -n "$latency" ] && echo "Latency: $latency"
|
|
}
|
|
return 0
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
# 主测试函数
|
|
main_test() {
|
|
log "=== Speedtest started (PID: $$) ==="
|
|
|
|
# 检测可用的speedtest版本
|
|
local version_info=$(detect_speedtest "$PREFERRED_VERSION")
|
|
if [ -z "$version_info" ]; then
|
|
log "Error: No speedtest version found"
|
|
echo "Test failed" > "$RESULT_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
local version_type=${version_info%:*}
|
|
local speedtest_bin=${version_info#*:}
|
|
log "Using $version_type version: $speedtest_bin"
|
|
TEST_SUCCESS=0
|
|
|
|
# 运行测试
|
|
case $version_type in
|
|
ookla)
|
|
RUNTEST=$(run_ookla_test "$speedtest_bin" "$SELECTED_SERVER")
|
|
;;
|
|
python)
|
|
RUNTEST=$(run_python_test "$speedtest_bin" "$SELECTED_SERVER")
|
|
;;
|
|
esac
|
|
|
|
echo "$RUNTEST" >> "$LOG_FILE"
|
|
|
|
# 解析结果
|
|
case $version_type in
|
|
ookla) RESULT=$(parse_ookla_result "$RUNTEST") ;;
|
|
python) RESULT=$(parse_python_result "$RUNTEST") ;;
|
|
esac
|
|
|
|
if [ -n "$RESULT" ]; then
|
|
echo "$RESULT" > "$RESULT_FILE"
|
|
TEST_SUCCESS=1
|
|
log "Test successful"
|
|
fi
|
|
|
|
# 如果失败,尝试自动选择
|
|
if [ $TEST_SUCCESS -eq 0 ] && [ "$SELECTED_SERVER" != "auto" ]; then
|
|
log "Test failed with selected server, trying automatic server selection"
|
|
SELECTED_SERVER="auto"
|
|
|
|
case $version_type in
|
|
ookla)
|
|
RUNTEST=$(run_ookla_test "$speedtest_bin" "auto")
|
|
;;
|
|
python)
|
|
RUNTEST=$(run_python_test "$speedtest_bin" "auto")
|
|
;;
|
|
esac
|
|
|
|
echo "$RUNTEST" >> "$LOG_FILE"
|
|
|
|
case $version_type in
|
|
ookla) RESULT=$(parse_ookla_result "$RUNTEST") ;;
|
|
python) RESULT=$(parse_python_result "$RUNTEST") ;;
|
|
esac
|
|
|
|
if [ -n "$RESULT" ]; then
|
|
echo "$RESULT" > "$RESULT_FILE"
|
|
log "Test successful with automatic server selection"
|
|
TEST_SUCCESS=1
|
|
fi
|
|
fi
|
|
|
|
# 最终检查
|
|
if [ $TEST_SUCCESS -eq 0 ]; then
|
|
echo "Test failed" > "$RESULT_FILE"
|
|
log "All tests failed"
|
|
fi
|
|
|
|
log "=== Speedtest completed (PID: $$) ==="
|
|
echo "" >> "$LOG_FILE"
|
|
}
|
|
|
|
# 显示帮助信息
|
|
show_help() {
|
|
echo "Usage: $0 [OPTIONS]"
|
|
echo "Options:"
|
|
echo " --version VERSION Preferred version (ookla/python/auto)"
|
|
echo " --server SERVER_ID Server ID to test with"
|
|
echo " --help Show this help message"
|
|
}
|
|
|
|
# 命令行参数处理
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--version)
|
|
if [ -n "$2" ]; then
|
|
PREFERRED_VERSION="$2"
|
|
shift 2
|
|
else
|
|
echo "Error: --version requires an argument"
|
|
exit 1
|
|
fi
|
|
;;
|
|
--server)
|
|
if [ -n "$2" ]; then
|
|
SELECTED_SERVER="$2"
|
|
shift 2
|
|
else
|
|
echo "Error: --server requires an argument"
|
|
exit 1
|
|
fi
|
|
;;
|
|
--help)
|
|
show_help
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unknown option: $1"
|
|
show_help
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# 运行测试
|
|
check_running
|
|
main_test
|
|
exit 0 |