−25%

su Windows con pagamento annuale, fino al 31/10. Vai ai piani

EQVPS
Inizia

Come eseguire uno script 24/7 su Windows Server: sopravvive a disconnessioni, crash e riavvii

Tieni un bot o uno script attivo giorno e notte su un VPS Windows Server 2022 con la sola Utilità di pianificazione: parte all'avvio senza nessuno connesso, riparte entro un minuto dopo un crash e non gira mai in due copie. Abbiamo ucciso il processo e riavviato per verificarlo.

Il modo abituale di far girare un bot su un VPS Windows è avviarlo in una sessione RDP e chiudere la finestra. Funziona finché un aggiornamento non riavvia il server alle 3 di notte e nessuno lo rilancia. L'Utilità di pianificazione, presente su ogni Windows Server, risolve senza software aggiuntivo. La configurazione qui sotto:

  • avvia lo script al boot, prima che qualcuno acceda;
  • lo riavvia entro un minuto se va in crash o viene ucciso;
  • non avvia mai due copie contemporaneamente.

Abbiamo provato tutte e tre le cose sulla nostra immagine Windows Server 2022: processo ucciso, server riavviato, istanze contate.

Lo script di esempio

Un sostituto del tuo bot: scrive una riga ogni 10 secondi, così è facile vedere se è vivo.

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

Registra l'attività

Esegui in un PowerShell con privilegi di amministratore:

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

Cosa fa ogni parte:

  • -AtStartup avvia il bot all'accensione di Windows, senza utenti connessi.
  • La ripetizione ogni minuto riesegue l'attività ogni minuto. Se il bot è vivo non succede nulla; se è morto, riparte.
  • -MultipleInstances IgnoreNew rende sicura la ripetizione: un'esecuzione che trova il bot già attivo viene saltata.
  • -ExecutionTimeLimit 0 disattiva il limite predefinito di 72 ore, dopo il quale l'Utilità di pianificazione fermerebbe il bot.
  • -User 'SYSTEM' lo esegue senza password né sessione. SYSTEM ha pieni diritti sul server, quindi esegui così solo il tuo codice.

Per Python, sostituisci l'azione:

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

Cosa abbiamo verificato

Crash. Abbiamo ucciso il processo del bot con Stop-Process -Force. 46 secondi dopo il trigger di ogni minuto ne aveva avviato uno nuovo, e c'era esattamente una copia.

Riavvio. Abbiamo riavviato il server senza accedere. 40 secondi dopo l'avvio il bot scriveva già nel suo log, senza sessioni utente sul server.

Cosa non ha funzionato. Due cose sembrano giuste e non lo sono:

  1. «Se l'attività non riesce, riavvia ogni…» L'abbiamo impostata, ucciso il processo, e l'attività è rimasta per minuti in stato Pronta. Reagisce a un'attività che non riesce ad avviarsi, non al programma che muore dopo.
  2. Un ciclo wrapper (while ($true) { & bot; sleep 5 }). Riavvia un bot caduto, ma se muore il wrapper stesso il figlio continua a girare e l'avvio successivo lancia un secondo bot. Ci siamo ritrovati con due copie, che per un bot Telegram significa due processi che si contendono gli stessi aggiornamenti.

Come controllarlo

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

Per fermarlo durante una manutenzione, prima Disable-ScheduledTask mybot (altrimenti il trigger di ogni minuto lo riavvia), poi ferma il processo. Enable-ScheduledTask mybot lo rimette in funzione.

Log

L'attività non cattura l'output. Fai scrivere al bot un proprio log, come nell'esempio, oppure reindirizza l'output in un piccolo avviatore .cmd e punta -Execute a quel file.

Quale piano

Un bot in PowerShell o Python usa poca CPU, ma Windows da solo occupa da 1 a 1,3 GB di RAM a riposo sulla nostra immagine. Windows-Small (4 vCPU, 4 GB di RAM, 50 GB, $11/mese) è la misura giusta per uno o due bot. Su un piano NAT le connessioni in uscita (Telegram, API degli exchange, webhook che chiami) funzionano normalmente. Se il bot deve ricevere webhook o altro traffico in ingresso, scegli Windows Small-IP ($28/mese) con IPv4 propria.

Passi successivi: proteggi RDP e, se preferisci gestire il bot via SSH, installa OpenSSH. Il pagamento è in USDT, USDC o ETH, e Windows è Server 2022 con la tua licenza (BYOL). Tutti i piani: Windows VPS.

FAQ

Perché non lasciare lo script nella mia sessione RDP?

Funziona finché qualcosa non chiude la sessione: una disconnessione dell'utente, un riavvio per aggiornamenti o un crash. Chiudere la finestra RDP (disconnettersi) mantiene viva la sessione, ma uscire dalla sessione uccide tutto ciò che contiene, e dopo un riavvio nessuno è connesso per rilanciarlo. Un'attività pianificata non dipende da alcuna sessione.

L'Utilità di pianificazione non ha l'opzione «riavvia in caso di errore»?

Sì, ma nel nostro test non è servita. Quando abbiamo ucciso il processo dello script, l'attività è passata a «Pronta» ed è rimasta lì. L'opzione reagisce quando l'attività non riesce ad avviarsi, non quando il programma muore dopo. A riportarla in vita è il trigger ripetuto di questa guida.

Possono girare due copie del mio bot?

Non con questa configurazione. L'attività esegue il bot stesso (senza script wrapper) e usa MultipleInstances IgnoreNew, quindi il trigger di ogni minuto non fa nulla finché il bot è vivo. A creare doppioni è proprio un ciclo wrapper: uccidi il wrapper, il suo processo figlio continua a girare e un nuovo wrapper ne avvia un altro. Abbiamo visto esattamente questo.

Funziona con Python o Node.js?

Sì. Metti l'interprete in -Execute e lo script in -Argument, con percorsi completi, per esempio -Execute 'C:\Program Files\Python312\python.exe' -Argument 'C:\bots\bot.py'. Installa l'interprete per tutti gli utenti, così l'account SYSTEM lo trova.

Commenti

Ancora nessun commento. Sii il primo.

Lascia un commento

I commenti sono moderati prima di comparire.