Windows VPS でボットを動かす一般的な方法は、RDP セッションで起動してウィンドウを閉じることです。これは、更新が午前 3 時にサーバーを再起動し、誰もボットを起動し直さない日まで動きます。どの Windows Server にもあるタスク スケジューラを使えば、追加ソフトなしで解決できます。以下の構成は:
- 誰かがログインする前に、起動時にスクリプトを開始し、
- クラッシュや強制終了があっても 1 分以内に再起動し、
- 2 つ同時には決して動かしません。
3 点とも当社の Windows Server 2022 イメージで試しました。プロセスを終了し、サーバーを再起動し、インスタンス数を数えました。
サンプルスクリプト
ボットの代わりです。10 秒ごとに 1 行書くので、生きているかすぐ分かります。
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 起動時にボットを開始します。- 1 分ごとの繰り返しは、毎分タスクを実行し直します。ボットが生きていれば何も起きず、落ちていれば再び起動します。
-MultipleInstances IgnoreNewが繰り返しを安全にします。ボットがすでに動いているときの実行はスキップされます。-ExecutionTimeLimit 0は既定の 72 時間の制限を外します。この制限があると、タスク スケジューラがボットを止めてしまいます。-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 秒後には 1 分ごとのトリガーが新しいプロセスを起動しており、動いていたのはちょうど 1 つでした。
再起動。 サーバーを再起動し、ログインしませんでした。起動から 40 秒後にはボットがログに書き込んでおり、サーバーにユーザーセッションはありませんでした。
うまくいかなかったこと。 正しそうに見えて、実は違うものが 2 つあります。
- 「タスクが失敗した場合の再起動の間隔」。 設定してプロセスを終了したところ、タスクは数分間 準備完了 のままでした。タスクが起動できない場合に反応する設定で、プログラムが後で落ちた場合ではありません。
- ラッパーのループ(
while ($true) { & bot; sleep 5 })。落ちたボットは再起動しますが、ラッパー自体が終了すると子プロセスは動き続け、次の起動で 2 つ目のボットが立ち上がります。私たちの環境でも 2 つになりました。Telegram ボットなら、同じ更新を 2 つのプロセスで奪い合うことになります。
状態の確認
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 を実行し(そうしないと 1 分ごとのトリガーがまた起動します)、それからプロセスを止めます。Enable-ScheduledTask mybot で元に戻ります。
ログ
タスクは出力を記録しません。例のようにボット自身にログを書かせるか、小さな .cmd ランチャーで出力をリダイレクトし、-Execute でそのファイルを指定してください。
どのプランを選ぶか
PowerShell や Python のボットは CPU をほとんど使いませんが、当社のイメージでは Windows 自体がアイドル時に 1〜1.3 GB の RAM を使います。Windows-Small(4 vCPU、RAM 4 GB、50 GB、月 $11)はボット 1〜2 個にちょうどよいサイズです。NAT プランでも、外向きの接続(Telegram、取引所の API、呼び出す Webhook)は普通に使えます。ボットが Webhook などの受信トラフィックを受け取る必要があるなら、専用 IPv4 付きの Windows Small-IP(月 $28)を選んでください。
次のステップ:RDP を守る。SSH でボットを管理したいなら OpenSSH を入れる。支払いは USDT、USDC、ETH で、Windows はあなた自身のライセンスで使う Server 2022 です(BYOL)。全プラン:Windows VPS。
コメント
まだコメントはありません。最初になりましょう。