Hetzner 流量监控自动重建

部署在 VPS 上,并且采用最稳妥的 Docker 方式,以下是为你准备的一份可以直接复制粘贴的“保姆级”实操指南。

请按顺序一步步操作。


🟢 第一步:准备必要信息

在开始敲代码前,请先把下面这 5 个关键信息找出来,记在记事本上,一会儿填到脚本里:

  1. Hetzner API Token: (必须是 Read & Write 读写权限)

  2. Telegram Bot Token: (从 @BotFather 获取)

  3. Telegram Chat ID: (从 @userinfobot 获取)

  4. 服务器名称 (Server Name): (Hetzner 后台显示的那个名字,例如 My-VPS)

  5. 快照 ID (Snapshot ID): (Hetzner 后台 Snapshots 列表里的数字 ID)


🔵 第二步:环境配置 (在 OVH 服务器上)

使用 SSH 登录你的 OVH 服务器,执行以下命令:

1. 检查并安装 Docker (如果没有安装的话)

Bash

# 检查 Docker 是否存在,如果报错说明没安装,执行下面的安装脚本
docker --version

# 如果没安装,运行这个官方一键安装脚本:
curl -fsSL https://get.docker.com | bash

2. 创建项目文件夹

我们将所有文件放在一个独立的目录里,整洁规范。

Bash

mkdir -p /root/hetzner_monitor
cd /root/hetzner_monitor

🟡 第三步:创建 Python 脚本

这里是核心逻辑。我们将创建一个 main.py 文件。

1. 创建文件

Bash

nano main.py

2. 粘贴代码 (⚠️ 只有 "配置区域" 需要你修改)

将下面的代码复制进去,然后用键盘移动光标,把配置区域的内容改成你自己的。

Python

# -*- coding: utf-8 -*-
import time
import sys
import requests
from hcloud import Client
from hcloud.images.domain import Image
from hcloud.server_types.domain import ServerType
from hcloud.locations.domain import Location

# ================= ⚠️ 配置区域 (请修改这里) =================

# 1. Hetzner API Token
HETZNER_TOKEN = "你的_API_TOKEN_粘贴在这里"

# 2. Telegram 通知配置
TG_BOT_TOKEN = "你的_BOT_TOKEN_粘贴在这里"
TG_CHAT_ID = "你的_CHAT_ID_粘贴在这里"

# 3. 服务器配置
SERVER_NAME = "My-Server"      # Hetzner 后台的服务器名字,必须完全一致
SNAPSHOT_ID = 12345678         # 快照 ID (数字)
LOCATION = "nbg1"              # 机房: nbg1(纽伦堡), fsn1(法尔肯施泰因), hel1(赫尔辛基), ash(美国)
SERVER_TYPE = "cx22"           # 机型: cx22, cpx11, cpx21 等

# 4. 流量阈值 (达到此值即触发删机)
TRAFFIC_LIMIT_TB = 18.0        # 单位: TB

# 5. 检测频率 (秒)
CHECK_INTERVAL = 300           # 300秒 = 5分钟检查一次

# ==========================================================

LIMIT_BYTES = TRAFFIC_LIMIT_TB * 1024 * 1024 * 1024 * 1024
client = Client(token=HETZNER_TOKEN)

def send_tg(message):
    """发送 Telegram 通知"""
    url = f"https://api.telegram.org/bot{TG_BOT_TOKEN}/sendMessage"
    data = {
        "chat_id": TG_CHAT_ID,
        "text": f"🤖 [Hetzner 监控] \n{message}",
        "parse_mode": "Markdown"
    }
    try:
        requests.post(url, json=data, timeout=10)
    except Exception:
        pass # 发送失败不中断程序

def monitor_task():
    try:
        # 获取服务器
        server = client.servers.get_by_name(SERVER_NAME)
        
        if server is None:
            print(f"[{time.strftime('%H:%M:%S')}] 服务器 '{SERVER_NAME}' 不存在,可能正在重建中...")
            return

        # 获取出站流量
        current_usage = server.outgoing_traffic
        usage_gb = current_usage / (1024 ** 3)
        usage_tb = current_usage / (1024 ** 4)

        log_msg = f"[{time.strftime('%H:%M:%S')}] 当前流量: {usage_gb:.2f} GB ({usage_tb:.4f} TB)"
        print(log_msg)

        # 判断是否超标
        if current_usage > LIMIT_BYTES:
            msg = f"🚨 **流量超标警告!**\n当前用量: `{usage_tb:.4f} TB`\n设定阈值: `{TRAFFIC_LIMIT_TB} TB`\n\n⚠️ **正在执行自动销毁程序...**"
            print("流量超标,发送警告并执行删除...")
            send_tg(msg)

            # 1. 删除服务器
            server.delete()
            print("服务器已删除,等待 15 秒...")
            time.sleep(15)

            # 2. 重建服务器
            print(f"正在使用快照 ID {SNAPSHOT_ID} 重建...")
            # 如果快照里包含了 SSH Key,这里不需要额外指定,否则需在此处添加 ssh_keys 参数
            new_server_response = client.servers.create(
                name=SERVER_NAME,
                server_type=ServerType(name=SERVER_TYPE),
                image=Image(id=SNAPSHOT_ID),
                location=Location(name=LOCATION)
            )
            
            new_ip = new_server_response.server.public_net.ipv4.ip
            
            success_msg = (
                f"✅ **重建成功!**\n"
                f"服务器: `{SERVER_NAME}`\n"
                f"新 IP: `{new_ip}`\n"
                f"快照 ID: `{SNAPSHOT_ID}`"
            )
            print(f"重建完成,新IP: {new_ip}")
            send_tg(success_msg)
            
            # 重建后暂停一段时间防止逻辑死循环
            time.sleep(60)
        
    except Exception as e:
        error_text = f"❌ 监控运行出错: {str(e)}"
        print(error_text)
        send_tg(error_text)

if __name__ == "__main__":
    print("🚀 Hetzner 流量监控守护进程已启动...")
    send_tg(f"✅ 流量监控已在 OVH 启动\n目标服务器: `{SERVER_NAME}`\n阈值: `{TRAFFIC_LIMIT_TB} TB`")
    
    while True:
        monitor_task()
        time.sleep(CHECK_INTERVAL)

3. 保存并退出

  • Ctrl + O (保存) -> 按 Enter (确认)

  • Ctrl + X (退出)


🟠 第四步:创建依赖文件

1. 创建 requirements.txt

Bash

nano requirements.txt

2. 粘贴以下内容

Plaintext

hcloud
requests
  • Ctrl + O, Enter, Ctrl + X 保存退出。


🟣 第五步:创建 Docker 配置文件

1. 创建 Dockerfile

Bash

nano Dockerfile

2. 粘贴以下内容

Dockerfile

FROM python:3.9-slim

WORKDIR /app

# 安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 设置时区为中国时间 (方便看日志)
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

# 复制脚本
COPY main.py .

# 启动 (使用 -u 参数保证日志实时输出)
CMD ["python", "-u", "main.py"]
  • Ctrl + O, Enter, Ctrl + X 保存退出。


🔴 第六步:构建并启动 (Final Step)

现在我们把这个机器人跑起来。

1. 构建镜像

Bash

docker build -t hetzner-bot .

2. 启动容器 (后台运行 + 自动重启)

Bash

docker run -d \
  --name hetzner-monitor \
  --restart always \
  hetzner-bot

🔎 如何验证是否成功?

1. 检查运行日志

输入以下命令,看看它有没有在正常打印流量数据:

Bash

docker logs -f hetzner-monitor
  • 如果你看到类似 [14:20:01] 当前流量: 102.50 GB (0.1001 TB) 的输出,说明成功了

  • 你的 Telegram 同时也应该收到了一条“✅ 流量监控已在 OVH 启动”的消息。

  • Ctrl + C 可以退出日志查看模式(不会停止程序)。

2. 如何停止或重启?

  • 停止:docker stop hetzner-monitor

  • 重启:docker restart hetzner-monitor

  • 修改配置后更新:修改 main.py -> 重新执行 docker build 那一步 -> 重新 docker stop / rm / run

现在,你的 VPS 服务器已经变身成为了 Hetzner 的全自动守卫了。

消息盒子

# 暂无消息 #

只显示最新10条未读和已读信息