NaiveProxy Windows 开机自启动,避免前台跑出现异常
最初手动双击 `naive.exe` 可以运行,但会打开一个窗口并持续输出日志。日志太多时,进程可能会自动退出。因此改为使用 Windows 内置的任务计划程序加守护脚本运行。
背景
本机有一个 NaiveProxy 程序,需要在 Windows 开机后自动后台运行。
程序目录:
text
C:\Users\halcyon\Documents\naiveproxy目录内主要文件:
text
naive.exe
config.json最初手动双击 naive.exe 可以运行,但会打开一个窗口并持续输出日志。日志太多时,进程可能会自动退出。因此改为使用 Windows 内置的任务计划程序加守护脚本运行。
最终方案
使用:
text
Windows Task Scheduler + PowerShell guardian script优点:
- 不需要安装第三方工具
- 开机自动启动
- 后台隐藏窗口运行
- 进程退出后自动重启
- 日志写入文件
- 自动清理旧日志
守护脚本路径
脚本保存位置:
text
C:\Users\halcyon\Documents\naiveproxy\run-naiveproxy.ps1脚本内容:
powershell
$ErrorActionPreference = "Stop"
$Root = "C:\Users\halcyon\Documents\naiveproxy"
$Exe = Join-Path $Root "naive.exe"
$LogDir = Join-Path $Root "logs"
New-Item -ItemType Directory -Force -Path $LogDir | Out-Null
function Remove-OldLogs {
Get-ChildItem -LiteralPath $LogDir -Filter "*.log" -File -ErrorAction SilentlyContinue |
Sort-Object LastWriteTime -Descending |
Select-Object -Skip 20 |
Remove-Item -Force -ErrorAction SilentlyContinue
}
while ($true) {
Remove-OldLogs
$stamp = Get-Date -Format "yyyyMMdd-HHmmss"
$stdout = Join-Path $LogDir "naiveproxy-$stamp.out.log"
$stderr = Join-Path $LogDir "naiveproxy-$stamp.err.log"
$p = Start-Process `
-FilePath $Exe `
-ArgumentList "config.json" `
-WorkingDirectory $Root `
-WindowStyle Hidden `
-RedirectStandardOutput $stdout `
-RedirectStandardError $stderr `
-PassThru
$p.WaitForExit()
Add-Content -LiteralPath $stderr -Value ("[{0}] naiveproxy exited with code {1}; restarting in 5 seconds." -f (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $p.ExitCode)
Start-Sleep -Seconds 5
}创建守护脚本
在管理员 PowerShell 中执行:
powershell
@'
$ErrorActionPreference = "Stop"
$Root = "C:\Users\halcyon\Documents\naiveproxy"
$Exe = Join-Path $Root "naive.exe"
$LogDir = Join-Path $Root "logs"
New-Item -ItemType Directory -Force -Path $LogDir | Out-Null
function Remove-OldLogs {
Get-ChildItem -LiteralPath $LogDir -Filter "*.log" -File -ErrorAction SilentlyContinue |
Sort-Object LastWriteTime -Descending |
Select-Object -Skip 20 |
Remove-Item -Force -ErrorAction SilentlyContinue
}
while ($true) {
Remove-OldLogs
$stamp = Get-Date -Format "yyyyMMdd-HHmmss"
$stdout = Join-Path $LogDir "naiveproxy-$stamp.out.log"
$stderr = Join-Path $LogDir "naiveproxy-$stamp.err.log"
$p = Start-Process `
-FilePath $Exe `
-ArgumentList "config.json" `
-WorkingDirectory $Root `
-WindowStyle Hidden `
-RedirectStandardOutput $stdout `
-RedirectStandardError $stderr `
-PassThru
$p.WaitForExit()
Add-Content -LiteralPath $stderr -Value ("[{0}] naiveproxy exited with code {1}; restarting in 5 seconds." -f (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $p.ExitCode)
Start-Sleep -Seconds 5
}
'@ | Set-Content -Encoding UTF8 "C:\Users\halcyon\Documents\naiveproxy\run-naiveproxy.ps1"注册开机启动任务
在管理员 PowerShell 中执行:
powershell
$action = New-ScheduledTaskAction `
-Execute "powershell.exe" `
-Argument '-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File "C:\Users\halcyon\Documents\naiveproxy\run-naiveproxy.ps1"'
$trigger = New-ScheduledTaskTrigger -AtStartup
$settings = New-ScheduledTaskSettingsSet `
-AllowStartIfOnBatteries `
-DontStopIfGoingOnBatteries `
-ExecutionTimeLimit ([TimeSpan]::Zero) `
-RestartCount 999 `
-RestartInterval (New-TimeSpan -Minutes 1) `
-MultipleInstances IgnoreNew
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest
Register-ScheduledTask `
-TaskName "naiveproxy-guardian" `
-Action $action `
-Trigger $trigger `
-Settings $settings `
-Principal $principal启动任务
powershell
Start-ScheduledTask -TaskName "naiveproxy-guardian"查看任务状态
powershell
Get-ScheduledTask -TaskName "naiveproxy-guardian"也可以查看更详细的运行信息:
powershell
Get-ScheduledTaskInfo -TaskName "naiveproxy-guardian"停止任务
powershell
Stop-ScheduledTask -TaskName "naiveproxy-guardian"注意:停止任务会停止守护脚本,但如果 naive.exe 已经被脚本启动,必要时可手动结束 naive.exe 进程。
删除任务
powershell
Unregister-ScheduledTask -TaskName "naiveproxy-guardian" -Confirm:$false日志位置
日志目录:
text
C:\Users\halcyon\Documents\naiveproxy\logs日志文件格式:
text
naiveproxy-YYYYMMDD-HHMMSS.out.log
naiveproxy-YYYYMMDD-HHMMSS.err.log脚本会保留最近 20 个 .log 文件,旧日志会自动清理。
维护注意事项
修改 config.json 后,建议重启任务:
powershell
Stop-ScheduledTask -TaskName "naiveproxy-guardian"
Start-ScheduledTask -TaskName "naiveproxy-guardian"如果修改了 run-naiveproxy.ps1,同样需要重启任务。
如果发现代理不可用,优先检查:
config.json是否正确C:\Users\halcyon\Documents\naiveproxy\logs下最新的.err.log- 是否已经有其他手动启动的
naive.exe占用了同一个端口 - 任务计划程序中的
naiveproxy-guardian是否正在运行
当时遇到的问题
尝试过使用 NSSM 将程序包装为 Windows Service,但本机没有 nssm 命令:
text
nssm : 无法将“nssm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称随后尝试通过 winget 安装 NSSM,但本机也没有 winget。由于 NSSM 无法方便下载,最终改用 Windows 内置任务计划程序方案。
当前结论
当前方案已经验证可用:
text
naiveproxy-guardian 任务计划程序项负责开机启动 run-naiveproxy.ps1
run-naiveproxy.ps1 负责后台启动 naive.exe config.json
naive.exe 退出后,脚本等待 5 秒并自动重启
日志写入 naiveproxy\logs