−25%

auf Windows bei Jahreszahlung, bis 31.10. Zu den Tarifen

EQVPS
Loslegen

Ein Skript 24/7 auf Windows Server ausführen: übersteht Abmelden, Abstürze und Neustarts

Einen Bot oder ein Skript rund um die Uhr auf einem Windows-Server-2022-VPS nur mit der Aufgabenplanung betreiben: Start beim Booten ohne angemeldeten Benutzer, Neustart binnen einer Minute nach einem Absturz und nie zwei Kopien. Wir haben den Prozess beendet und neu gestartet, um es zu prüfen.

Üblicherweise startet man einen Bot auf einem Windows-VPS in einer RDP-Sitzung und schließt das Fenster. Das klappt, bis ein Update den Server um 3 Uhr nachts neu startet und ihn niemand wieder startet. Die Aufgabenplanung, die auf jedem Windows Server vorhanden ist, löst das ohne Zusatzsoftware. Der Aufbau unten:

  • startet das Skript beim Booten, bevor sich jemand anmeldet;
  • startet es binnen einer Minute neu, wenn es abstürzt oder beendet wird;
  • startet nie zwei Kopien gleichzeitig.

Alle drei Punkte haben wir auf unserem Windows-Server-2022-Image getestet: Prozess beendet, Server neu gestartet, Instanzen gezählt.

Das Beispielskript

Ein Platzhalter für Ihren Bot: Er schreibt alle 10 Sekunden eine Zeile, so sehen Sie leicht, ob er lebt.

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

Die Aufgabe registrieren

In einer PowerShell mit Administratorrechten ausführen:

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

Was die einzelnen Teile tun:

  • -AtStartup startet den Bot beim Hochfahren von Windows, ohne angemeldeten Benutzer.
  • Die minütliche Wiederholung führt die Aufgabe jede Minute erneut aus. Lebt der Bot, passiert nichts; ist er gestorben, startet er neu.
  • -MultipleInstances IgnoreNew macht die Wiederholung sicher: Ein Lauf, der den Bot schon laufend vorfindet, wird übersprungen.
  • -ExecutionTimeLimit 0 schaltet das Standardlimit von 72 Stunden ab, nach dem die Aufgabenplanung den Bot stoppen würde.
  • -User 'SYSTEM' führt ihn ohne Passwort und ohne Sitzung aus. SYSTEM hat volle Rechte auf dem Server, starten Sie so also nur Ihren eigenen Code.

Für Python ersetzen Sie die Aktion:

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

Was wir geprüft haben

Absturz. Wir haben den Prozess des Bots mit Stop-Process -Force beendet. 46 Sekunden später hatte der minütliche Trigger einen neuen gestartet, und es gab genau eine Kopie.

Neustart. Wir haben den Server neu gestartet und uns nicht angemeldet. 40 Sekunden nach dem Booten schrieb der Bot in sein Log, ohne Benutzersitzungen auf dem Server.

Was nicht funktionierte. Zwei Dinge sehen richtig aus und sind es nicht:

  1. „Falls Aufgabe fehlschlägt, neu starten alle…“ Wir haben es eingestellt, den Prozess beendet, und die Aufgabe stand minutenlang auf Bereit. Die Einstellung reagiert darauf, dass die Aufgabe nicht starten kann, nicht darauf, dass Ihr Programm später stirbt.
  2. Eine Wrapper-Schleife (while ($true) { & bot; sleep 5 }). Sie startet einen abgestürzten Bot neu, aber stirbt der Wrapper selbst, läuft sein Kindprozess weiter, und der nächste Start bringt einen zweiten Bot. Bei uns liefen zwei Kopien, was für einen Telegram-Bot zwei Poller bedeutet, die um dieselben Updates streiten.

Den Zustand prüfen

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

Um ihn für Wartung zu stoppen, zuerst Disable-ScheduledTask mybot (sonst startet ihn der minütliche Trigger wieder), dann den Prozess beenden. Enable-ScheduledTask mybot bringt ihn zurück.

Logs

Die Aufgabe fängt keine Ausgabe auf. Lassen Sie den Bot sein eigenes Log schreiben, wie im Beispiel, oder leiten Sie die Ausgabe in einem kleinen .cmd-Starter um und zeigen Sie mit -Execute auf diese Datei.

Welcher Tarif

Ein PowerShell- oder Python-Bot braucht wenig CPU, aber Windows selbst belegt auf unserem Image im Leerlauf 1 bis 1,3 GB RAM. Windows-Small (4 vCPU, 4 GB RAM, 50 GB, $11/Monat) ist die richtige Größe für ein oder zwei Bots. Auf einem NAT-Tarif funktionieren ausgehende Verbindungen (Telegram, Börsen-APIs, Webhooks, die Sie aufrufen) wie gewohnt. Muss der Bot Webhooks oder anderen eingehenden Verkehr empfangen, nehmen Sie Windows Small-IP ($28/Monat) mit eigener IPv4.

Als Nächstes: RDP absichern und, wenn Sie den Bot lieber per SSH verwalten, OpenSSH installieren. Bezahlt wird in USDT, USDC oder ETH, und Windows ist Server 2022 mit Ihrer eigenen Lizenz (BYOL). Alle Tarife: Windows VPS.

FAQ

Warum das Skript nicht einfach in der RDP-Sitzung laufen lassen?

Das geht, bis etwas die Sitzung beendet: Abmelden, ein Neustart nach Updates oder ein Absturz. Wer das RDP-Fenster schließt (trennt), lässt die Sitzung leben, aber Abmelden beendet alles darin, und nach einem Neustart ist niemand angemeldet, der es wieder startet. Eine geplante Aufgabe hängt von keiner Sitzung ab.

Hat die Aufgabenplanung nicht eine Einstellung ‚bei Fehler neu starten‘?

Ja, aber in unserem Test half sie nicht. Als wir den Prozess des Skripts beendeten, ging die Aufgabe einfach auf ‚Bereit‘ und blieb dort. Die Einstellung reagiert darauf, dass die Aufgabe nicht starten kann, nicht darauf, dass Ihr Programm später stirbt. Zurück bringt es der sich wiederholende Trigger aus dieser Anleitung.

Können zwei Kopien meines Bots laufen?

Nicht mit diesem Aufbau. Die Aufgabe startet den Bot selbst (kein Wrapper-Skript) und nutzt MultipleInstances IgnoreNew, daher tut der minütliche Trigger nichts, solange der Bot lebt. Doppelte erzeugt gerade eine Wrapper-Schleife: Beenden Sie den Wrapper, läuft sein Kindprozess weiter, und ein neuer Wrapper startet einen zweiten. Genau das haben wir gesehen.

Funktioniert das mit Python oder Node.js?

Ja. Setzen Sie den Interpreter in -Execute und das Skript in -Argument, mit vollständigen Pfaden, zum Beispiel -Execute 'C:\Program Files\Python312\python.exe' -Argument 'C:\bots\bot.py'. Installieren Sie den Interpreter für alle Benutzer, damit das SYSTEM-Konto ihn findet.

Kommentare

Noch keine Kommentare. Sei der Erste.

Kommentar hinterlassen

Kommentare werden vor der Anzeige moderiert.