−25%

Windows 按年付费,截至 10 月 31 日。 查看套餐

EQVPS
开始使用

如何在 Windows Server 上 24/7 运行脚本:注销、崩溃、重启都不中断

只用任务计划程序,让机器人或脚本在 Windows Server 2022 VPS 上昼夜不停地运行:无人登录也能开机启动,崩溃后一分钟内恢复,并且永远不会同时运行两份。我们强制结束进程并重启服务器做了验证。

在 Windows VPS 上运行机器人的常见做法,是在 RDP 会话里启动它然后关掉窗口。这样能一直运行,直到某次更新在凌晨 3 点重启服务器,再也没人把它启动起来。每台 Windows Server 都自带的任务计划程序无需额外软件就能解决这个问题。下面的配置:

  • 在开机时、任何人登录之前启动脚本;
  • 如果它崩溃或被结束,会在一分钟内重新启动;
  • 绝不会同时运行两份。

这三点我们都在 Windows Server 2022 镜像上验证过:结束进程、重启服务器、统计实例数量。

示例脚本

用来代替你的机器人:每 10 秒写一行,很容易看出它是否还在运行。

New-Item -ItemType Directory -Force C:\bots | Out-Null
Set-Content C:\bots\heartbeat.ps1 -Encoding ascii -Value @'
while ($true) {
    Add-Content -Path C:\bots\heartbeat.log -Value ("{0:u} pid {1}" -f (Get-Date), $PID)
    Start-Sleep -Seconds 10
}
'@

注册任务

在管理员 PowerShell 中运行:

$action   = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-NoProfile -ExecutionPolicy Bypass -File C:\bots\heartbeat.ps1' -WorkingDirectory 'C:\bots'
$atBoot   = New-ScheduledTaskTrigger -AtStartup
$everyMin = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 1)
$settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit ([TimeSpan]::Zero) -MultipleInstances IgnoreNew -StartWhenAvailable
Register-ScheduledTask -TaskName 'mybot' -Action $action -Trigger $atBoot, $everyMin -Settings $settings -User 'SYSTEM' -RunLevel Highest
Start-ScheduledTask -TaskName 'mybot'

各部分的作用:

  • -AtStartup 在 Windows 启动时运行机器人,无需用户登录。
  • 每分钟重复会每分钟再次运行任务。机器人还活着就什么也不发生;如果它挂了,就会重新启动。
  • -MultipleInstances IgnoreNew 让重复变得安全:发现机器人已在运行的那次执行会被跳过。
  • -ExecutionTimeLimit 0 取消默认的 72 小时上限,否则到时任务计划程序会停止机器人。
  • -User 'SYSTEM' 无需密码和会话即可运行。SYSTEM 在服务器上拥有全部权限,所以只用这种方式运行你自己的代码。

如果是 Python,替换操作:

$action = New-ScheduledTaskAction -Execute 'C:\Program Files\Python312\python.exe' -Argument 'C:\bots\bot.py' -WorkingDirectory 'C:\bots'

我们验证了什么

崩溃。 我们用 Stop-Process -Force 结束机器人进程。46 秒后,每分钟的触发器已经启动了新进程,而且正好只有一份。

重启。 我们重启服务器且没有登录。开机 40 秒后,机器人已经在写日志,服务器上没有任何用户会话。

无效的做法。 有两样东西看起来对,其实不对:

  1. “如果任务失败,重新启动间隔…” 我们启用了它,结束进程后,任务在准备就绪状态停了好几分钟。它针对的是任务无法启动的情况,而不是程序之后崩溃。
  2. 包装循环(while ($true) { & bot; sleep 5 })。它能重新启动崩溃的机器人,但如果包装脚本本身挂了,子进程会继续运行,下一次启动又会拉起第二个机器人。我们最后就得到了两份,对 Telegram 机器人来说,这意味着两个进程在抢同一批更新。

如何检查

Get-ScheduledTask -TaskName mybot | Select-Object TaskName, State
Get-ScheduledTaskInfo -TaskName mybot | Select-Object LastRunTime, NextRunTime
Get-Content C:\bots\heartbeat.log -Tail 5

维护时要停止它,先运行 Disable-ScheduledTask mybot(否则每分钟的触发器会再次启动它),然后停止进程。Enable-ScheduledTask mybot 可以恢复。

日志

任务不会捕获输出。让机器人自己写日志(如示例所示),或者在一个小的 .cmd 启动文件中重定向输出,再让 -Execute 指向这个文件。

选哪个套餐

PowerShell 或 Python 机器人几乎不占 CPU,但在我们的镜像上,Windows 本身空闲时就占 1 到 1.3 GB 内存。Windows-Small(4 vCPU、4 GB 内存、50 GB,$11/月)适合跑一两个机器人。在 NAT 套餐上,出站连接(Telegram、交易所 API、你调用的 Webhook)都能正常工作。如果机器人需要接收 Webhook 或其他入站流量,请选择带独立 IPv4 的 Windows Small-IP($28/月)。

下一步:保护 RDP;如果你更喜欢通过 SSH 管理机器人,安装 OpenSSH。支付方式为 USDT、USDC 或 ETH,Windows 是使用你自有许可证的 Server 2022(BYOL)。全部套餐:Windows VPS。

常见问题

为什么不直接让脚本在我的 RDP 会话里运行?

那只能撑到有什么事情结束会话:注销、更新后重启或崩溃。关闭 RDP 窗口(断开连接)会保留会话,但注销会结束其中的一切,而重启后没有人登录去重新启动它。计划任务不依赖任何会话。

任务计划程序不是有“如果任务失败,重新启动”的设置吗?

有,但在我们的测试中没有用。我们结束脚本进程后,任务变成“准备就绪”并一直停在那里。这个设置在任务无法启动时才起作用,而不是在你的程序之后崩溃时。真正把它拉起来的,是本文的重复触发器。

会不会同时运行两个机器人?

用这个配置不会。任务直接运行机器人本身(没有包装脚本),并使用 MultipleInstances IgnoreNew,所以机器人存活时每分钟的触发器什么也不做。真正会制造重复的是包装循环:结束包装脚本后,它的子进程继续运行,新的包装脚本又会再启动一个。我们亲眼看到了这种情况。

Python 或 Node.js 也能这样用吗?

可以。在 -Execute 中填解释器,在 -Argument 中填脚本,都用完整路径,例如 -Execute 'C:\Program Files\Python312\python.exe' -Argument 'C:\bots\bot.py'。请为所有用户安装解释器,这样 SYSTEM 账户才能找到它。

评论

暂无评论。来做第一个吧。

发表评论

评论在显示前会经过审核。