−25%

la planurile Windows anuale, până pe 31 oct. Vezi planurile

EQVPS
Începe

Cum rulezi un script 24/7 pe Windows Server: rezistă la deconectare, căderi și reporniri

Ține un bot sau un script pornit zi și noapte pe un VPS cu Windows Server 2022 doar cu Task Scheduler: pornește la boot fără niciun utilizator conectat, repornește în mai puțin de un minut după o cădere și nu rulează niciodată două copii. Am oprit forțat procesul și am repornit ca să verificăm.

Modul obișnuit de a rula un bot pe un VPS Windows este să-l pornești într-o sesiune RDP și să închizi fereastra. Merge până când o actualizare repornește serverul la 3 noaptea și nimeni nu-l mai pornește. Task Scheduler, prezent pe orice Windows Server, rezolvă asta fără software suplimentar. Configurația de mai jos:

  • pornește scriptul la boot, înainte să se conecteze cineva;
  • îl repornește în mai puțin de un minut dacă se blochează sau e oprit forțat;
  • nu rulează niciodată două copii simultan.

Am testat toate trei pe imaginea noastră Windows Server 2022: proces oprit forțat, server repornit, instanțe numărate.

Scriptul de exemplu

Un înlocuitor pentru botul tău: scrie un rând la fiecare 10 secunde, ca să vezi ușor dacă e viu.

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
}
'@

Înregistrează sarcina

Rulează într-un PowerShell cu drepturi de administrator:

$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'

Ce face fiecare parte:

  • -AtStartup pornește botul când Windows pornește, fără utilizator conectat.
  • Repetarea la fiecare minut rulează sarcina din nou în fiecare minut. Dacă botul e viu, nu se întâmplă nimic; dacă a murit, pornește din nou.
  • -MultipleInstances IgnoreNew face repetarea sigură: o rulare care găsește botul deja pornit este sărită.
  • -ExecutionTimeLimit 0 dezactivează limita implicită de 72 de ore, după care Task Scheduler ar opri botul.
  • -User 'SYSTEM' îl rulează fără parolă și fără sesiune. SYSTEM are drepturi depline pe server, așa că rulează astfel doar propriul cod.

Pentru Python, înlocuiește acțiunea:

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

Ce am verificat

Cădere. Am oprit forțat procesul botului cu Stop-Process -Force. După 46 de secunde, declanșatorul de la fiecare minut pornise unul nou și exista exact o copie.

Repornire. Am repornit serverul și nu ne-am conectat. La 40 de secunde după boot, botul scria deja în jurnal, fără sesiuni de utilizator pe server.

Ce nu a funcționat. Două lucruri par corecte, dar nu sunt:

  1. „Dacă sarcina eșuează, repornește la fiecare…” Am activat-o, am oprit forțat procesul, iar sarcina a stat minute întregi în Pregătit. Reacționează la o sarcină care nu reușește să pornească, nu la programul care moare mai târziu.
  2. O buclă de împachetare (while ($true) { & bot; sleep 5 }). Repornește un bot căzut, dar dacă moare chiar împachetarea, copilul continuă să ruleze și următoarea pornire lansează un al doilea bot. Am ajuns la două copii, ceea ce pentru un bot Telegram înseamnă două procese care se bat pe aceleași actualizări.

Cum verifici

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

Ca să-l oprești pentru mentenanță, rulează mai întâi Disable-ScheduledTask mybot (altfel declanșatorul de la fiecare minut îl pornește din nou), apoi oprește procesul. Enable-ScheduledTask mybot îl readuce.

Jurnale

Sarcina nu capturează ieșirea. Lasă botul să-și scrie singur jurnalul, ca în exemplu, sau redirecționează ieșirea într-un mic lansator .cmd și îndreaptă -Execute spre acel fișier.

Ce plan

Un bot în PowerShell sau Python consumă puțin CPU, dar Windows singur ocupă în repaus între 1 și 1,3 GB RAM pe imaginea noastră. Windows-Small (4 vCPU, 4 GB RAM, 50 GB, $11/lună) este dimensiunea potrivită pentru unul sau doi boți. Pe un plan NAT, conexiunile de ieșire (Telegram, API-uri de exchange-uri, webhook-uri pe care le apelezi) funcționează normal. Dacă botul trebuie să primească webhook-uri sau alt trafic de intrare, alege Windows Small-IP ($28/lună) cu IPv4 propriu.

Pașii următori: securizează RDP și, dacă preferi să administrezi botul prin SSH, instalează OpenSSH. Plata se face în USDT, USDC sau ETH, iar Windows este Server 2022 cu propria ta licență (BYOL). Toate planurile: Windows VPS.

Întrebări frecvente

De ce să nu las scriptul în sesiunea mea RDP?

Merge până când ceva închide sesiunea: o deconectare a contului, o repornire după actualizări sau o cădere. Închiderea ferestrei RDP (deconectarea) păstrează sesiunea, dar ieșirea din cont omoară tot ce rulează în ea, iar după repornire nimeni nu e conectat ca să pornească scriptul din nou. O sarcină planificată nu depinde de nicio sesiune.

Task Scheduler nu are opțiunea „repornește dacă eșuează”?

Are, dar în testul nostru nu a ajutat. Când am oprit forțat procesul scriptului, sarcina a trecut în „Pregătit” și a rămas acolo. Opțiunea reacționează când sarcina nu reușește să pornească, nu când programul tău moare mai târziu. Ce îl readuce este declanșatorul repetat din acest ghid.

Pot ajunge să ruleze două copii ale botului?

Nu cu această configurație. Sarcina rulează botul însuși (fără script de împachetare) și folosește MultipleInstances IgnoreNew, așa că declanșatorul de la fiecare minut nu face nimic cât timp botul trăiește. Dublurile le creează tocmai o buclă de împachetare: oprești împachetarea, procesul copil merge mai departe, iar o nouă împachetare pornește încă unul. Exact asta am văzut.

Funcționează cu Python sau Node.js?

Da. Pune interpretorul în -Execute și scriptul în -Argument, cu căi complete, de exemplu -Execute 'C:\Program Files\Python312\python.exe' -Argument 'C:\bots\bot.py'. Instalează interpretorul pentru toți utilizatorii, ca să-l găsească contul SYSTEM.

Comentarii

Încă nu există comentarii. Fii primul.

Lasă un comentariu

Comentariile sunt moderate înainte să apară.