diff --git a/Limiting_Shut_down1.sh b/Limiting_Shut_down1.sh index d970abd00..2fe9e78ad 100644 --- a/Limiting_Shut_down1.sh +++ b/Limiting_Shut_down1.sh @@ -1,48 +1,397 @@ #!/bin/bash -# 获取总的接收流量(只统计公网网卡) -rx_output=$(awk 'BEGIN { rx_total = 0 } - $1 ~ /^(eth|ens|enp|eno)[0-9]+/ { rx_total += $2 } - END { - printf("%.0f Bytes", rx_total); - }' /proc/net/dev) - -# 获取总的发送流量(只统计公网网卡) -tx_output=$(awk 'BEGIN { tx_total = 0 } - $1 ~ /^(eth|ens|enp|eno)[0-9]+/ { tx_total += $10 } - END { - printf("%.0f Bytes", tx_total); - }' /proc/net/dev) - -# 获取接收流量数据 -rx=$(echo "$rx_output" | awk '{print $1}') - -# 获取发送流量数据 -tx=$(echo "$tx_output" | awk '{print $1}') - -# 显示当前流量使用情况 -echo "当前接收流量: $rx Bytes" -echo "当前发送流量: $tx Bytes" +SCRIPT_PATH=$(readlink -f "$0" 2>/dev/null || printf '%s' "$0") +SCRIPT_DIR=$(dirname "$SCRIPT_PATH") +CONFIG_FILE="$SCRIPT_DIR/.kejilion_traffic_limit.conf" +STATE_FILE="$SCRIPT_DIR/.kejilion_traffic_limit.state" rx_threshold_gb=110 tx_threshold_gb=120 +reset_day=1 +persist_after_reboot=0 +boot_grace_minutes=15 -# 将GB转换为字节 -rx_threshold=$((rx_threshold_gb * 1024 * 1024 * 1024)) -tx_threshold=$((tx_threshold_gb * 1024 * 1024 * 1024)) - -# 检查是否达到接收流量阈值 -if (( rx > rx_threshold )); then - echo "接收流量达到${rx_threshold_gb}GB (${rx_threshold} Bytes),正在关闭服务器..." - shutdown -h now -else - echo "当前接收流量未达到${rx_threshold_gb}GB (${rx_threshold} Bytes),继续监视..." -fi - -# 检查是否达到发送流量阈值 -if (( tx > tx_threshold )); then - echo "发送流量达到${tx_threshold_gb}GB (${tx_threshold} Bytes),正在关闭服务器..." - shutdown -h now -else - echo "当前发送流量未达到${tx_threshold_gb}GB (${tx_threshold} Bytes),继续监视..." -fi +is_number() { + [[ "$1" =~ ^[0-9]+$ ]] +} + +load_config() { + if [ -f "$CONFIG_FILE" ]; then + # shellcheck disable=SC1090 + . "$CONFIG_FILE" + fi + + is_number "$rx_threshold_gb" || rx_threshold_gb=110 + is_number "$tx_threshold_gb" || tx_threshold_gb=120 + is_number "$reset_day" || reset_day=1 + is_number "$persist_after_reboot" || persist_after_reboot=0 + is_number "$boot_grace_minutes" || boot_grace_minutes=15 + + (( reset_day < 1 )) && reset_day=1 + (( reset_day > 31 )) && reset_day=31 + (( boot_grace_minutes < 1 )) && boot_grace_minutes=15 + [ "$persist_after_reboot" -eq 1 ] || persist_after_reboot=0 + + rx_threshold=$((rx_threshold_gb * 1024 * 1024 * 1024)) + tx_threshold=$((tx_threshold_gb * 1024 * 1024 * 1024)) +} + +load_state() { + last_rx=0 + last_tx=0 + total_rx=0 + total_tx=0 + period_key="" + last_boot_id="" + maintenance_until=0 + session_skip_boot_id="" + prompt_pending=0 + + if [ -f "$STATE_FILE" ]; then + # shellcheck disable=SC1090 + . "$STATE_FILE" + fi + + is_number "$last_rx" || last_rx=0 + is_number "$last_tx" || last_tx=0 + is_number "$total_rx" || total_rx=0 + is_number "$total_tx" || total_tx=0 + is_number "$maintenance_until" || maintenance_until=0 + is_number "$prompt_pending" || prompt_pending=0 +} + +save_state() { + cat > "$STATE_FILE" </dev/null || echo "unknown-boot" +} + +get_public_traffic() { + awk 'BEGIN { rx_total = 0; tx_total = 0 } + $1 ~ /^(eth|ens|enp|eno)[0-9]+/ { + rx_total += $2 + tx_total += $10 + } + END { + printf("%.0f %.0f\n", rx_total, tx_total); + }' /proc/net/dev +} + +format_bytes() { + local bytes="${1:-0}" + local units=("Bytes" "K" "M" "G" "T" "P") + local unit_index=0 + local value="$bytes" + + while [ "$(printf '%.0f' "$value")" -ge 1024 ] && [ "$unit_index" -lt 5 ]; do + value=$(awk -v v="$value" 'BEGIN { printf "%.2f", v / 1024 }') + unit_index=$((unit_index + 1)) + done + + printf "%s%s" "$value" "${units[$unit_index]}" +} + +format_seconds() { + local seconds="${1:-0}" + (( seconds < 0 )) && seconds=0 + + local hours=$((seconds / 3600)) + local minutes=$(((seconds % 3600) / 60)) + + if (( hours > 0 )); then + printf "%d小时%d分钟" "$hours" "$minutes" + else + printf "%d分钟" "$minutes" + fi +} + +clamp_reset_day() { + local year="$1" + local month="$2" + local wanted="$3" + local last_day + + last_day=$(date -d "${year}-${month}-01 +1 month -1 day" +%d 2>/dev/null) + last_day=$((10#$last_day)) + wanted=$((10#$wanted)) + + if (( wanted > last_day )); then + printf "%d" "$last_day" + else + printf "%d" "$wanted" + fi +} + +get_cycle_key() { + local now_ts="${1:-$(date +%s)}" + local year month current_day current_boundary prev_ref prev_year prev_month prev_day + + year=$(date -d "@$now_ts" +%Y) + month=$(date -d "@$now_ts" +%m) + current_day=$(clamp_reset_day "$year" "$month" "$reset_day") + current_boundary=$(date -d "${year}-${month}-${current_day} 00:00:00" +%s) + + if (( now_ts >= current_boundary )); then + printf "%04d-%02d-%02d" "$year" "$((10#$month))" "$current_day" + else + prev_ref=$(date -d "${year}-${month}-01 -1 month" +%Y-%m) + prev_year=${prev_ref%-*} + prev_month=${prev_ref#*-} + prev_day=$(clamp_reset_day "$prev_year" "$prev_month" "$reset_day") + printf "%04d-%02d-%02d" "$prev_year" "$((10#$prev_month))" "$prev_day" + fi +} + +is_over_limit() { + (( used_rx >= rx_threshold || used_tx >= tx_threshold )) +} + +reset_state_now() { + local current_rx current_tx + + read -r current_rx current_tx < <(get_public_traffic) + load_state + total_rx=0 + total_tx=0 + last_rx=$current_rx + last_tx=$current_tx + period_key=$(get_cycle_key) + last_boot_id=$(get_boot_id) + maintenance_until=0 + session_skip_boot_id="" + prompt_pending=0 + save_state +} + +refresh_usage() { + local now_ts current_rx current_tx current_boot_id current_period_key delta_rx delta_tx + + now_ts=$(date +%s) + current_boot_id=$(get_boot_id) + read -r current_rx current_tx < <(get_public_traffic) + + current_rx=${current_rx:-0} + current_tx=${current_tx:-0} + used_rx=$current_rx + used_tx=$current_tx + + if [ "$persist_after_reboot" -ne 1 ]; then + return + fi + + load_state + current_period_key=$(get_cycle_key "$now_ts") + + if [ "$period_key" != "$current_period_key" ]; then + total_rx=0 + total_tx=0 + maintenance_until=0 + session_skip_boot_id="" + prompt_pending=0 + fi + + if [ "$last_boot_id" != "$current_boot_id" ]; then + delta_rx=$current_rx + delta_tx=$current_tx + session_skip_boot_id="" + total_rx=$((total_rx + delta_rx)) + total_tx=$((total_tx + delta_tx)) + last_rx=$current_rx + last_tx=$current_tx + last_boot_id=$current_boot_id + period_key=$current_period_key + used_rx=$total_rx + used_tx=$total_tx + + if [ "$persist_after_reboot" -eq 1 ] && [ "$session_skip_boot_id" != "$current_boot_id" ] && is_over_limit; then + maintenance_until=$((now_ts + boot_grace_minutes * 60)) + prompt_pending=1 + if command -v wall >/dev/null 2>&1; then + wall "限流自动关机提示:当前累计流量已达到设定阈值,已为本次开机保留 ${boot_grace_minutes} 分钟维护窗口。登录 root 后会看到处理提示。" + fi + fi + + save_state + return + else + if (( current_rx >= last_rx )); then + delta_rx=$((current_rx - last_rx)) + else + delta_rx=$current_rx + fi + + if (( current_tx >= last_tx )); then + delta_tx=$((current_tx - last_tx)) + else + delta_tx=$current_tx + fi + fi + + total_rx=$((total_rx + delta_rx)) + total_tx=$((total_tx + delta_tx)) + last_rx=$current_rx + last_tx=$current_tx + last_boot_id=$current_boot_id + period_key=$current_period_key + used_rx=$total_rx + used_tx=$total_tx + + save_state +} + +show_login_prompt() { + local now_ts current_boot_id remaining_window choice custom_minutes + + [ "$persist_after_reboot" -eq 1 ] || return 0 + [ -t 0 ] || return 0 + [ -t 1 ] || return 0 + + refresh_usage + load_state + now_ts=$(date +%s) + current_boot_id=$(get_boot_id) + + if [ "$session_skip_boot_id" = "$current_boot_id" ]; then + prompt_pending=0 + save_state + return 0 + fi + + is_over_limit || return 0 + [ "$prompt_pending" -eq 1 ] || return 0 + + while true; do + echo + echo "================================================" + echo "当前累计流量已达到设定限额" + echo "当前累计接收: $(format_bytes "$used_rx") / 阈值 ${rx_threshold_gb}G" + echo "当前累计发送: $(format_bytes "$used_tx") / 阈值 ${tx_threshold_gb}G" + echo "当前重置日: 每月 ${reset_day} 日" + if (( maintenance_until > now_ts )); then + remaining_window=$((maintenance_until - now_ts)) + echo "当前维护窗口剩余: $(format_seconds "$remaining_window")" + else + echo "当前维护窗口: 已过期" + fi + echo "------------------------------------------------" + echo "1. 立即关机" + echo "2. 使用默认维护窗口 (${boot_grace_minutes} 分钟)" + echo "3. 自定义维护窗口" + echo "4. 本次开机不再自动关机" + echo "0. 保持当前维护窗口" + echo "------------------------------------------------" + read -r -p "请输入你的选择: " choice + + case "$choice" in + 1) + prompt_pending=0 + maintenance_until=0 + save_state + shutdown -h now + exit 0 + ;; + 2) + maintenance_until=$((now_ts + boot_grace_minutes * 60)) + session_skip_boot_id="" + prompt_pending=0 + save_state + echo "已为本次开机设置 ${boot_grace_minutes} 分钟维护窗口。" + break + ;; + 3) + read -r -p "请输入维护窗口分钟数: " custom_minutes + if is_number "$custom_minutes" && [ "$custom_minutes" -gt 0 ]; then + maintenance_until=$((now_ts + custom_minutes * 60)) + session_skip_boot_id="" + prompt_pending=0 + save_state + echo "已为本次开机设置 ${custom_minutes} 分钟维护窗口。" + break + else + echo "请输入大于 0 的整数分钟数。" + fi + ;; + 4) + session_skip_boot_id=$current_boot_id + maintenance_until=0 + prompt_pending=0 + save_state + echo "本次开机已暂停自动关机。下次重启后若仍超限,会再次提示。" + break + ;; + 0|"") + prompt_pending=0 + save_state + echo "已保留当前维护窗口。" + break + ;; + *) + echo "无效的选择,请重新输入。" + ;; + esac + done +} + +run_monitor() { + local now_ts current_boot_id + + refresh_usage + + echo "当前接收流量: $(format_bytes "$used_rx")" + echo "当前发送流量: $(format_bytes "$used_tx")" + + if ! is_over_limit; then + echo "当前流量未达到阈值,继续监视..." + return 0 + fi + + if [ "$persist_after_reboot" -eq 1 ]; then + load_state + now_ts=$(date +%s) + current_boot_id=$(get_boot_id) + + if [ "$session_skip_boot_id" = "$current_boot_id" ]; then + echo "当前开机已临时暂停自动关机,等待下次重启后重新检查。" + return 0 + fi + + if (( maintenance_until > now_ts )); then + echo "当前已超限,但仍处于维护窗口内。" + return 0 + fi + fi + + echo "累计流量达到设定阈值,正在关闭服务器..." + shutdown -h now +} + +load_config + +case "$1" in + --boot-check) + refresh_usage + ;; + --login-prompt) + show_login_prompt + ;; + --reset-state) + reset_state_now + echo "限流累计数据已清零。" + ;; + *) + run_monitor + ;; +esac diff --git a/kejilion.sh b/kejilion.sh index 0275a3158..ab8394900 100644 --- a/kejilion.sh +++ b/kejilion.sh @@ -3335,6 +3335,193 @@ output_status() { } +traffic_limit_is_number() { + [[ "$1" =~ ^[0-9]+$ ]] +} + +traffic_limit_paths() { + TL_SCRIPT="$HOME/Limiting_Shut_down.sh" + TL_CONFIG="$HOME/.kejilion_traffic_limit.conf" + TL_STATE="$HOME/.kejilion_traffic_limit.state" + TL_PROFILE="/etc/profile.d/kejilion-traffic-limit.sh" +} + +traffic_limit_format_bytes() { + local bytes="${1:-0}" + local units=("Bytes" "K" "M" "G" "T" "P") + local unit_index=0 + local value="$bytes" + + while [ "$(printf '%.0f' "$value")" -ge 1024 ] && [ "$unit_index" -lt 5 ]; do + value=$(awk -v v="$value" 'BEGIN { printf "%.2f", v / 1024 }') + unit_index=$((unit_index + 1)) + done + + printf "%s%s" "$value" "${units[$unit_index]}" +} + +traffic_limit_format_seconds() { + local seconds="${1:-0}" + (( seconds < 0 )) && seconds=0 + + local hours=$((seconds / 3600)) + local minutes=$(((seconds % 3600) / 60)) + + if (( hours > 0 )); then + printf "%d小时%d分钟" "$hours" "$minutes" + else + printf "%d分钟" "$minutes" + fi +} + +traffic_limit_load_settings() { + local rx_threshold_gb="" tx_threshold_gb="" reset_day="" persist_after_reboot="" boot_grace_minutes="" + + traffic_limit_paths + TL_RX_THRESHOLD_GB="" + TL_TX_THRESHOLD_GB="" + TL_RESET_DAY=1 + TL_PERSIST_AFTER_REBOOT=0 + TL_BOOT_GRACE_MINUTES=15 + + if [ -f "$TL_CONFIG" ]; then + # shellcheck disable=SC1090 + . "$TL_CONFIG" + TL_RX_THRESHOLD_GB="$rx_threshold_gb" + TL_TX_THRESHOLD_GB="$tx_threshold_gb" + TL_RESET_DAY="$reset_day" + TL_PERSIST_AFTER_REBOOT="$persist_after_reboot" + TL_BOOT_GRACE_MINUTES="$boot_grace_minutes" + elif [ -f "$TL_SCRIPT" ]; then + TL_RX_THRESHOLD_GB=$(grep -oP '^rx_threshold_gb=\K\d+' "$TL_SCRIPT" | head -n 1) + TL_TX_THRESHOLD_GB=$(grep -oP '^tx_threshold_gb=\K\d+' "$TL_SCRIPT" | head -n 1) + TL_RESET_DAY=$(crontab -l 2>/dev/null | awk '/KEJILION_TRAFFIC_LIMIT_RESET/ {print $3; exit}') + [ -n "$TL_RESET_DAY" ] || TL_RESET_DAY=$(crontab -l 2>/dev/null | awk '/^0 1 [0-9]+ \* \* reboot$/ {print $3; exit}') + fi + + traffic_limit_is_number "$TL_RX_THRESHOLD_GB" || TL_RX_THRESHOLD_GB=100 + traffic_limit_is_number "$TL_TX_THRESHOLD_GB" || TL_TX_THRESHOLD_GB=100 + traffic_limit_is_number "$TL_RESET_DAY" || TL_RESET_DAY=1 + traffic_limit_is_number "$TL_PERSIST_AFTER_REBOOT" || TL_PERSIST_AFTER_REBOOT=0 + traffic_limit_is_number "$TL_BOOT_GRACE_MINUTES" || TL_BOOT_GRACE_MINUTES=15 + + (( TL_RESET_DAY < 1 )) && TL_RESET_DAY=1 + (( TL_RESET_DAY > 31 )) && TL_RESET_DAY=31 + (( TL_BOOT_GRACE_MINUTES < 1 )) && TL_BOOT_GRACE_MINUTES=15 + [ "$TL_PERSIST_AFTER_REBOOT" -eq 1 ] || TL_PERSIST_AFTER_REBOOT=0 +} + +traffic_limit_load_state() { + local total_rx=0 total_tx=0 maintenance_until=0 session_skip_boot_id="" + + traffic_limit_paths + TL_TOTAL_RX=0 + TL_TOTAL_TX=0 + TL_MAINTENANCE_UNTIL=0 + TL_SESSION_SKIP_BOOT_ID="" + + if [ -f "$TL_STATE" ]; then + # shellcheck disable=SC1090 + . "$TL_STATE" + TL_TOTAL_RX="$total_rx" + TL_TOTAL_TX="$total_tx" + TL_MAINTENANCE_UNTIL="$maintenance_until" + TL_SESSION_SKIP_BOOT_ID="$session_skip_boot_id" + fi + + traffic_limit_is_number "$TL_TOTAL_RX" || TL_TOTAL_RX=0 + traffic_limit_is_number "$TL_TOTAL_TX" || TL_TOTAL_TX=0 + traffic_limit_is_number "$TL_MAINTENANCE_UNTIL" || TL_MAINTENANCE_UNTIL=0 +} + +traffic_limit_write_settings() { + local rx_threshold_gb="$1" + local tx_threshold_gb="$2" + local reset_day="$3" + local persist_after_reboot="$4" + local boot_grace_minutes="$5" + + traffic_limit_paths + cat > "$TL_CONFIG" < "$TL_PROFILE" <<'EOF' +if [ "$(id -u 2>/dev/null)" -ne 0 ]; then + return 0 2>/dev/null || exit 0 +fi +case "$-" in + *i*) ;; + *) return 0 2>/dev/null || exit 0 ;; +esac +if [ -x /root/Limiting_Shut_down.sh ]; then + /root/Limiting_Shut_down.sh --login-prompt +fi +EOF + chmod 644 "$TL_PROFILE" +} + +traffic_limit_remove_prompt_profile() { + traffic_limit_paths + rm -f "$TL_PROFILE" +} + +traffic_limit_filter_existing_cron() { + crontab -l 2>/dev/null \ + | grep -v 'KEJILION_TRAFFIC_LIMIT' \ + | grep -v '~/Limiting_Shut_down.sh' \ + | grep -vE '^0 1 [0-9]{1,2} \* \* reboot$' || true +} + +traffic_limit_apply_cron() { + local persist_mode="$1" + local reset_day="$2" + + check_crontab_installed + { + traffic_limit_filter_existing_cron + echo "* * * * * ~/Limiting_Shut_down.sh # KEJILION_TRAFFIC_LIMIT_MONITOR" + if [ "$persist_mode" -eq 1 ]; then + echo "@reboot ~/Limiting_Shut_down.sh --boot-check # KEJILION_TRAFFIC_LIMIT_BOOT" + else + echo "0 1 $reset_day * * reboot # KEJILION_TRAFFIC_LIMIT_RESET" + fi + } | crontab - +} + +traffic_limit_remove_cron() { + check_crontab_installed + traffic_limit_filter_existing_cron | crontab - +} + +traffic_limit_template_path() { + local script_path + + script_path=$(readlink -f "${BASH_SOURCE[0]}" 2>/dev/null || printf '%s' "${BASH_SOURCE[0]}") + printf '%s/Limiting_Shut_down1.sh\n' "$(dirname "$script_path")" +} + +traffic_limit_install_script() { + local template_path + + traffic_limit_paths + template_path=$(traffic_limit_template_path) + if [ -f "$template_path" ]; then + cp "$template_path" "$TL_SCRIPT" + else + curl -Ss -o "$TL_SCRIPT" ${gh_proxy}raw.githubusercontent.com/kejilion/sh/main/Limiting_Shut_down1.sh + fi + chmod +x "$TL_SCRIPT" +} + @@ -19210,77 +19397,135 @@ EOF ;; - 23) - root_use - send_stats "限流关机功能" - while true; do - clear - echo "限流关机功能" - echo "视频介绍: https://www.bilibili.com/video/BV1mC411j7Qd?t=0.1" - echo "------------------------------------------------" - echo "当前流量使用情况,重启服务器流量计算会清零!" - output_status - echo -e "${gl_kjlan}总接收: ${gl_bai}$rx" - echo -e "${gl_kjlan}总发送: ${gl_bai}$tx" - - # 检查是否存在 Limiting_Shut_down.sh 文件 - if [ -f ~/Limiting_Shut_down.sh ]; then - # 获取 threshold_gb 的值 - local rx_threshold_gb=$(grep -oP 'rx_threshold_gb=\K\d+' ~/Limiting_Shut_down.sh) - local tx_threshold_gb=$(grep -oP 'tx_threshold_gb=\K\d+' ~/Limiting_Shut_down.sh) - echo -e "${gl_lv}当前设置的进站限流阈值为: ${gl_huang}${rx_threshold_gb}${gl_lv}G${gl_bai}" - echo -e "${gl_lv}当前设置的出站限流阈值为: ${gl_huang}${tx_threshold_gb}${gl_lv}GB${gl_bai}" - else - echo -e "${gl_hui}当前未启用限流关机功能${gl_bai}" - fi + 23) + root_use + send_stats "限流关机功能" + while true; do + clear + local current_boot_id current_ts + echo "限流关机功能" + echo "视频介绍: https://www.bilibili.com/video/BV1mC411j7Qd?t=0.1" + echo "------------------------------------------------" + echo "当前本次开机流量使用情况" + output_status + echo -e "${gl_kjlan}总接收: ${gl_bai}$rx" + echo -e "${gl_kjlan}总发送: ${gl_bai}$tx" + traffic_limit_load_settings + current_boot_id=$(cat /proc/sys/kernel/random/boot_id 2>/dev/null) + current_ts=$(date +%s) + + if [ -f "$TL_SCRIPT" ]; then + echo -e "${gl_lv}当前设置的进站限流阈值为: ${gl_huang}${TL_RX_THRESHOLD_GB}${gl_lv}G${gl_bai}" + echo -e "${gl_lv}当前设置的出站限流阈值为: ${gl_huang}${TL_TX_THRESHOLD_GB}${gl_lv}G${gl_bai}" + echo -e "${gl_lv}当前流量重置日为: ${gl_huang}每月 ${TL_RESET_DAY} 日${gl_bai}" + if [ "$TL_PERSIST_AFTER_REBOOT" -eq 1 ]; then + traffic_limit_load_state + echo -e "${gl_lv}当前统计模式: ${gl_huang}重启后保留累计数据${gl_bai}" + echo -e "${gl_lv}当前累计接收: ${gl_huang}$(traffic_limit_format_bytes "$TL_TOTAL_RX")${gl_bai}" + echo -e "${gl_lv}当前累计发送: ${gl_huang}$(traffic_limit_format_bytes "$TL_TOTAL_TX")${gl_bai}" + echo -e "${gl_lv}超限后默认维护窗口: ${gl_huang}${TL_BOOT_GRACE_MINUTES}${gl_lv}分钟${gl_bai}" + if [ "$TL_SESSION_SKIP_BOOT_ID" = "$current_boot_id" ] && [ -n "$current_boot_id" ]; then + echo -e "${gl_hui}当前开机已暂停自动关机,下次重启后若仍超限会再次提示。${gl_bai}" + elif [ "$TL_MAINTENANCE_UNTIL" -gt "$current_ts" ]; then + echo -e "${gl_hui}当前维护窗口剩余: $(traffic_limit_format_seconds $((TL_MAINTENANCE_UNTIL - current_ts)))${gl_bai}" + fi + else + echo -e "${gl_lv}当前统计模式: ${gl_huang}重启后清零${gl_bai}" + fi + else + echo -e "${gl_hui}当前未启用限流关机功能${gl_bai}" + fi - echo - echo "------------------------------------------------" - echo "系统每分钟会检测实际流量是否到达阈值,到达后会自动关闭服务器!" - echo "------------------------" - echo "1. 开启限流关机功能 2. 停用限流关机功能" - echo "------------------------" - echo "0. 返回上一级选单" - echo "------------------------" - read -e -p "请输入你的选择: " Limiting + echo + echo "------------------------------------------------" + echo "系统每分钟会检测实际流量是否到达阈值,到达后会自动关闭服务器!" + echo "超限后手动开机时,会提示立即关机、设置维护窗口或本次开机不再自动关机。" + echo "------------------------" + echo "1. 开启/更新限流关机功能 2. 停用限流关机功能" + echo "3. 清零累计流量数据" + echo "------------------------" + echo "0. 返回上一级选单" + echo "------------------------" + read -e -p "请输入你的选择: " Limiting - case "$Limiting" in - 1) - # 输入新的虚拟内存大小 - echo "如果实际服务器就100G流量,可设置阈值为95G,提前关机,以免出现流量误差或溢出。" - read -e -p "请输入进站流量阈值(单位为G,默认100G): " rx_threshold_gb - rx_threshold_gb=${rx_threshold_gb:-100} - read -e -p "请输入出站流量阈值(单位为G,默认100G): " tx_threshold_gb - tx_threshold_gb=${tx_threshold_gb:-100} - read -e -p "请输入流量重置日期(默认每月1日重置): " cz_day - cz_day=${cz_day:-1} - - cd ~ - curl -Ss -o ~/Limiting_Shut_down.sh ${gh_proxy}raw.githubusercontent.com/kejilion/sh/main/Limiting_Shut_down1.sh - chmod +x ~/Limiting_Shut_down.sh - sed -i "s/110/$rx_threshold_gb/g" ~/Limiting_Shut_down.sh - sed -i "s/120/$tx_threshold_gb/g" ~/Limiting_Shut_down.sh - check_crontab_installed - crontab -l | grep -v '~/Limiting_Shut_down.sh' | crontab - - (crontab -l ; echo "* * * * * ~/Limiting_Shut_down.sh") | crontab - > /dev/null 2>&1 - crontab -l | grep -v 'reboot' | crontab - - (crontab -l ; echo "0 1 $cz_day * * reboot") | crontab - > /dev/null 2>&1 - echo "限流关机已设置" - send_stats "限流关机已设置" - ;; - 2) - check_crontab_installed - crontab -l | grep -v '~/Limiting_Shut_down.sh' | crontab - - crontab -l | grep -v 'reboot' | crontab - - rm ~/Limiting_Shut_down.sh - echo "已关闭限流关机功能" - ;; - *) - break - ;; - esac - done - ;; + case "$Limiting" in + 1) + local rx_threshold_gb tx_threshold_gb cz_day persist_choice persist_mode boot_grace_minutes existing_persist + existing_persist="$TL_PERSIST_AFTER_REBOOT" + echo "如果实际服务器就100G流量,可设置阈值为95G,提前关机,以免出现流量误差或溢出。" + read -e -p "请输入进站流量阈值(单位为G,默认100G): " rx_threshold_gb + rx_threshold_gb=${rx_threshold_gb:-100} + read -e -p "请输入出站流量阈值(单位为G,默认100G): " tx_threshold_gb + tx_threshold_gb=${tx_threshold_gb:-100} + read -e -p "请输入流量重置日期(1-31,默认每月1日重置): " cz_day + cz_day=${cz_day:-1} + read -e -p "重启后是否保留累计流量?(Y/N,默认N): " persist_choice + + if ! traffic_limit_is_number "$rx_threshold_gb" || [ "$rx_threshold_gb" -le 0 ]; then + rx_threshold_gb=100 + fi + if ! traffic_limit_is_number "$tx_threshold_gb" || [ "$tx_threshold_gb" -le 0 ]; then + tx_threshold_gb=100 + fi + if ! traffic_limit_is_number "$cz_day" || [ "$cz_day" -lt 1 ] || [ "$cz_day" -gt 31 ]; then + cz_day=1 + fi + + case "$persist_choice" in + [Yy]) persist_mode=1 ;; + *) persist_mode=0 ;; + esac + + boot_grace_minutes=15 + if [ "$persist_mode" -eq 1 ]; then + read -e -p "请输入超限后手动开机的默认维护窗口分钟数(默认15分钟): " boot_grace_minutes + boot_grace_minutes=${boot_grace_minutes:-15} + if ! traffic_limit_is_number "$boot_grace_minutes" || [ "$boot_grace_minutes" -le 0 ]; then + boot_grace_minutes=15 + fi + fi + + cd ~ + traffic_limit_install_script + traffic_limit_write_settings "$rx_threshold_gb" "$tx_threshold_gb" "$cz_day" "$persist_mode" "$boot_grace_minutes" + + if [ "$persist_mode" -eq 1 ]; then + traffic_limit_install_prompt_profile + if [ "$existing_persist" -ne 1 ] || [ ! -f "$TL_STATE" ]; then + "$TL_SCRIPT" --boot-check > /dev/null 2>&1 + fi + else + traffic_limit_remove_prompt_profile + rm -f "$TL_STATE" + fi + + traffic_limit_apply_cron "$persist_mode" "$cz_day" + echo "限流关机已设置" + send_stats "限流关机已设置" + ;; + 2) + traffic_limit_remove_cron + traffic_limit_remove_prompt_profile + rm -f "$TL_SCRIPT" "$TL_CONFIG" "$TL_STATE" + echo "已关闭限流关机功能" + ;; + 3) + if [ ! -x "$TL_SCRIPT" ]; then + echo "当前未启用限流关机功能" + elif [ "$TL_PERSIST_AFTER_REBOOT" -ne 1 ]; then + echo "当前模式为重启清零,无需手动清零累计数据。" + else + "$TL_SCRIPT" --reset-state > /dev/null 2>&1 + echo "累计流量数据已清零" + fi + ;; + *) + break + ;; + esac + sleep 1 + done + ;; 24)