−25%

за Windows при годишно плащане, до 31.10. Към плановете

EQVPS
Започни

Как да пуснете скрипт 24/7 на Windows Server: оцелява при излизане, сривове и рестарти

Бот или скрипт денонощно на VPS с Windows Server 2022 само с Task Scheduler: стартира при зареждане без влязъл потребител, рестартира се до минута след срив и никога не работи в две копия. Спирахме процеса принудително и рестартирахме сървъра, за да проверим.

Обичайният начин да пуснете бот на Windows VPS е да го стартирате в RDP сесия и да затворите прозореца. Това работи, докато обновление не рестартира сървъра в 3 през нощта и никой не го пусне отново. Task Scheduler, който го има на всеки 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 часа, след който Task Scheduler би спрял бота.
  • -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 почти не натоварва процесора, но самата Windows заема в покой от 1 до 1,3 GB RAM на нашия образ. Windows-Small (4 vCPU, 4 GB RAM, 50 GB, $11/месец) е подходящият размер за един-два бота. На план с NAT изходящите връзки (Telegram, API на борси, уебкуки, които извиквате) работят нормално. Ако ботът трябва да приема уебкуки или друг входящ трафик, изберете Windows Small-IP ($28/месец) със собствен IPv4.

Следващи стъпки: защитете RDP, а ако предпочитате да управлявате бота през SSH, инсталирайте OpenSSH. Плащането е в USDT, USDC или ETH, а Windows е Server 2022 с вашия собствен лиценз (BYOL). Всички планове: Windows VPS.

Въпроси

Защо просто да не оставя скрипта в RDP сесията си?

Това работи, докато нещо не прекрати сесията: излизане от акаунта, рестарт след обновления или срив. Затварянето на прозореца на RDP (прекъсване) оставя сесията жива, но излизането от акаунта спира всичко в нея, а след рестарт никой не е влязъл, за да пусне скрипта отново. Задачата в Task Scheduler не зависи от сесия.

Няма ли в Task Scheduler настройка „рестартиране при неуспех“?

Има, но в нашата проверка не помогна. Когато спряхме процеса на скрипта, задачата премина в състояние „Готова“ и остана там. Настройката реагира, когато задачата не може да стартира, а не когато програмата ви умре по-късно. Връща я повтарящият се тригер от това ръководство.

Може ли да тръгнат две копия на бота ми?

Не и с тази настройка. Задачата пуска самия бот (без скрипт-обвивка) и използва MultipleInstances IgnoreNew, затова тригерът всяка минута не прави нищо, докато ботът е жив. Дублите ги създава именно обвивка с цикъл: спрете обвивката, дъщерният ѝ процес продължава, а новата обвивка пуска още един. Видяхме точно това.

Работи ли това за Python или Node.js?

Да. Посочете интерпретатора в -Execute, а скрипта в -Argument, с пълни пътища, например -Execute 'C:\Program Files\Python312\python.exe' -Argument 'C:\bots\bot.py'. Инсталирайте интерпретатора за всички потребители, за да го намери акаунтът SYSTEM.

Коментари

Още няма коментари. Бъди първият.

Остави коментар

Коментарите се модерират преди да се появят.