Prechádzať zdrojové kódy

feature: add time interval

Dew-OF-Aurora 2 týždňov pred
rodič
commit
1f3445b644
3 zmenil súbory, kde vykonal 131 pridanie a 11 odobranie
  1. 2 1
      CLAUDE.md
  2. 77 10
      scripts/install_debian.sh
  3. 52 0
      scripts/run_update_and_commit.sh

+ 2 - 1
CLAUDE.md

@@ -78,7 +78,8 @@ sh scripts/router_local_http.sh ./config_router.conf
 
 ```bash
 sudo bash scripts/install_debian.sh --config config.server.json
-sudo bash scripts/install_debian.sh --config config.server.json --interval 5min
+sudo bash scripts/install_debian.sh --config config.server.json --offpeak-interval 30min --peak-interval 10min
+sudo bash scripts/install_debian.sh --config config.server.json --peak-start 19 --peak-end 24 --peak-tz Asia/Shanghai
 sudo bash scripts/install_debian.sh --config config.server.json --git-push 0
 sudo bash scripts/uninstall_debian.sh
 sudo bash scripts/uninstall_debian.sh --keep-auth-files

+ 77 - 10
scripts/install_debian.sh

@@ -19,7 +19,11 @@ RUN_GROUP=""
 RUN_USER_SET="0"
 RUN_GROUP_SET="0"
 RUN_HOME=""
-INTERVAL="30min"
+PEAK_START_HOUR="19"
+PEAK_END_HOUR="24"
+PEAK_TZ="Asia/Shanghai"
+PEAK_INTERVAL="10min"
+OFFPEAK_INTERVAL="30min"
 INSTALL_DEPS="1"
 CONFIG_PATH=""
 GIT_PUSH_ENABLED="1"
@@ -42,7 +46,12 @@ Default behavior:
 Options:
  --user <name>                  Service user (default: current sudo user)
  --group <name>                 Service group (default: current sudo user's group)
- --interval <value>             Timer interval, e.g. 1h/30min (default: 30min)
+ --interval <value>             Alias for --offpeak-interval (default: 30min)
+ --peak-start <hour>            Peak period start hour, 0-23 (default: 19)
+ --peak-end <hour>              Peak period end hour, 1-24 (default: 24)
+ --peak-tz <timezone>           Peak period timezone (default: Asia/Shanghai)
+ --peak-interval <value>        Update interval during peak (default: 10min)
+ --offpeak-interval <value>     Update interval during offpeak (default: 30min)
  --config <path>                Config file path (default: <repo>/config.server.json)
  --git-push <0|1>               Enable/disable push to remote (default: 1)
  --git-push-remote <name>       Remote name for push (default: origin)
@@ -57,10 +66,9 @@ Options:
 Examples:
  sudo bash scripts/install_debian.sh
  sudo bash scripts/install_debian.sh --config /opt/vmess-domain-rotator/config.server.json
- sudo bash scripts/install_debian.sh --interval 10min
+ sudo bash scripts/install_debian.sh --peak-start 18 --peak-end 23
+ sudo bash scripts/install_debian.sh --peak-interval 5min --offpeak-interval 15min
  sudo bash scripts/install_debian.sh --git-push 0
- sudo bash scripts/install_debian.sh --git-http-username aurora --git-http-token-file /root/.config/vmess-token
- sudo bash scripts/install_debian.sh --git-use-credential-store 1 --git-credentials-file /home/aurora/.git-credentials
 EOF
 }
 
@@ -81,7 +89,27 @@ while [[ $# -gt 0 ]]; do
 			shift 2
 			;;
 		--interval)
-			INTERVAL="$2"
+			OFFPEAK_INTERVAL="$2"
+			shift 2
+			;;
+		--peak-start)
+			PEAK_START_HOUR="$2"
+			shift 2
+			;;
+		--peak-end)
+			PEAK_END_HOUR="$2"
+			shift 2
+			;;
+		--peak-tz)
+			PEAK_TZ="$2"
+			shift 2
+			;;
+		--peak-interval)
+			PEAK_INTERVAL="$2"
+			shift 2
+			;;
+		--offpeak-interval)
+			OFFPEAK_INTERVAL="$2"
 			shift 2
 			;;
 		--config)
@@ -225,6 +253,37 @@ if [[ -z "$RUN_HOME" ]]; then
 	exit 1
 fi
 
+to_minutes() {
+	local val="$1"
+	if [[ "$val" =~ ^([0-9]+)min$ ]] || [[ "$val" =~ ^([0-9]+)m$ ]]; then
+		echo "${BASH_REMATCH[1]}"
+	elif [[ "$val" =~ ^([0-9]+)h$ ]]; then
+		echo $(( ${BASH_REMATCH[1]} * 60 ))
+	else
+		echo "$val" | tr -cd '0-9'
+	fi
+}
+
+PEAK_INTERVAL_MIN=$(to_minutes "$PEAK_INTERVAL")
+OFFPEAK_INTERVAL_MIN=$(to_minutes "$OFFPEAK_INTERVAL")
+
+if [[ -z "$PEAK_INTERVAL_MIN" ]] || [[ "$PEAK_INTERVAL_MIN" -eq 0 ]]; then
+	log_err "Error: invalid peak interval: $PEAK_INTERVAL"
+	exit 1
+fi
+
+if [[ -z "$OFFPEAK_INTERVAL_MIN" ]] || [[ "$OFFPEAK_INTERVAL_MIN" -eq 0 ]]; then
+	log_err "Error: invalid offpeak interval: $OFFPEAK_INTERVAL"
+	exit 1
+fi
+
+# Timer runs at the minimum of the two intervals to handle both schedules
+if [[ "$PEAK_INTERVAL_MIN" -lt "$OFFPEAK_INTERVAL_MIN" ]]; then
+	TIMER_INTERVAL="$PEAK_INTERVAL"
+else
+	TIMER_INTERVAL="$OFFPEAK_INTERVAL"
+fi
+
 if [[ "$INSTALL_DEPS" == "1" ]]; then
 	export DEBIAN_FRONTEND=noninteractive
 	apt-get update -y
@@ -297,6 +356,11 @@ GIT_PUSH_REMOTE=${GIT_PUSH_REMOTE}
 GIT_RUNTIME_BRANCH=runtime-state
 GIT_HTTP_USERNAME=${GIT_HTTP_USERNAME}
 HOME=${RUN_HOME}
+PEAK_START_HOUR=${PEAK_START_HOUR}
+PEAK_END_HOUR=${PEAK_END_HOUR}
+PEAK_TZ=${PEAK_TZ}
+PEAK_INTERVAL_MIN=${PEAK_INTERVAL_MIN}
+OFFPEAK_INTERVAL_MIN=${OFFPEAK_INTERVAL_MIN}
 EOF
 
 if [[ "$GIT_USE_CREDENTIAL_STORE" == "1" ]]; then
@@ -332,11 +396,11 @@ EOF
 
 cat >"/etc/systemd/system/${SERVICE_NAME}.timer" <<EOF
 [Unit]
-Description=Run VMess Domain Rotator every ${INTERVAL}
+Description=Run VMess Domain Rotator every ${TIMER_INTERVAL}
 
 [Timer]
 OnBootSec=2min
-OnUnitActiveSec=${INTERVAL}
+OnUnitActiveSec=${TIMER_INTERVAL}
 AccuracySec=30s
 Unit=${SERVICE_NAME}.service
 Persistent=true
@@ -357,7 +421,10 @@ log "  Working directory: ${APP_DIR}"
 log "  Config path: ${CONFIG_PATH}"
 log "  Service user: ${RUN_USER}"
 log "  Service group: ${RUN_GROUP}"
-log "  Timer interval: ${INTERVAL}"
+log "  Timer interval: ${TIMER_INTERVAL}"
+log "  Peak hour: ${PEAK_START_HOUR} to ${PEAK_END_HOUR} (${PEAK_TZ})"
+log "  Peak interval: ${PEAK_INTERVAL}"
+log "  Off-peak interval: ${OFFPEAK_INTERVAL}"
 log "  Push enabled: ${GIT_PUSH_ENABLED}"
 log "  Push remote: ${GIT_PUSH_REMOTE}"
 log "  Auth mode: ${AUTH_MODE}"
@@ -365,7 +432,7 @@ log "  Env file: ${ENV_FILE}"
 log ""
 log "Commands:"
 log "  Check status: systemctl status ${SERVICE_NAME}.timer"
-log "  View logs:    journalctl -u ${SERVICE_NAME}.service -n 50 --no-pager"
+log "  View logs:    journalctl -t ${SERVICE_NAME} -u ${SERVICE_NAME}.service -n 50 --no-pager"
 log "  Manual run:   sudo systemctl start ${SERVICE_NAME}.service"
 log "  Force commit: sudo -u ${RUN_USER} /bin/bash ${APP_DIR}/scripts/run_update_and_commit.sh --force-commit ${CONFIG_PATH}"
 log ""

+ 52 - 0
scripts/run_update_and_commit.sh

@@ -1,6 +1,12 @@
 #!/usr/bin/env bash
 set -euo pipefail
 
+# --- journald tee: log to journal even when run manually ---
+if [[ -z "${INVOCATION_ID:-}" ]] && command -v systemd-cat >/dev/null 2>&1; then
+  exec > >(tee >(systemd-cat -t vmess-domain-rotator -p info)) \
+       2> >(tee >(systemd-cat -t vmess-domain-rotator -p err) >&2)
+fi
+
 timestamp() {
   date '+%Y-%m-%d %H:%M:%S'
 }
@@ -27,6 +33,52 @@ if [[ ! "$force_commit" =~ ^[01]$ ]]; then
 fi
 CONFIG_PATH="${1:-${APP_DIR}/config.server.json}"
 
+# --- adaptive interval check ---
+if [[ "$force_commit" != "1" ]]; then
+  peak_start="${PEAK_START_HOUR:-19}"
+  peak_end="${PEAK_END_HOUR:-24}"
+  peak_tz="${PEAK_TZ:-Asia/Shanghai}"
+  peak_int="${PEAK_INTERVAL_MIN:-10}"
+  offpeak_int="${OFFPEAK_INTERVAL_MIN:-30}"
+
+  # Get current hour and minute in peak timezone
+  curr_hour=$(TZ="$peak_tz" date '+%H' | sed 's/^0//')
+  curr_hour=${curr_hour:-0}
+  curr_min=$(TZ="$peak_tz" date '+%M' | sed 's/^0//')
+  curr_min=${curr_min:-0}
+
+  # Normalize peak_end=24 to 0 (both mean "end of day / midnight")
+  [[ "$peak_end" -eq 24 ]] && peak_end=0
+
+  in_peak=0
+  if [[ "$peak_start" -eq "$peak_end" ]]; then
+    # start == end: no peak window defined, always off-peak
+    in_peak=0
+  elif [[ "$peak_start" -lt "$peak_end" ]]; then
+    # Normal range (e.g. 8 to 22)
+    if [[ "$curr_hour" -ge "$peak_start" ]] && [[ "$curr_hour" -lt "$peak_end" ]]; then
+      in_peak=1
+    fi
+  else
+    # Crossing midnight (e.g. peak-start 22, peak-end 2)
+    if [[ "$curr_hour" -ge "$peak_start" ]] || [[ "$curr_hour" -lt "$peak_end" ]]; then
+      in_peak=1
+    fi
+  fi
+
+  if [[ "$in_peak" -eq 0 ]]; then
+    # Outside peak hours: only execute near offpeak_int minute boundaries (e.g. 0, 30)
+    # Allow drift tolerance of half the timer tick (peak_int / 2)
+    remainder=$((curr_min % offpeak_int))
+    tolerance=$(( (peak_int + 1) / 2 ))
+    if [[ $remainder -gt $tolerance ]] && [[ $remainder -lt $((offpeak_int - tolerance)) ]]; then
+      log "[vmess-domain-rotator] off-peak run skipped: hour=${curr_hour} minute=${curr_min} (remainder=${remainder}m, next at ${offpeak_int}m boundary)"
+      exit 0
+    fi
+  fi
+  # During peak hours: always execute (timer already fires at peak_int interval)
+fi
+
 export GIT_TERMINAL_PROMPT=0
 
 commit_name="${GIT_COMMIT_NAME:-vmess-domain-rotator}"