VPS 状态一键报告:用 Shell 脚本让 AI Agent 快速理解服务器全貌

起因

我的 VPS(162.43.92.249)上跑了很多东西:

  • PM2:3 个 Node.js 应用
  • Docker:8 个容器(n8n、one-api、ArcReel、Excalidraw、RustDesk 等)
  • k3s:WordPress、K8s Dashboard、Traefik
  • Nginx:多个站点的反向代理
  • Tailscale:4 台设备的私有网络

每次让新的 AI Agent 接手工作时,都要花大量时间解释「什么在跑、跑在哪、怎么访问」。于是写了一个 Shell 脚本,一条命令输出完整状态。


脚本设计思路

报告需要覆盖 15 个维度,让读者无需额外提问就能理解全貌:

#维度内容
1系统基本OS、内核、CPU、内存、磁盘
2网络接口、Tailscale 设备
3公开端口LISTEN 中的 TCP/UDP
4防火墙ufw 规则
5systemd主要服务
6PM2进程、cwd、端口
7Docker容器、卷、磁盘占用
8k3sNamespace、Deployment、Pod、Service、PVC
9Nginxsites-enabled、server_name
10域名DNS 解析结果
11磁盘占用/root 下 Top 15
12workspace.openclaw/workspace 的构成
13内存占用Top 10 进程
14大文件100MB 以上
15错误日志Nginx 最近 5 条

脚本正文

保存到 /root/vps-report.sh:

bash

#!/bin/bash
# ============================================================
#  VPS 全体状態レポート
#  実行: bash /root/vps-report.sh
#  保存: bash /root/vps-report.sh 2>&1 | tee /root/vps-report-$(date +%Y%m%d).txt
# ============================================================

REPORT_DATE=$(date '+%Y-%m-%d %H:%M:%S %Z')
HOSTNAME=$(hostname)
PUBLIC_IP=$(curl -s --max-time 5 ifconfig.me 2>/dev/null)
TAILSCALE_IP=$(tailscale ip -4 2>/dev/null | head -1)

cat << EOF
################################################################
#  VPS 全体状態レポート
#  実行日時: ${REPORT_DATE}
#  ホスト名: ${HOSTNAME}
#  公開IP:   ${PUBLIC_IP}
#  Tailscale IP: ${TAILSCALE_IP}
################################################################

EOF

echo "=========================================="
echo "1. システム基本情報"
echo "=========================================="
cat /etc/os-release | grep -E "PRETTY_NAME|VERSION="
echo "カーネル: $(uname -r)"
echo "CPU: $(nproc) cores"
echo ""
free -h
echo ""
df -h / | tail -1
echo ""

echo "=========================================="
echo "2. ネットワーク"
echo "=========================================="
ip -br addr | grep -vE "^veth|^br-|^docker|^cni|^flannel"
echo ""
echo "--- Tailscale ---"
tailscale status 2>/dev/null || echo "未接続"
echo ""

echo "=========================================="
echo "3. 公開ポート(LISTEN中)"
echo "=========================================="
echo "--- TCP ---"
ss -tlnp | grep LISTEN | awk '{print $4}' | sort -u | grep -vE "^127\.|^\[::1\]"
echo ""
echo "--- UDP ---"
ss -ulnp | grep UNCONN | awk '{print $4}' | sort -u | grep -vE "^127\.|^\[::1\]"
echo ""

echo "=========================================="
echo "4. ファイアウォール(ufw)"
echo "=========================================="
ufw status 2>/dev/null | grep -E "Status|ALLOW"
echo ""

echo "=========================================="
echo "5. systemd 主要サービス"
echo "=========================================="
systemctl list-units --type=service --state=running --no-pager 2>/dev/null | grep -E "docker|k3s|nginx|pm2|tailscale|ssh|cron|dsh|ollama" | head -15
echo ""

echo "=========================================="
echo "6. PM2 プロセス"
echo "=========================================="
pm2 list 2>/dev/null | grep -E "id|online|stopped|errored"
echo ""

echo "=========================================="
echo "7. Docker コンテナ"
echo "=========================================="
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}" 2>/dev/null
echo ""
echo "--- Docker ボリューム ---"
docker volume ls 2>/dev/null
echo ""
echo "--- Docker ディスク使用量 ---"
docker system df 2>/dev/null
echo ""

echo "=========================================="
echo "8. Kubernetes (k3s)"
echo "=========================================="
if command -v kubectl >/dev/null 2>&1; then
  echo "--- Namespaces ---"
  kubectl get namespaces 2>/dev/null
  echo ""
  echo "--- Deployments ---"
  kubectl get deployments -A 2>/dev/null
  echo ""
  echo "--- Pods (Running) ---"
  kubectl get pods -A 2>/dev/null | grep -v "Completed"
  echo ""
  echo "--- Services (NodePort/LoadBalancer) ---"
  kubectl get svc -A 2>/dev/null | grep -E "NodePort|LoadBalancer|NAMESPACE"
  echo ""
  echo "--- PVC ---"
  kubectl get pvc -A 2>/dev/null
else
  echo "kubectl 未インストール"
fi
echo ""

echo "=========================================="
echo "9. Nginx 設定"
echo "=========================================="
ls -la /etc/nginx/sites-enabled/ 2>/dev/null
echo ""
echo "--- 全 server_name ---"
nginx -T 2>/dev/null | grep -E "server_name" | grep -v "^\s*#" | sort -u
echo ""

echo "=========================================="
echo "10. ドメインとDNS"
echo "=========================================="
for domain in helloai.jp traffic.helloai.jp fbinjapan.xvps.jp; do
  ip=$(dig +short $domain A 2>/dev/null | head -1)
  echo "  $domain → ${ip:-解決失敗}"
done
echo ""

echo "=========================================="
echo "11. ディスク使用量トップ15(/root)"
echo "=========================================="
du -sh /root/* 2>/dev/null | sort -rh | head -15
echo ""

echo "=========================================="
echo "12. .openclaw/workspace の内訳"
echo "=========================================="
if [ -d /root/.openclaw/workspace ]; then
  du -sh /root/.openclaw/workspace 2>/dev/null
  echo ""
  du -sh /root/.openclaw/workspace/* 2>/dev/null | sort -rh | head -10
else
  echo "存在しません"
fi
echo ""

echo "=========================================="
echo "13. メモリ使用量トップ10"
echo "=========================================="
ps aux --sort=-%mem | head -11 | awk '{printf "%-10s %-8s %5s%% %8s  %s\n", $1, $2, $4, $6, $11}'
echo ""

echo "=========================================="
echo "14. 大きなファイル(100MB以上、/root配下)"
echo "=========================================="
find /root -type f -size +100M -exec ls -lh {} \; 2>/dev/null | awk '{print $5, $9}' | sort -rh | head -10
echo ""

echo "=========================================="
echo "15. 最近のエラーログ(Nginx)"
echo "=========================================="
tail -5 /var/log/nginx/error.log 2>/dev/null || echo "ログなし"
echo ""

echo "################################################################"
echo "#  レポート完了"
echo "################################################################"

使用方法

1. スクリプトの作成

bash

cat > /root/vps-report.sh << 'SCRIPT_EOF'
(上記のスクリプトを貼り付け)
SCRIPT_EOF

chmod +x /root/vps-report.sh

2. 実行

bash

# 画面に表示
bash /root/vps-report.sh

# ファイルに保存(推奨)
bash /root/vps-report.sh 2>&1 | tee /root/vps-report-$(date +%Y%m%d).txt

3. 定期的に実行(オプション)

bash

# cron に追加(毎日9時)
crontab -e
# 以下を追加
0 9 * * * bash /root/vps-report.sh > /root/vps-report-$(date +\%Y\%m\%d).txt 2>&1

输出示例

以下是实际运行结果的摘要:

text

################################################################
#  VPS 全体状態レポート
#  実行日時: 2026-09-26 19:56:31 JST
#  ホスト名: x162-43-92-249
#  公開IP:   162.43.92.249
#  Tailscale IP: 100.99.4.120
################################################################

==========================================
1. システム基本情報
==========================================
PRETTY_NAME="Ubuntu 22.04.5 LTS"
カーネル: 5.15.0-181-generic
CPU: 4 cores

               total        used        free
Mem:           5.8Gi       3.5Gi       175Mi
Swap:          2.0Gi       1.9Gi       118Mi

/dev/vda1       146G  103G   43G  71% /

==========================================
3. 公開ポート(LISTEN中)
==========================================
--- TCP ---
*:3002        ← my-dashboard
*:6443        ← k3s API
*:8002        ← photo-gem-map
0.0.0.0:22    ← SSH
0.0.0.0:80    ← Nginx
0.0.0.0:3000  ← one-api
0.0.0.0:5678  ← n8n
0.0.0.0:8000  ← photo-gem-map (Nginx)
0.0.0.0:8001  ← tokyo-traffic
0.0.0.0:8080  ← OpenClaw
0.0.0.0:8088  ← Dify
100.99.4.120:8081  ← WordPress (Tailscale)
...

==========================================
8. Kubernetes (k3s)
==========================================
--- Deployments ---
default                wordpress                   1/1
default                wordpress-mysql             1/1
kube-system            traefik                     1/1
kubernetes-dashboard   kubernetes-dashboard        1/1
wordpress-prod         wordpress                   1/1

--- Services (NodePort/LoadBalancer) ---
kube-system   traefik       LoadBalancer  162.43.92.249  80:31340/TCP,443:31026/TCP
default       wordpress     NodePort      80:30080/TCP
wordpress-prod wordpress    NodePort      80:30081/TCP
kubernetes-dashboard  kubernetes-dashboard  NodePort  443:30082/TCP

==========================================
10. ドメインとDNS
==========================================
  helloai.jp → 85.131.207.20         ← 別サーバー
  traffic.helloai.jp → 85.131.207.20 ← 別サーバー
  fbinjapan.xvps.jp → 162.43.92.249  ← このVPS

==========================================
11. ディスク使用量トップ15(/root)
==========================================
905M	/root/my-dashboard
414M	/root/one-api
174M	/root/hermes-agent
137M	/root/ArcReel
...

==========================================
14. 大きなファイル(100MB以上)
==========================================
5.6G /root/.ollama/models/blobs/sha256-a99b...
4.8G /root/.openclaw/workspace-backup-20260403-101753.tar.gz
4.4G /root/.ollama/models/blobs/sha256-6a07...
4.4G /root/.ollama/models/blobs/sha256-60e0...
...

脚本能发现的问题

运行报告后,一眼就能看出:

  1. 磁盘占用分布:哪些目录最占空间
  2. Docker 卷的浪费:RECLAIMABLE 提示可回收大小
  3. k3s 里停摆的 Deployment:0/0 就是没在跑
  4. 域名与服务器不符:helloai.jp 指向 85.131.207.20,不是这台 VPS
  5. 内存瓶颈:Swap 用到 1.9/2.0GB,说明内存紧张
  6. 大文件残留:Ollama 模型、旧备份、Hugging Face 缓存

成本

项目成本
脚本开发0 元(一次编写)
执行时间约 10〜20 秒
输出大小约 5〜10 KB
运行成本0 元

当前状态

项目状态
脚本位置✅ /root/vps-report.sh
最新报告✅ /root/vps-report-20260926.txt
磁盘使用✅ 71%(空き43GB)
执行时间✅ 约15秒
15个维度✅ 全部输出

可优化的方向

  1. JSON 输出:增加 --json 选项,便于程序解析
  2. 差分报告:与上次报告对比,高亮变化
  3. 告警阈值:磁盘 > 90%、内存 > 90% 时标红
  4. 定时执行:cron 每天自动生成
  5. 推送到 Slack/邮件:异常时自动通知

一句话总结

一条命令,15 个维度,让任何 AI Agent 或协作者在 15 秒内理解整台 VPS 的全貌。 从端口、容器、K8s 到域名解析和磁盘占用,交接和排查都变得有据可查。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注