start_only_udp.sh 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #!/usr/bin/env bash
  2. set -euo pipefail
  3. usage() {
  4. cat <<'EOF'
  5. Usage: start_only_udp.sh [config_path]
  6. Options via env:
  7. MYNETSPEEDER_SOCKS_HOST SOCKS 监听地址,默认读取配置或 127.0.0.1
  8. MYNETSPEEDER_SOCKS_PORT SOCKS 监听端口,默认读取配置或 19180
  9. MYNETSPEEDER_USER 运行用户,默认 mynetspeeder
  10. MYNETSPEEDER_LOG_MAX_MB 单个日志最大大小,默认 50
  11. MYNETSPEEDER_LOG_BACKUPS 日志轮转保留份数,默认 3
  12. EOF
  13. }
  14. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  15. ROOT_DIR="$(dirname "$SCRIPT_DIR")"
  16. PACKAGE_PARENT="$(dirname "$ROOT_DIR")"
  17. PACKAGE_NAME="$(basename "$ROOT_DIR")"
  18. CONFIG_PATH="${1:-$ROOT_DIR/config.json}"
  19. RUNTIME_USER="${MYNETSPEEDER_USER:-mynetspeeder}"
  20. PID_FILE="/var/run/mynetspeeder-socks.pid"
  21. LOG_FILE="/var/log/mynetspeeder-socks.log"
  22. LOG_MAX_MB="${MYNETSPEEDER_LOG_MAX_MB:-50}"
  23. LOG_BACKUPS="${MYNETSPEEDER_LOG_BACKUPS:-3}"
  24. if [[ $EUID -ne 0 ]]; then
  25. echo "need root"
  26. exit 1
  27. fi
  28. if [[ ! -f "$CONFIG_PATH" ]]; then
  29. echo "config not found: $CONFIG_PATH"
  30. exit 1
  31. fi
  32. SOCKS_HOST_FROM_CONFIG=$(python3 - <<'PY' "$CONFIG_PATH"
  33. import json, sys
  34. cfg = json.load(open(sys.argv[1]))
  35. print(cfg.get("socks_host", "127.0.0.1"))
  36. PY
  37. )
  38. SOCKS_PORT_FROM_CONFIG=$(python3 - <<'PY' "$CONFIG_PATH"
  39. import json, sys
  40. cfg = json.load(open(sys.argv[1]))
  41. port = int(cfg.get("socks_port", 19180) or 19180)
  42. print(port if port > 0 else 19180)
  43. PY
  44. )
  45. SOCKS_HOST="${MYNETSPEEDER_SOCKS_HOST:-$SOCKS_HOST_FROM_CONFIG}"
  46. SOCKS_PORT="${MYNETSPEEDER_SOCKS_PORT:-$SOCKS_PORT_FROM_CONFIG}"
  47. if ! [[ "$SOCKS_PORT" =~ ^[0-9]+$ ]]; then
  48. echo "socks port must be numeric"
  49. exit 1
  50. fi
  51. id -u "$RUNTIME_USER" >/dev/null 2>&1 || useradd --system --no-create-home --shell /usr/sbin/nologin "$RUNTIME_USER"
  52. mkdir -p /var/log
  53. touch "$LOG_FILE"
  54. chown "$RUNTIME_USER":"$RUNTIME_USER" "$LOG_FILE"
  55. if ! [[ "$LOG_MAX_MB" =~ ^[0-9]+$ ]] || ! [[ "$LOG_BACKUPS" =~ ^[0-9]+$ ]]; then
  56. echo "log limits must be numeric"
  57. exit 1
  58. fi
  59. LOG_MAX_BYTES=$((LOG_MAX_MB * 1024 * 1024))
  60. wait_for_listen() {
  61. local host="$1"
  62. local port="$2"
  63. local log_file="$3"
  64. local log_pattern="$4"
  65. local label="$5"
  66. local timeout_sec="${6:-10}"
  67. local deadline=$((SECONDS + timeout_sec))
  68. local pattern
  69. pattern="${host//./\\.}:${port}( |$)"
  70. while (( SECONDS < deadline )); do
  71. if ss -H -lntp 2>/dev/null | grep -qE "$pattern"; then
  72. return 0
  73. fi
  74. if [[ -f "$log_file" ]] && grep -qE "$log_pattern" "$log_file" 2>/dev/null; then
  75. return 0
  76. fi
  77. sleep 0.2
  78. done
  79. echo "$label failed to listen"
  80. return 1
  81. }
  82. pkill -f 'python3 -m mynetspeeder socks' || true
  83. runuser -u "$RUNTIME_USER" -- bash -lc "export PYTHONUNBUFFERED=1; export PYTHONPATH=${PACKAGE_PARENT}; cd ${PACKAGE_PARENT} && exec nohup python3 -m ${PACKAGE_NAME} socks --listen-host ${SOCKS_HOST} --listen-port ${SOCKS_PORT} --config ${CONFIG_PATH} 2>&1 | python3 ${ROOT_DIR}/scripts/rotate-log.py ${LOG_FILE} ${LOG_MAX_BYTES} ${LOG_BACKUPS}" &
  84. SOCKS_PID=$!
  85. echo "$SOCKS_PID" > "$PID_FILE"
  86. if ! wait_for_listen "$SOCKS_HOST" "$SOCKS_PORT" "$LOG_FILE" "socks5 listening on" "socks" 15; then
  87. tail -n 50 "$LOG_FILE" || true
  88. exit 1
  89. fi
  90. echo "mynetspeeder udp+socks mode started on ${SOCKS_HOST}:${SOCKS_PORT}"
  91. echo "tcp: direct"
  92. echo "udp: use socks5 udp associate for project acceleration"
  93. echo "pid file: $PID_FILE"
  94. echo "log file: $LOG_FILE"
  95. echo "log max: ${LOG_MAX_MB}MB x ${LOG_BACKUPS}"