−25%

Windows 年払い、10月31日まで。 プランを見る

EQVPS
始める

Windows Server でスクリプトを 24 時間動かす方法:サインアウト、クラッシュ、再起動にも耐える

Windows Server 2022 VPS で、ボットやスクリプトをタスク スケジューラだけで昼夜動かし続ける方法:誰もログインしていなくても起動時に開始し、クラッシュ後 1 分以内に復帰し、決して 2 つ同時に動かない。プロセスを強制終了し、再起動して確かめました。

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 つあります。

  1. 「タスクが失敗した場合の再起動の間隔」。 設定してプロセスを終了したところ、タスクは数分間 準備完了 のままでした。タスクが起動できない場合に反応する設定で、プログラムが後で落ちた場合ではありません。
  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。

よくある質問

RDP セッションでスクリプトを動かしたままではだめですか?

何かがセッションを終わらせるまでは動きます。サインアウト、更新後の再起動、クラッシュなどです。RDP ウィンドウを閉じる(切断する)だけならセッションは残りますが、サインアウトすると中のものはすべて終了し、再起動後は誰もログインしていないので再開されません。スケジュールされたタスクはどのセッションにも依存しません。

タスク スケジューラには「失敗した場合に再起動」の設定がありませんか?

ありますが、私たちのテストでは役に立ちませんでした。スクリプトのプロセスを終了すると、タスクは「準備完了」になってそのままでした。この設定はタスクが起動できなかったときに反応するもので、プログラムが後で落ちたときには反応しません。復帰させるのは、このガイドの繰り返しトリガーです。

ボットが 2 つ同時に動くことはありますか?

この構成ではありません。タスクはボット本体を直接起動し(ラッパースクリプトなし)、MultipleInstances IgnoreNew を使うので、ボットが動いている間は 1 分ごとのトリガーは何もしません。重複を生むのはむしろラッパーのループです。ラッパーを終了しても子プロセスは動き続け、新しいラッパーがもう 1 つ起動します。実際にそうなりました。

Python や Node.js でも使えますか?

使えます。-Execute にインタープリター、-Argument にスクリプトを、それぞれフルパスで指定します。例:-Execute 'C:\Program Files\Python312\python.exe' -Argument 'C:\bots\bot.py'。SYSTEM アカウントが見つけられるよう、インタープリターはすべてのユーザー向けにインストールしてください。

コメント

まだコメントはありません。最初になりましょう。

コメントを残す

コメントは表示される前にモデレートされます。