|
|
@@ -0,0 +1,109 @@
|
|
|
+#!/usr/bin/env bash
|
|
|
+set -euo pipefail
|
|
|
+
|
|
|
+usage() {
|
|
|
+ cat <<'EOF'
|
|
|
+Usage: start_only_udp.sh [config_path]
|
|
|
+
|
|
|
+Options via env:
|
|
|
+ MYNETSPEEDER_SOCKS_HOST SOCKS 监听地址,默认读取配置或 127.0.0.1
|
|
|
+ MYNETSPEEDER_SOCKS_PORT SOCKS 监听端口,默认读取配置或 19180
|
|
|
+ MYNETSPEEDER_USER 运行用户,默认 mynetspeeder
|
|
|
+ MYNETSPEEDER_LOG_MAX_MB 单个日志最大大小,默认 50
|
|
|
+ MYNETSPEEDER_LOG_BACKUPS 日志轮转保留份数,默认 3
|
|
|
+EOF
|
|
|
+}
|
|
|
+
|
|
|
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
+ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
|
|
+PACKAGE_PARENT="$(dirname "$ROOT_DIR")"
|
|
|
+PACKAGE_NAME="$(basename "$ROOT_DIR")"
|
|
|
+
|
|
|
+CONFIG_PATH="${1:-$ROOT_DIR/config.json}"
|
|
|
+RUNTIME_USER="${MYNETSPEEDER_USER:-mynetspeeder}"
|
|
|
+PID_FILE="/var/run/mynetspeeder-socks.pid"
|
|
|
+LOG_FILE="/var/log/mynetspeeder-socks.log"
|
|
|
+LOG_MAX_MB="${MYNETSPEEDER_LOG_MAX_MB:-50}"
|
|
|
+LOG_BACKUPS="${MYNETSPEEDER_LOG_BACKUPS:-3}"
|
|
|
+
|
|
|
+if [[ $EUID -ne 0 ]]; then
|
|
|
+ echo "need root"
|
|
|
+ exit 1
|
|
|
+fi
|
|
|
+
|
|
|
+if [[ ! -f "$CONFIG_PATH" ]]; then
|
|
|
+ echo "config not found: $CONFIG_PATH"
|
|
|
+ exit 1
|
|
|
+fi
|
|
|
+
|
|
|
+SOCKS_HOST_FROM_CONFIG=$(python3 - <<'PY' "$CONFIG_PATH"
|
|
|
+import json, sys
|
|
|
+cfg = json.load(open(sys.argv[1]))
|
|
|
+print(cfg.get("socks_host", "127.0.0.1"))
|
|
|
+PY
|
|
|
+)
|
|
|
+SOCKS_PORT_FROM_CONFIG=$(python3 - <<'PY' "$CONFIG_PATH"
|
|
|
+import json, sys
|
|
|
+cfg = json.load(open(sys.argv[1]))
|
|
|
+port = int(cfg.get("socks_port", 19180) or 19180)
|
|
|
+print(port if port > 0 else 19180)
|
|
|
+PY
|
|
|
+)
|
|
|
+SOCKS_HOST="${MYNETSPEEDER_SOCKS_HOST:-$SOCKS_HOST_FROM_CONFIG}"
|
|
|
+SOCKS_PORT="${MYNETSPEEDER_SOCKS_PORT:-$SOCKS_PORT_FROM_CONFIG}"
|
|
|
+
|
|
|
+if ! [[ "$SOCKS_PORT" =~ ^[0-9]+$ ]]; then
|
|
|
+ echo "socks port must be numeric"
|
|
|
+ exit 1
|
|
|
+fi
|
|
|
+
|
|
|
+id -u "$RUNTIME_USER" >/dev/null 2>&1 || useradd --system --no-create-home --shell /usr/sbin/nologin "$RUNTIME_USER"
|
|
|
+mkdir -p /var/log
|
|
|
+touch "$LOG_FILE"
|
|
|
+chown "$RUNTIME_USER":"$RUNTIME_USER" "$LOG_FILE"
|
|
|
+if ! [[ "$LOG_MAX_MB" =~ ^[0-9]+$ ]] || ! [[ "$LOG_BACKUPS" =~ ^[0-9]+$ ]]; then
|
|
|
+ echo "log limits must be numeric"
|
|
|
+ exit 1
|
|
|
+fi
|
|
|
+LOG_MAX_BYTES=$((LOG_MAX_MB * 1024 * 1024))
|
|
|
+
|
|
|
+wait_for_listen() {
|
|
|
+ local host="$1"
|
|
|
+ local port="$2"
|
|
|
+ local log_file="$3"
|
|
|
+ local log_pattern="$4"
|
|
|
+ local label="$5"
|
|
|
+ local timeout_sec="${6:-10}"
|
|
|
+ local deadline=$((SECONDS + timeout_sec))
|
|
|
+ local pattern
|
|
|
+ pattern="${host//./\\.}:${port}( |$)"
|
|
|
+ while (( SECONDS < deadline )); do
|
|
|
+ if ss -H -lntp 2>/dev/null | grep -qE "$pattern"; then
|
|
|
+ return 0
|
|
|
+ fi
|
|
|
+ if [[ -f "$log_file" ]] && grep -qE "$log_pattern" "$log_file" 2>/dev/null; then
|
|
|
+ return 0
|
|
|
+ fi
|
|
|
+ sleep 0.2
|
|
|
+ done
|
|
|
+ echo "$label failed to listen"
|
|
|
+ return 1
|
|
|
+}
|
|
|
+
|
|
|
+pkill -f 'python3 -m mynetspeeder socks' || true
|
|
|
+
|
|
|
+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}" &
|
|
|
+SOCKS_PID=$!
|
|
|
+echo "$SOCKS_PID" > "$PID_FILE"
|
|
|
+
|
|
|
+if ! wait_for_listen "$SOCKS_HOST" "$SOCKS_PORT" "$LOG_FILE" "socks5 listening on" "socks" 15; then
|
|
|
+ tail -n 50 "$LOG_FILE" || true
|
|
|
+ exit 1
|
|
|
+fi
|
|
|
+
|
|
|
+echo "mynetspeeder udp+socks mode started on ${SOCKS_HOST}:${SOCKS_PORT}"
|
|
|
+echo "tcp: direct"
|
|
|
+echo "udp: use socks5 udp associate for project acceleration"
|
|
|
+echo "pid file: $PID_FILE"
|
|
|
+echo "log file: $LOG_FILE"
|
|
|
+echo "log max: ${LOG_MAX_MB}MB x ${LOG_BACKUPS}"
|