mirror of
https://mirror.skon.top/github.com/cft0808/edict
synced 2026-04-21 05:10:27 +08:00
run_loop.sh 的 Windows 等效版本,支持单实例保护、日志轮转、 超时控制和定时巡检。感谢 @Vip4pt 贡献。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
120 lines
3.5 KiB
PowerShell
120 lines
3.5 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
三省六部数据刷新循环 (Windows PowerShell 版本)
|
|
.DESCRIPTION
|
|
run_loop.sh 的 Windows 等效脚本。
|
|
用法: .\run_loop.ps1 [-Interval 15] [-ScanInterval 120]
|
|
.NOTES
|
|
源自 GitHub Issue #245 (感谢 @Vip4pt 贡献)
|
|
#>
|
|
param(
|
|
[int]$Interval = 15,
|
|
[int]$ScanInterval = 120
|
|
)
|
|
|
|
# ── 基础配置 ──
|
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
if (-not $env:OPENCLAW_HOME) {
|
|
$env:OPENCLAW_HOME = Split-Path -Parent $ScriptDir
|
|
}
|
|
|
|
$Log = "$env:TEMP\sansheng_liubu_refresh.log"
|
|
$PidFile = "$env:TEMP\sansheng_liubu_refresh.pid"
|
|
$MaxLogSize = 10MB
|
|
$ScriptTimeout = 30
|
|
$DashboardPort = $env:EDICT_DASHBOARD_PORT
|
|
if (-not $DashboardPort) { $DashboardPort = 7891 }
|
|
|
|
# ── 单实例保护 ──
|
|
if (Test-Path $PidFile) {
|
|
$OldPid = Get-Content $PidFile -ErrorAction SilentlyContinue
|
|
if ($OldPid -and (Get-Process -Id $OldPid -ErrorAction SilentlyContinue)) {
|
|
Write-Host "Already running (PID=$OldPid), exiting."
|
|
exit 1
|
|
}
|
|
Remove-Item $PidFile -Force -ErrorAction SilentlyContinue
|
|
}
|
|
$PID | Out-File $PidFile
|
|
|
|
# ── 优雅退出 ──
|
|
$cleanup = {
|
|
"$(Get-Date -Format HH:mm:ss) [loop] Shutting down..." | Out-File $Log -Append
|
|
Remove-Item $PidFile -Force -ErrorAction SilentlyContinue
|
|
exit
|
|
}
|
|
Register-EngineEvent PowerShell.Exiting -Action $cleanup | Out-Null
|
|
|
|
# ── 日志轮转 ──
|
|
function Rotate-Log {
|
|
if (Test-Path $Log) {
|
|
$size = (Get-Item $Log).Length
|
|
if ($size -gt $MaxLogSize) {
|
|
Move-Item $Log "$Log.1" -Force
|
|
"$(Get-Date -Format HH:mm:ss) [loop] Log rotated" | Out-File $Log
|
|
}
|
|
}
|
|
}
|
|
|
|
# ── 安全执行(带超时)──
|
|
function Safe-Run($script) {
|
|
$psi = New-Object System.Diagnostics.ProcessStartInfo
|
|
$psi.FileName = "python"
|
|
$psi.Arguments = "`"$script`""
|
|
$psi.RedirectStandardOutput = $true
|
|
$psi.RedirectStandardError = $true
|
|
$psi.UseShellExecute = $false
|
|
|
|
$process = New-Object System.Diagnostics.Process
|
|
$process.StartInfo = $psi
|
|
$process.Start() | Out-Null
|
|
|
|
if (-not $process.WaitForExit($ScriptTimeout * 1000)) {
|
|
try {
|
|
$process.Kill()
|
|
"$(Get-Date -Format HH:mm:ss) [loop] Script timeout (${ScriptTimeout}s): $script" | Out-File $Log -Append
|
|
} catch {}
|
|
}
|
|
|
|
$stdout = $process.StandardOutput.ReadToEnd()
|
|
$stderr = $process.StandardError.ReadToEnd()
|
|
|
|
if ($stdout) { $stdout | Out-File $Log -Append }
|
|
if ($stderr) { $stderr | Out-File $Log -Append }
|
|
}
|
|
|
|
# ── 启动信息 ──
|
|
Write-Host "Data refresh loop started (PID=$PID)"
|
|
Write-Host " Script dir: $ScriptDir"
|
|
Write-Host " Interval: ${Interval}s Scan: ${ScanInterval}s Timeout: ${ScriptTimeout}s"
|
|
Write-Host " Log: $Log"
|
|
Write-Host " Ctrl+C to stop"
|
|
|
|
$ScanCounter = 0
|
|
|
|
# ── 主循环 ──
|
|
while ($true) {
|
|
Rotate-Log
|
|
|
|
Safe-Run "$ScriptDir\sync_from_openclaw_runtime.py"
|
|
Safe-Run "$ScriptDir\sync_agent_config.py"
|
|
Safe-Run "$ScriptDir\apply_model_changes.py"
|
|
Safe-Run "$ScriptDir\sync_officials_stats.py"
|
|
Safe-Run "$ScriptDir\refresh_live_data.py"
|
|
|
|
# ── 巡检任务 ──
|
|
$ScanCounter += $Interval
|
|
if ($ScanCounter -ge $ScanInterval) {
|
|
$ScanCounter = 0
|
|
try {
|
|
Invoke-RestMethod -Uri "http://127.0.0.1:$DashboardPort/api/scheduler-scan" `
|
|
-Method POST `
|
|
-ContentType "application/json" `
|
|
-Body '{"thresholdSec":180}' | Out-Null
|
|
} catch {
|
|
$_ | Out-File $Log -Append
|
|
}
|
|
}
|
|
|
|
Start-Sleep -Seconds $Interval
|
|
}
|