−25%

na Windows przy płatności rocznej, do 31.10. Do planów

EQVPS
Zacznij

Jak uruchomić skrypt 24/7 na Windows Server: przetrwa wylogowanie, awarie i restarty

Bot lub skrypt działający całą dobę na VPS z Windows Server 2022 tylko dzięki Harmonogramowi zadań: start przy rozruchu bez zalogowanego użytkownika, ponowne uruchomienie w ciągu minuty po awarii i nigdy dwie kopie. Zabijaliśmy proces i restartowaliśmy serwer, żeby to sprawdzić.

Zwykle bota na VPS z Windows uruchamia się w sesji RDP i zamyka okno. To działa, dopóki aktualizacja nie zrestartuje serwera o 3 w nocy i nikt go nie uruchomi ponownie. Harmonogram zadań, obecny w każdym Windows Server, rozwiązuje to bez dodatkowego oprogramowania. Konfiguracja poniżej:

  • uruchamia skrypt przy rozruchu, zanim ktokolwiek się zaloguje;
  • uruchamia go ponownie w ciągu minuty, jeśli padnie lub zostanie zabity;
  • nigdy nie uruchamia dwóch kopii naraz.

Wszystkie trzy punkty sprawdziliśmy na naszym obrazie Windows Server 2022: zabity proces, restart serwera, policzone instancje.

Przykładowy skrypt

Zastępca twojego bota: co 10 sekund zapisuje wiersz, więc łatwo zobaczyć, czy żyje.

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

Zarejestruj zadanie

Uruchom w PowerShell z uprawnieniami administratora:

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

Co robi każda część:

  • -AtStartup uruchamia bota przy starcie Windows, bez zalogowanego użytkownika.
  • Powtórzenie co minutę uruchamia zadanie ponownie co minutę. Jeśli bot żyje, nic się nie dzieje; jeśli padł, startuje od nowa.
  • -MultipleInstances IgnoreNew sprawia, że powtarzanie jest bezpieczne: uruchomienie, które zastaje działającego bota, jest pomijane.
  • -ExecutionTimeLimit 0 wyłącza domyślny limit 72 godzin, po którym Harmonogram zatrzymałby bota.
  • -User 'SYSTEM' uruchamia go bez hasła i bez sesji. SYSTEM ma pełne prawa na serwerze, więc tak uruchamiaj tylko własny kod.

Dla Pythona zamień akcję:

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

Co sprawdziliśmy

Awaria. Zabiliśmy proces bota przez Stop-Process -Force. Po 46 sekundach wyzwalacz co minutę uruchomił nowy i była dokładnie jedna kopia.

Restart. Zrestartowaliśmy serwer i nie logowaliśmy się. 40 sekund po rozruchu bot już pisał do swojego logu, bez żadnych sesji użytkowników na serwerze.

Co nie zadziałało. Dwie rzeczy wyglądają dobrze, a nie są:

  1. „Jeśli zadanie zakończy się niepowodzeniem, uruchamiaj ponownie co…” Włączyliśmy to, zabiliśmy proces, a zadanie przez kilka minut stało w stanie Gotowe. Opcja reaguje na zadanie, które nie może wystartować, a nie na program, który pada później.
  2. Pętla w opakowaniu (while ($true) { & bot; sleep 5 }). Restartuje bota po awarii, ale jeśli padnie samo opakowanie, jego proces potomny działa dalej, a kolejne uruchomienie startuje drugiego bota. Skończyło się na dwóch kopiach, co dla bota Telegrama oznacza dwa procesy walczące o te same aktualizacje.

Jak sprawdzić

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

Aby zatrzymać bota na czas prac, najpierw Disable-ScheduledTask mybot (inaczej wyzwalacz co minutę znów go uruchomi), potem zatrzymaj proces. Enable-ScheduledTask mybot przywraca wszystko.

Logi

Zadanie nie przechwytuje wyjścia. Niech bot sam pisze log do pliku, jak w przykładzie, albo przekieruj wyjście w małym pliku .cmd i wskaż go w -Execute.

Jaki plan

Bot w PowerShell lub Pythonie zużywa mało CPU, ale sam Windows zajmuje na naszym obrazie w spoczynku od 1 do 1,3 GB RAM. Windows-Small (4 vCPU, 4 GB RAM, 50 GB, $11/mies.) to dobry rozmiar na jednego lub dwa boty. Na planie NAT połączenia wychodzące (Telegram, API giełd, wywoływane webhooki) działają normalnie. Jeśli bot ma przyjmować webhooki lub inny ruch przychodzący, wybierz Windows Small-IP ($28/mies.) z własnym IPv4.

Dalej: zabezpiecz RDP, a jeśli wolisz zarządzać botem przez SSH, zainstaluj OpenSSH. Płatność w USDT, USDC lub ETH, a Windows to Server 2022 z twoją licencją (BYOL). Wszystkie plany: Windows VPS.

FAQ

Czemu po prostu nie zostawić skryptu w sesji RDP?

To działa, dopóki coś nie zakończy sesji: wylogowanie, restart po aktualizacji albo awaria. Zamknięcie okna RDP (rozłączenie) zostawia sesję, ale wylogowanie zabija wszystko, co w niej działa, a po restarcie nikt nie jest zalogowany, żeby uruchomić skrypt ponownie. Zadanie Harmonogramu nie zależy od żadnej sesji.

Czy Harmonogram zadań nie ma opcji „uruchom ponownie w razie niepowodzenia”?

Ma, ale w naszym teście nie pomogła. Gdy zabiliśmy proces skryptu, zadanie przeszło w stan „Gotowe” i tam zostało. Ta opcja reaguje, gdy zadanie nie może wystartować, a nie gdy twój program padnie później. Przywraca go powtarzany wyzwalacz z tego poradnika.

Czy mogą działać dwie kopie mojego bota?

Przy tej konfiguracji nie. Zadanie uruchamia samego bota (bez skryptu-opakowania) i używa MultipleInstances IgnoreNew, więc wyzwalacz co minutę nic nie robi, dopóki bot żyje. Duplikaty tworzy właśnie pętla w opakowaniu: zabij opakowanie, jego proces potomny działa dalej, a nowe opakowanie uruchamia kolejny. Dokładnie to zobaczyliśmy.

Czy to działa z Pythonem lub Node.js?

Tak. Wpisz interpreter w -Execute, a skrypt w -Argument, z pełnymi ścieżkami, na przykład -Execute 'C:\Program Files\Python312\python.exe' -Argument 'C:\bots\bot.py'. Zainstaluj interpreter dla wszystkich użytkowników, żeby konto SYSTEM go znalazło.

Komentarze

Brak komentarzy. Bądź pierwszy.

Zostaw komentarz

Komentarze są moderowane przed pojawieniem się.