−25%

על Windows בתשלום שנתי, עד 31.10. לחבילות

EQVPS
התחלה

איך מריצים סקריפט 24/7 ב-Windows Server: שורד התנתקות, קריסות ואתחולים

הריצו בוט או סקריפט יומם ולילה ב-VPS עם Windows Server 2022 רק עם Task Scheduler: עולה באתחול בלי שאף אחד מחובר, חוזר תוך דקה אחרי קריסה ולעולם לא רץ בשני עותקים. הרגנו את התהליך ואתחלנו את השרת כדי לבדוק.

הדרך הרגילה להריץ בוט ב-VPS עם Windows היא להפעיל אותו בסשן RDP ולסגור את החלון. זה עובד עד שעדכון מאתחל את השרת בשלוש לפנות בוקר ואף אחד לא מפעיל אותו שוב. 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. "אם המשימה נכשלת, הפעל מחדש כל…". הפעלנו, הרגנו את התהליך, והמשימה עמדה דקות במצב Ready. ההגדרה מגיבה למשימה שלא מצליחה לעלות, לא לתוכנה שנופלת אחר כך.
  2. לולאה עוטפת (while ($true) { & bot; sleep 5 }). היא מפעילה מחדש בוט שקרס, אבל אם העוטף עצמו מת, הבן ממשיך לרוץ וההפעלה הבאה מעלה בוט שני. נשארנו עם שני עותקים, ובבוט טלגרם זה אומר שני תהליכים שרבים על אותם עדכונים.

איך בודקים

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 זיכרון במנוחה. Windows-Small (4 vCPU, 4 GB זיכרון, 50 GB, $11 לחודש) הוא הגודל המתאים לבוט אחד או שניים. בתוכנית NAT חיבורים יוצאים (טלגרם, ממשקי API של בורסות, webhooks שאתם קוראים) עובדים כרגיל. אם הבוט צריך לקבל webhooks או תעבורה נכנסת אחרת, בחרו Windows Small-IP ($28 לחודש) עם IPv4 משלה.

הצעדים הבאים: אבטחו את RDP, ואם אתם מעדיפים לנהל את הבוט דרך SSH, התקינו OpenSSH. התשלום ב-USDT, USDC או ETH, ו-Windows הוא Server 2022 עם הרישיון שלכם (BYOL). כל התוכניות: Windows VPS.

שאלות נפוצות

למה לא להשאיר את הסקריפט רץ בסשן ה-RDP שלי?

זה עובד עד שמשהו מסיים את הסשן: התנתקות מהחשבון, אתחול אחרי עדכונים או קריסה. סגירת חלון ה-RDP (ניתוק) משאירה את הסשן חי, אבל יציאה מהחשבון הורגת כל מה שרץ בו, ואחרי אתחול אף אחד לא מחובר כדי להפעיל אותו מחדש. משימה מתוזמנת לא תלויה באף סשן.

אין ל-Task Scheduler הגדרה של 'הפעל מחדש אם נכשל'?

יש, אבל בבדיקה שלנו היא לא עזרה. כשהרגנו את תהליך הסקריפט, המשימה עברה למצב 'Ready' ונשארה שם. ההגדרה מגיבה כשהמשימה לא מצליחה לעלות, לא כשהתוכנה שלכם נופלת אחר כך. מה שמחזיר אותה הוא הטריגר החוזר במדריך הזה.

יכולים לרוץ שני עותקים של הבוט שלי?

לא עם ההגדרה הזו. המשימה מריצה את הבוט עצמו (בלי סקריפט עוטף) ומשתמשת ב-MultipleInstances IgnoreNew, כך שהטריגר הדקתי לא עושה כלום כל עוד הבוט חי. מה שיוצר כפילויות הוא דווקא לולאה עוטפת: הורגים את העוטף, תהליך הבן ממשיך לרוץ, ועוטף חדש מפעיל עוד אחד. ראינו בדיוק את זה.

זה עובד עם Python או Node.js?

כן. שימו את המפרש ב--Execute ואת הסקריפט ב--Argument, עם נתיבים מלאים, למשל -Execute 'C:\Program Files\Python312\python.exe' -Argument 'C:\bots\bot.py'. התקינו את המפרש לכל המשתמשים כדי שחשבון SYSTEM ימצא אותו.

תגובות

אין עדיין תגובות. היו הראשונים.

השאירו תגובה

התגובות עוברות מודרציה לפני שהן מופיעות.