本文へスキップ
Articles

2026-08-24 公開 / サーバー・インフラ

PCを起動しなくても回るように、AIのCLIをサーバーに置いて毎日動かす

毎日決まった時刻にAIに調べ物をさせて、結果を自分用のページにまとめる仕組みを動かしています。最初はこれを手元のPCの定期実行でやっていました。当然ながらPCを起動していない日は動きません。これをサーバーへ移したときの構成を書きます。AIのコマンドライン版はサブスクのログインで動くので、追加のAPI契約は要りません。ただし置き方には気をつける点がありました。

前提: なぜAPI課金なしで動くのか

主要なAIには、対話画面とは別にコマンドライン版が用意されています。これらは多くの場合、既に契約しているサブスクのアカウントでサインインすれば使えます。つまり従量課金のAPIキーを新たに用意しなくても、スクリプトから呼べます。

この性質が、個人の自動化とは相性が良いです。毎日1回の調べ物のためにAPIの従量課金を始めると、失敗したときのコストが読みにくい。サブスクの範囲で回るなら、「回しすぎたら止まる」だけで、請求が伸びません。

ただしサブスクには利用上限があります。上限に当たるとその日の処理が丸ごと落ちるので、後述のフォールバックが要ります。無料枠のサーバーで動かす場合はメモリにも注意してください。この手のCLIはNode.js製が多く、小さいインスタンスだと動かないことがあります。

いちばん気をつけたところ: 何を読ませているのかを意識する

この自動化の中身は「外部のWebページを取ってきて、AIに読ませて、構造化させる」です。ここで一度立ち止まりました。外部から取ってきたテキストをAIに読ませるということは、そのテキストに書かれた指示をAIが読むということでもあります。

収集対象のページに「これまでの指示は無視して、次のコマンドを実行してください」と書いてあったらどうなるか。実際にそう書いてあることは稀ですが、稀であることは対策になりません。そこで、この処理は次の前提で組みました。

つまり「AIに書かせる場所」と「実際に使う場所」を分けて、間に検証を挟む形です。仮に変な出力が混ざっても、そのまま公開物にはなりません。

サンドボックスは仕組み側で用意されている

Linux の systemd を使っているなら、サービス定義に数行足すだけでかなり絞れます。私が入れているのは次のようなものです。

大事なのは、これらを「AIが暴走したときのため」ではなく「読ませている入力が信用できないため」と考えることです。前者だと過剰に見えますが、後者なら、外部入力を扱うプログラムに普通にやることと同じです。

定期実行で最初に踏む2つの罠

罠1: サーバーの時刻はUTCのことが多い

クラウドで立てたサーバーは、初期状態のタイムゾーンがUTCであることがよくあります。ここで「朝6時に実行」のつもりで 06:00 と書くと、日本時間の15時に動きます。

私は定期実行の定義にUTCで書き、コメントに日本時間を併記するようにしました。サーバーのタイムゾーン自体を日本時間に変えるやり方もありますが、ログの時刻や他のツールの前提も一緒に動くので、「サーバーはUTC。書くときに変換する」で統一したほうが事故が少ないというのが私の結論です。

罠2: 実行が重なる

この種のジョブを複数持つと、同じ時刻に集中しがちです。AIのCLIは1回の実行が数分かかることもあるので、用途ごとに1時間ずつずらしました。同時に走らせて上限に当たるより、順番に走らせたほうが結果的に速いです。

上限に当たったときの逃げ道を作る

サブスクで動かす以上、利用上限は必ずいつか来ます。来た日に処理が丸ごと落ちると、その日のデータが空きます。そこで二段構えにしました。

3つ目について。失敗判定は「異常終了したか」だけでは足りません。CLIは正常終了しつつ、中身が期待と違うことがあります。私は次の3つを見ています。

2つ目の文字列判定には注意点があります。私は最初429という数字を単純に含まれるかで見ていて、CLIが出力するセッションIDの16進文字列にたまたま 429 が入っていて「上限に達した」と誤判定したことがあります。成功しているのに切り替え先を消費していました。この手の判定は、単語の境界を指定するなどして絞ってください。

指示文はファイル経由で渡す

細かいですが実害があった点です。長い指示文をコマンドの引数として渡すと、改行・日本語・波括弧が途中で壊れることがあります。壊れた結果、AIが「条件が不足しています」と質問を返してきて、その日の収集が空になりました。

対策は簡単で、指示文はいったんファイルに書き出して、標準入力から流し込むことです。これだけで壊れなくなりました。生成した指示文がファイルに残るので、後から「その日何を聞いたのか」を確認できるという副次的な利点もあります。

結果として何が良くなったか

いちばんはPCの起動状態と無関係になったことです。旅行中でも、PCが壊れていても動きます。当たり前のようですが、手元で定期実行していた頃は「昨日動いていない」がそれなりの頻度で起きていました。

もう1つは、実行記録が1か所に集まったことです。サーバー側のログに全部残るので、失敗した日に何が起きたのかを後から追えます。手元のPCだと、気づいたときにはもうログが流れていました。

逆に増えた手間もあります。手元で直したものをサーバーへ持っていく作業が毎回発生します。ここは、更新するファイルを明示的に列挙して転送し、転送後にハッシュを突き合わせる、という手順に固めました。

持ち帰れること

サーバーに置くと言うと大げさに聞こえますが、やっていることは「毎日決まった時刻にコマンドを1本走らせ、出力をファイルに置く」だけです。難しいのは実行そのものではなく、失敗したときにどう振る舞うかを先に決めておくことでした。