−25%

روی پرداخت سالانه Windows، تا ۳۱ اکتبر. مشاهده پلن‌ها

EQVPS
شروع کنید

چگونه یک اسکریپت را 24/7 روی Windows Server اجرا کنیم: پایدار در برابر خروج، کرش و راه‌اندازی دوباره

یک بات یا اسکریپت را شبانه‌روز روی VPS با Windows Server 2022 فقط با Task Scheduler اجرا کنید: هنگام بوت بدون ورود کسی شروع می‌شود، پس از کرش ظرف یک دقیقه برمی‌گردد و هرگز دو نسخه هم‌زمان اجرا نمی‌شود. برای بررسی، فرایند را کشتیم و سرور را دوباره راه‌اندازی کردیم.

روش معمول اجرای بات روی VPS ویندوزی این است که آن را در یک نشست RDP اجرا کنید و پنجره را ببندید. این کار تا وقتی جواب می‌دهد که یک به‌روزرسانی ساعت 3 بامداد سرور را دوباره راه بیندازد و کسی بات را دوباره اجرا نکند. 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 هنگام بوت ویندوز، بدون کاربر واردشده، بات را شروع می‌کند.
  • تکرار هر دقیقه کار را هر دقیقه دوباره اجرا می‌کند. اگر بات زنده باشد، اتفاقی نمی‌افتد؛ اگر مرده باشد، دوباره شروع می‌شود.
  • -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 پردازنده کمی مصرف می‌کند، اما خود ویندوز روی ایمیج ما در حالت بیکار 1 تا 1.3 GB حافظه می‌گیرد. Windows-Small (4 vCPU، 4 GB حافظه، 50 GB، ماهانه $11) اندازهٔ مناسبی برای یکی دو بات است. در پلن NAT اتصال‌های خروجی (تلگرام، API صرافی‌ها، وب‌هوک‌هایی که فرامی‌خوانید) عادی کار می‌کنند. اگر بات باید وب‌هوک یا ترافیک ورودی دیگری دریافت کند، Windows Small-IP (ماهانه $28) با IPv4 اختصاصی را بگیرید.

گام‌های بعدی: RDP را ایمن کنید و اگر ترجیح می‌دهید بات را از راه SSH مدیریت کنید، OpenSSH را نصب کنید. پرداخت با USDT، USDC یا ETH است و ویندوز همان 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 پیدایش کند.

نظرات

هنوز نظری نیست. اولین نفر باشید.

یک نظر بگذارید

نظرات پیش از نمایش بررسی می‌شوند.