🐤 Sync 2026-03-30 12:52:58

This commit is contained in:
github-actions[bot] committed 2026-03-30 12:52:58 +08:00
1 parent 238cb2aa39
commit 9941499a61
63 files changed
+3456 -4029

No files matched your search

@@ -1,6 +1,7 @@
#!/bin/sh /etc/rc.common
#
# Copyright (C) 2023 sirpdboy herboy2008@gmail.com
# Copyright (C) 2022-2026 sirpdboy herboy2008@gmail.com
#
START=99
@@ -21,9 +22,9 @@ _timecontrol_start() {
if [ "$(grep -c 'option enable .1.' /etc/config/$NAME 2>/dev/null)" -gt "0" ]; then
touch $LOCK
timecontrol start
sleep 2
start_instance
else
echo "INFO: ûÓÐÈκιÜÖÆµÄÉ豸£¡"
stop_service
fi
}
@@ -40,11 +41,11 @@ service_triggers() {
stop_service(){
kill -9 $(busybox ps -w | grep 'timecontrolctrl' | grep -v 'grep' | awk '{print $1}') >/dev/null 2>&1
killall timecontrolctrl 2>/dev/null
rm -f $LOCK 2>/dev/null
timecontrol stop
}
reload_service() {
restart
}
@@ -7,7 +7,7 @@
}
EEOF
}
chmod +x /etc/init.d/timecontrol /usr/bin/timecontrol*
chmod +x /etc/init.d/timecontrol /usr/bin/timecontrol* /usr/libexec/timecontrol-call
uci -q batch <<-EOF >/dev/null
delete ucitrack.@timecontrol[-1]
add ucitrack timecontrol
@@ -16,5 +16,7 @@ uci -q batch <<-EOF >/dev/null
EOF
[ -s /etc/config/timecontrol ] || echo "config timecontrol" > /etc/config/timecontrol
/etc/init.d/rpcd restart
rm -f /tmp/luci-indexcache
exit 0
File diff suppressed because it is too large. Load diff
+117
View File
@@ -0,0 +1,117 @@
#!/bin/bash
# 时间控制日志查看工具
NAME=timecontrol
LOG_FILE="/var/log/$NAME.log"
STATUS_LOG="/var/lib/$NAME/status.log"
CONNECTION_LOG="/var/lib/$NAME/connections.log"
show_realtime_log() {
echo "正在显示实时日志,按 Ctrl+C 退出..."
echo ""
tail -f "$LOG_FILE" | while read line; do
# 高亮显示重要信息
if echo "$line" | grep -q "STATUS-CHANGE\|TIME_EXCEEDED\|RESET"; then
echo -e "\033[1;31m$line\033[0m" # 红色显示重要变更
elif echo "$line" | grep -q "ALLOW_ACCESS\|解除限制"; then
echo -e "\033[1;32m$line\033[0m" # 绿色显示允许访问
elif echo "$line" | grep -q "BLOCK_ACCESS\|添加限制"; then
echo -e "\033[1;33m$line\033[0m" # 黄色显示禁止访问
else
echo "$line"
fi
done
}
show_status_log() {
echo "最近状态变更记录:"
echo "────────────────────────────────────────────────────────────────────"
if [ -f "$STATUS_LOG" ]; then
tail -n 20 "$STATUS_LOG" | while read line; do
local time=$(echo "$line" | cut -d']' -f1 | sed 's/\[//')
local message=$(echo "$line" | cut -d']' -f2-)
printf "%-20s %s\n" "$time" "$message"
done
else
echo "暂无状态记录"
fi
}
show_connection_log() {
echo "设备连接记录:"
echo "────────────────────────────────────────────────────────────────────"
echo "时间 设备 状态"
echo "────────────────────────────────────────────────────────────────────"
if [ -f "$CONNECTION_LOG" ]; then
tail -n 20 "$CONNECTION_LOG" | while read line; do
local timestamp=$(echo "$line" | cut -d',' -f1)
local target=$(echo "$line" | cut -d',' -f2)
local action=$(echo "$line" | cut -d',' -f3)
local time_str=$(date -d "@$timestamp" '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo "$timestamp")
local action_text=""
case "$action" in
"connect") action_text="上线" ;;
"disconnect") action_text="下线" ;;
*) action_text="$action" ;;
esac
printf "%-20s %-18s %s\n" "$time_str" "$target" "$action_text"
done
else
echo "暂无连接记录"
fi
}
show_summary() {
local summary_file="/tmp/timecontrol_status.txt"
if [ -f "$summary_file" ]; then
cat "$summary_file"
else
echo "状态摘要文件不存在,正在生成..."
timecontrol status
fi
}
show_help() {
echo "时间控制日志查看工具"
echo ""
echo "用法: timecontrol-log {realtime|status|connections|summary|help}"
echo ""
echo "命令:"
echo " realtime - 实时显示日志(彩色高亮)"
echo " status - 显示状态变更记录"
echo " connections - 显示设备连接记录"
echo " summary - 显示状态摘要"
echo " help - 显示此帮助"
echo ""
echo "示例:"
echo " timecontrol-log realtime # 实时监控"
echo " timecontrol-log status # 查看状态变更"
}
case "$1" in
"realtime")
show_realtime_log
;;
"status")
show_status_log
;;
"connections")
show_connection_log
;;
"summary")
show_summary
;;
"help"|"")
show_help
;;
*)
echo "未知命令: $1"
show_help
exit 1
;;
esac
+294 -66
View File
@@ -1,41 +1,60 @@
#!/bin/sh
# Copyright (C) 2006 OpenWrt.org
# Copyright 2022-2025 sirpdboy <herboy2008@gmail.com>
# Copyright 2022-2026 sirpdboy <herboy2008@gmail.com>
NAME=timecontrol
LOG_FILE="/var/log/timecontrol.log"
DEBUG=1
# 时长数据库目录
DURATION_DIR="/var/lib/timecontrol"
DURATION_DB="$DURATION_DIR/duration.db"
CONNECTION_LOG="$DURATION_DIR/connections.log"
# 状态文件
IDLIST="/var/$NAME.idlist"
TMPID="/var/$NAME.tmpid"
STATUS_DB="$DURATION_DIR/status.db"
idlist=$(uci show $NAME | grep "enable='1'" | grep "device" | grep -oE '\[.*?\]' | grep -o '[0-9]')
config_get_type() {
local ret=$(uci -q get "${NAME}.${1}")
echo "${ret:=$2}"
# 初始化目录
init_dirs() {
mkdir -p "$DURATION_DIR"
touch "$DURATION_DB" "$CONNECTION_LOG" "$STATUS_DB" 2>/dev/null
}
config_n_get() {
local ret=$(uci -q get "${NAME}.${1}.${2}")
echo "${ret:=$3}"
# 日志函数
dbg() {
[ "$DEBUG" -eq 1 ] && {
local d="$(date '+%Y-%m-%d %H:%M:%S')"
echo "[$d] CTRL-DEBUG: $@" >> "$LOG_FILE"
}
}
info() {
local d="$(date '+%Y-%m-%d %H:%M:%S')"
echo "[$d] CTRL-INFO: $@" >> "$LOG_FILE"
}
# 配置文件读取
config_t_get() {
local index=${3:-0}
local ret=$(uci -q get "${NAME}.@${1}[${index}].${2}")
echo "${ret:=${4}}"
local index=${3:-0}
local ret=$(uci -q get "${NAME}.@${1}[${index}].${2}")
echo "${ret:=${4}}"
}
config_t_set() {
local index=${4:-0}
local ret=$(uci -q set "${NAME}.@${1}[${index}].${2}=${3}")
# 获取启用设备
get_enabled_devices() {
uci show $NAME 2>/dev/null | grep "enable='1'" | grep "device" | grep -oE '\[.*?\]' | grep -o '[0-9]' | sort -n
}
# 时间检查函数
is_time_in_range() {
local start_time=$1
local end_time=$2
local current_time=$(date +%H:%M)
if [ "$start_time" = "$end_time" ]; then
return 0
return 0
elif [ "$start_time" \< "$end_time" ]; then
[ "$current_time" \> "$start_time" ] && [ "$current_time" \< "$end_time" ] && return 0
else
@@ -48,60 +67,269 @@ is_weekday_in_range() {
local configured_weekdays=$1
local current_weekday=$(date +%u)
[ "$configured_weekdays" = "0" ] && return 0
for ww in $(echo $configured_weekdays | sed 's/,/ /g'); do
if [ "$current_weekday" = "$ww" ] || [ "$ww" = "0" ]; then
return 0
fi
[ "$current_weekday" = "$ww" ] && return 0
done
return 1
}
check_device() {
local id=$1
local start_time=$(config_t_get device timestart $id )
local end_time=$(config_t_get device timeend $id )
local weekdays=$(config_t_get device week $id )
if is_weekday_in_range "$weekdays" && is_time_in_range "$start_time" "$end_time"; then
return 0
else
return 1
fi
}
update_device_status() {
local id=$1
local action=$2
if [ "$action" = "add" ]; then
timecontrol add $id
echo "!${id}!" >> $IDLIST
elif [ "$action" = "del" ]; then
timecontrol del $id
sed -i "/!$id!/d" $IDLIST >/dev/null 2>&1
fi
}
process_devices() {
[ -s $IDLIST ] || touch $IDLIST
for id in $idlist; do
if check_device $id; then
if ! grep -q "!${id}!" $IDLIST; then
update_device_status $id "add"
fi
else
if grep -q "!${id}!" $IDLIST; then
update_device_status $id "del"
fi
# 时长管理
record_connection_time() {
local target="$1"
local action="$2"
local timestamp=$(date +%s)
echo "$timestamp,$target,$action" >> "$CONNECTION_LOG"
if [ "$action" = "connect" ]; then
if ! grep -q "^$target," "$DURATION_DB" 2>/dev/null; then
echo "$target,$timestamp,0,0" >> "$DURATION_DB"
dbg "初始化时长: $target"
fi
done
cat $IDLIST | sort | uniq > $TMPID
mv $TMPID $IDLIST
elif [ "$action" = "disconnect" ]; then
if grep -q "^$target," "$DURATION_DB" 2>/dev/null; then
local last_connect=$(grep "^$target," "$DURATION_DB" | cut -d',' -f2)
local total_used=$(grep "^$target," "$DURATION_DB" | cut -d',' -f3)
local last_reset=$(grep "^$target," "$DURATION_DB" | cut -d',' -f4)
local session_duration=$((timestamp - last_connect))
local new_total=$((total_used + session_duration))
sed -i "/^$target,/d" "$DURATION_DB"
echo "$target,$timestamp,$new_total,$last_reset" >> "$DURATION_DB"
fi
fi
}
while :; do
process_devices
sleep 60
done
get_connection_time() {
local target="$1"
local current_time=$(date +%s)
if grep -q "^$target," "$DURATION_DB" 2>/dev/null; then
local last_connect=$(grep "^$target," "$DURATION_DB" | cut -d',' -f2)
local total_used=$(grep "^$target," "$DURATION_DB" | cut -d',' -f3)
if tail -n 5 "$CONNECTION_LOG" 2>/dev/null | grep -q "^[0-9]*,$target,connect$"; then
local session_duration=$((current_time - last_connect))
total_used=$((total_used + session_duration))
fi
echo "$total_used"
else
echo "0"
fi
}
# 重置检查
should_reset_duration() {
local target="$1"
local reset_cycle="$2"
local last_reset_file="$DURATION_DIR/last_reset_$target"
[ ! -f "$last_reset_file" ] && return 0
local last_reset=$(cat "$last_reset_file" 2>/dev/null)
local current_time=$(date +%s)
case "$reset_cycle" in
"daily")
local last_date=$(date -d "@$last_reset" +%Y%m%d 2>/dev/null || echo "0")
local current_date=$(date +%Y%m%d)
[ "$last_date" != "$current_date" ]
;;
"weekly")
local last_week=$(date -d "@$last_reset" +%Y%W 2>/dev/null || echo "0")
local current_week=$(date +%Y%W)
[ "$last_week" != "$current_week" ]
;;
"monthly")
local last_month=$(date -d "@$last_reset" +%Y%m 2>/dev/null || echo "0")
local current_month=$(date +%Y%m)
[ "$last_month" != "$current_month" ]
;;
*)
false
;;
esac
}
reset_duration_counter() {
local target="$1"
local reset_cycle="$2"
local current_time=$(date +%s)
if grep -q "^$target," "$DURATION_DB" 2>/dev/null; then
sed -i "/^$target,/d" "$DURATION_DB"
fi
echo "$target,$current_time,0,$current_time" >> "$DURATION_DB"
echo "$current_time" > "$DURATION_DIR/last_reset_$target"
info "重置时长: $target (周期: $reset_cycle)"
}
# 主检查函数
check_device_control() {
local id="$1"
local target=$(config_t_get device mac "$id")
local time_mode=$(config_t_get device time_mode "$id" "period")
local weekdays=$(config_t_get device week "$id" "0")
# 检查星期
is_weekday_in_range "$weekdays" || {
dbg "星期不允许: $target"
return 1
}
case "$time_mode" in
"period")
local start_time=$(config_t_get device timestart "$id" "00:00")
local end_time=$(config_t_get device timeend "$id" "00:00")
is_time_in_range "$start_time" "$end_time" || {
dbg "时间段外: $target ($start_time-$end_time)"
return 1
}
dbg "时间段内: $target"
return 0
;;
"duration")
local duration=$(config_t_get device duration "$id" "60")
local reset_cycle=$(config_t_get device reset_cycle "$id" "daily")
# 重置检查
if should_reset_duration "$target" "$reset_cycle"; then
reset_duration_counter "$target" "$reset_cycle"
fi
# 记录连接
local last_action=$(grep ",$target," "$CONNECTION_LOG" 2>/dev/null | tail -1 | cut -d',' -f3)
if [ "$last_action" != "connect" ]; then
record_connection_time "$target" "connect"
fi
# 检查时长
local used_seconds=$(get_connection_time "$target")
local used_minutes=$((used_seconds / 60))
local max_minutes=$duration
dbg "时长检查: $target 已用=${used_minutes}分钟, 限制=${max_minutes}分钟"
if [ "$used_minutes" -ge "$max_minutes" ]; then
dbg "已超时: $target"
return 1
fi
dbg "未超时: $target"
return 0
;;
"combined")
local start_time=$(config_t_get device timestart "$id" "00:00")
local end_time=$(config_t_get device timeend "$id" "00:00")
local use_duration=$(config_t_get device use_duration "$id" "0")
# 时间段检查
is_time_in_range "$start_time" "$end_time" || {
dbg "时间段外: $target"
return 1
}
# 时长检查
if [ "$use_duration" = "1" ]; then
local duration=$(config_t_get device duration "$id" "60")
local reset_cycle=$(config_t_get device reset_cycle "$id" "daily")
if should_reset_duration "$target" "$reset_cycle"; then
reset_duration_counter "$target" "$reset_cycle"
fi
local last_action=$(grep ",$target," "$CONNECTION_LOG" 2>/dev/null | tail -1 | cut -d',' -f3)
if [ "$last_action" != "connect" ]; then
record_connection_time "$target" "connect"
fi
local used_seconds=$(get_connection_time "$target")
local used_minutes=$((used_seconds / 60))
local max_minutes=$duration
if [ "$used_minutes" -ge "$max_minutes" ]; then
dbg "时间段内但已超时: $target"
return 1
fi
fi
dbg "时间段内允许: $target"
return 0
;;
*)
# 默认时间段控制
local start_time=$(config_t_get device timestart "$id" "00:00")
local end_time=$(config_t_get device timeend "$id" "00:00")
is_time_in_range "$start_time" "$end_time"
return $?
;;
esac
}
# 更新设备状态
update_device_status() {
local id="$1"
local should_allow="$2" # 0=允许, 1=禁止
local target=$(config_t_get device mac "$id")
local comment=$(config_t_get device comment "$id" "设备$id")
# 检查当前状态
local current_blocked=0
if [ -f "$IDLIST" ] && grep -q "!${id}!" "$IDLIST" 2>/dev/null; then
current_blocked=1
fi
dbg "设备状态: $target, 应该允许=$should_allow, 当前阻止=$current_blocked"
if [ "$should_allow" -eq 0 ]; then
# 应该允许
if [ "$current_blocked" -eq 1 ]; then
dbg "解除阻止: $target"
timecontrol del "$id"
sed -i "/!$id!/d" "$IDLIST" 2>/dev/null
info "允许上网: $comment ($target)"
record_connection_time "$target" "disconnect"
fi
else
# 应该阻止
if [ "$current_blocked" -eq 0 ]; then
dbg "添加阻止: $target"
timecontrol add "$id"
if ! grep -q "!$id!" "$IDLIST" 2>/dev/null; then
echo "!$id!" >> "$IDLIST"
fi
info "阻止上网: $comment ($target)"
record_connection_time "$target" "disconnect"
fi
fi
}
# 主处理循环
main_loop() {
info "时间控制守护进程启动"
init_dirs
while :; do
dbg "开始检查设备"
[ `uci show $NAME 2>/dev/null | grep "enable='1'" | grep "device" | grep -oE '\[.*?\]' | grep -o '[0-9]' | sort -n | wc -l` eq 0 ] && timecontrol stop && break
for id in $(get_enabled_devices); do
if check_device_control "$id"; then
update_device_status "$id" 0 # 允许
else
update_device_status "$id" 1 # 阻止
fi
done
sleep 60
done
}
# 启动
main_loop
@@ -1,11 +1,4 @@
{ "admin/control": {
"title": "Control",
"order": 44,
"action": {
"type": "firstchild",
"recurse": true
}
},
{
"admin/control/timecontrol": {
"title": "Time Control",
"order": 10,