※AI関連作業・調査のメモ ディレクトリやファイル名はダミー
ChatGPT Plus 設定サーバ 作業・調査メモ
リモートサーバの稼働情報を毎朝レポートする仕組みを作る
リモートサーバの状態を毎朝確認して、Discordへ短く投稿する仕組みを作りました。最初はOpenClawの定期実行から直接サーバ情報を取りに行く構成で試しましたが、実行環境ごとのツール制限や投稿先指定の扱いでいくつか詰まったため、最終的には「対象サーバ側でレポートを生成し、OpenClaw側のOS cronで取得・投稿する」形に落ち着きました。
やりたかったこと
毎朝、リモートサーバについて次の情報をDiscordへ投稿することが目的でした。
- ディスク容量
- 現在の負荷
- 前日のSSH失敗数
- OSアップデートの有無
- 気になるサーバ内の挙動
投稿先は通常のチャンネルではなく、特定のスレッドまたはチャンネルID宛てにする必要がありました。
最初に試した構成
最初はOpenClawのスケジュール機能から、定期実行のたびにサーバ情報を取得して投稿する形を試しました。
OpenClaw cron
- df
- uptime
- journalctl
- dnf check-update
- Discordへ投稿
この方式は一見シンプルですが、実際には定期実行側のagentにシェルやファイル読み取りツールが出ない場合がありました。結果として、SSHコマンドやローカルファイル読み取りができず、「ツールが利用できない」という失敗メッセージだけが投稿されることがありました。
途中で起きた問題
今回の作業では、主に次の問題がありました。
- 定期実行agentでSSHコマンドが使えない
- 定期実行agentでローカルファイル読み取りも使えない
- Discordのreply-to指定が期待どおり反映されない
- OpenClaw CLIの一部操作でスコープ承認待ちが発生する
- 投稿先IDが「返信先メッセージID」なのか「チャンネル/スレッドID」なのかで指定方法が変わる
特に投稿先については、--reply-to <MESSAGE_ID> では期待した場所へ投稿されず、最終的には送信先そのものを channel:<TARGET_ID> にする必要がありました。
最終的な構成
最終的には、処理を3段階に分けました。
- 対象サーバ側で毎朝レポートを生成する
- OpenClaw側のOS cronでそのレポートを取得する
- OpenClaw側のOS cronでDiscordへ投稿する
構成イメージは次のようになります。
対象サーバ
systemd timer 09:00
- /path/to/generate-health-report.sh
- /path/to/cache/health-report.txt を生成
OpenClaw側
OS cron 09:03
- ssh <REMOTE_HOST> 'cat /path/to/cache/health-report.txt'
- /path/to/local/cache/keybind-health-report.txt に保存
OS cron 09:06
- /path/to/local/cache/keybind-health-report.txt を読む
- Discordの channel:<TARGET_ID> へ投稿
対象サーバ側で生成する内容
対象サーバ側では、毎朝systemd timerでテキストレポートを生成します。投稿用の本文を先に作っておくことで、OpenClaw側のagentにサーバ状態を調べさせる必要がなくなります。
レポート例は次のような形式です。
リモートサーバ 朝レポート YYYY-MM-DD
- 対象: <REMOTE_HOST>
- 生成時刻: YYYY-MM-DD HH:MM:SS JST
- ディスク容量:
- /: 31G/40G 使用 (77%), 空き 9.6G
- 現在の負荷: load average: 0.07, 0.08, 0.08 / CPU 2
- 昨日のssh失敗数: 132
- OSアップデート: なし
- 気になる挙動:
特に目立つ異常なし
ディスク容量は必要なマウントだけに絞りました。今回の用途では / のみで十分だったため、余計なマウントポイントは出さないようにしました。
OpenClaw側で取得する理由
OpenClawの定期実行agentにSSHをさせる構成だと、agentの実行環境によってはシェルツールが使えないことがあります。そこで、OpenClaw側のOS cronで取得する形にしました。
OS cronなら通常のシェルとして動くため、SSHやファイル保存を安定して実行できます。また、取得と投稿を分けることで、どこで失敗したのかも見やすくなります。
- 取得失敗ならfetchログを見る
- 投稿失敗ならpostログを見る
- 対象サーバ側の生成失敗なら対象サーバのsystemd journalを見る
投稿先の指定で気をつけたこと
Discordへの投稿先指定では、返信先メッセージIDとチャンネルID/スレッドIDを混同しないことが重要でした。
今回の最終形では、返信指定ではなく送信先そのものを指定しています。
openclaw message send \
--channel discord \
--target channel:<TARGET_ID> \
--message "$report"
--reply-to を使う形も試しましたが、dry-runで確認したpayloadには反映されていませんでした。そのため、スレッドまたはチャンネルへ確実に出したい場合は、--target channel:<TARGET_ID> にする方が確実でした。
セキュリティ面で見直したこと
作業中にOpenClaw CLIのスコープ承認待ちが発生しましたが、管理者スコープは承認しませんでした。不要な権限拡張は避けています。
今後の情報取得拡張も見据え、リモートサーバで生成したレポートファイルは、OpenClaw側からSSHするユーザーだけが読めるようにし、それ以外のローカルユーザーからは読めないようにしています。
/path/to/cache
owner: root
group: <READONLY_GROUP>
mode: 0750
/path/to/cache/health-report.txt
owner: root
group: <READONLY_GROUP>
mode: 0640
今回の落としどころ
最終的な構成は、OpenClawのagentに何でもやらせるのではなく、OS cronと対象サーバ側のtimerに処理を分担させる形です。
- 対象サーバは自分の情報を自分で生成する
- OpenClaw側は生成済みレポートを取得する
- 投稿はOS cronから直接行う
- OpenClaw cron agentには依存しない
この構成にしたことで、agentのツール制限に左右されず、投稿先も安定して指定できるようになりました。
まとめ
リモートサーバの稼働情報を毎朝投稿する仕組みは、対象サーバ側でレポートを生成し、OpenClaw側のOS cronで取得・投稿する形が扱いやすいと感じました。
一度に全部をOpenClaw cron agentへ任せるより、対象サーバ、OpenClawホスト、Discord投稿の責務を分けた方が、失敗時の切り分けもしやすく、権限も絞りやすくなります。
