生成 API Token

    VirtFusion 的面板长下面这样,如果你的 VPS 后台是这样的,那就是 VirtFusion

    部分 VPS 商会把这部分内容内嵌在网页里,这样展示出来的页面会砍掉最顶上那条 Dashboard,像这样:

    但是大同小异,对于这种被砍掉顶部条的,可以用浏览器的「查看框架源代码」功能跳转到新页面后,删去 URL 中的 view-source: 后就是实际后台面板的路径。路径中 /server/ 后的内容即为 service_id

    现在,我们得到了完整的后台面板页面,依次点击「Account」→「API」即可进入到生成 API Token(词元) 页面,点击「Generate Token」即可生成 Token(词元) ,只会展示一次,请及时备份或者复制

    首先点击上图中的「API Documentation」,确认好实际的 API 调用端点,一般为 https://面板域名/api

    配置 Gotify

    Gotify 如何部署就不赘述了,Docker Compose 一把梭!

    在 Apps 中新建应用,获取 Gotify Token

    计划任务

    把下面的内容添加到 sh 文件里,自行使用 crontab 等定时触发调用

    #!/bin/bash
    
    # ==========================================
    # 1. 配置区域 (请在此处填入你的实际信息)
    # ==========================================
    
    # VirtFusion 配置
    VF_API_URL="https://面板域名/api/server"
    SERVER_ID="你的服务器ID,参考上文"
    VF_TOKEN="替换为你的 VirtFusion API Token"
    
    # Gotify 配置
    GOTIFY_URL="https://你的Gotify服务器地址,不要加结尾的 /" 
    GOTIFY_TOKEN="你的 Gotify 应用 Token"
    GOTIFY_PRIORITY=5                       # 消息优先级 (默认 5)
    
    # 数据存储配置 (用于记录上次的流量,以此计算增量)
    # 默认存储在当前用户的家目录下,以 serverId 命名防止多台机器冲突
    STATE_FILE="$HOME/.vf_traffic_${SERVER_ID}_last.txt"
    
    # ==========================================
    # 2. 字节转换函数 (将 Bytes 转换为 KB/MB/GB)
    # ==========================================
    convert_bytes() {
        local bytes=$1
        if [[ -z "$bytes" || "$bytes" == "null" ]]; then
            echo "0 B"
            return
        fi
        
        echo "$bytes" | awk '
        function human(x) {
            s="B KB MB GB TB PB"
            split(s, v, " ")
            i=1
            while (x >= 1024 && i < 6) {
                x /= 1024
                i++
            }
            return sprintf("%.2f %s", x, v[i])
        }
        {print human($1)}'
    }
    
    # ==========================================
    # 3. 获取并解析 VirtFusion 数据
    # ==========================================
    echo "正在获取服务器数据..."
    
    RESPONSE=$(curl -s -X GET "${VF_API_URL}/${SERVER_ID}?state=true" \
      -H "Accept: application/json" \
      -H "Authorization: Bearer ${VF_TOKEN}")
    
    if ! echo "$RESPONSE" | jq -e . >/dev/null 2>&1; then
        echo "错误: VirtFusion API 返回了无效的 JSON 或请求失败。"
        exit 1
    fi
    
    SERVER_NAME=$(echo "$RESPONSE" | jq -r '.data.name')
    STATE_STATUS=$(echo "$RESPONSE" | jq -r '.data.state')
    
    if [[ "$STATE_STATUS" == "null" ]]; then
        MESSAGE="⚠️ 服务器 $SERVER_NAME 当前未运行 (State 为 null),无法获取实时流量数据。"
        TITLE="VirtFusion 流量报告 - $SERVER_NAME (离线)"
    else
        # 提取当前流量字节数
        RX_BYTES=$(echo "$RESPONSE" | jq -r '.data.state.network.primary.traffic.rx')
        TX_BYTES=$(echo "$RESPONSE" | jq -r '.data.state.network.primary.traffic.tx')
        TOTAL_BYTES=$(echo "$RESPONSE" | jq -r '.data.state.network.primary.traffic.total')
    
        # ==========================================
        # 4. 计算自上次以来的增量流量
        # ==========================================
        DIFF_BYTES=0
        DIFF_HUMAN=""
    
        if [[ -f "$STATE_FILE" ]]; then
            # 读取上次记录的总流量
            PREV_TOTAL=$(cat "$STATE_FILE")
            
            # 判断是否发生了流量重置 (当前流量 < 上次流量)
            if (( TOTAL_BYTES >= PREV_TOTAL )); then
                DIFF_BYTES=$(( TOTAL_BYTES - PREV_TOTAL ))
                DIFF_HUMAN=$(convert_bytes "$DIFF_BYTES")
            else
                # 流量被重置了,增量就是当前的全部流量
                DIFF_BYTES=$TOTAL_BYTES
                DIFF_HUMAN="$(convert_bytes "$DIFF_BYTES") (流量周期已重置)"
            fi
        else
            # 第一次运行,没有历史数据
            DIFF_HUMAN="首次记录,无历史对比数据"
        fi
    
        # 将当前的最新总流量写入文件,供下次运行使用
        echo "$TOTAL_BYTES" > "$STATE_FILE"
    
        # ==========================================
        # 5. 格式化数据并构建消息
        # ==========================================
        RX_HUMAN=$(convert_bytes "$RX_BYTES")
        TX_HUMAN=$(convert_bytes "$TX_BYTES")
        TOTAL_HUMAN=$(convert_bytes "$TOTAL_BYTES")
    
        TITLE="📊 流量报告: $SERVER_NAME"
        MESSAGE="昨日已用:$DIFF_HUMAN
    本月已用:$TX_HUMAN
    出入站总消耗: $TOTAL_HUMAN
    ---
    详细明细:
    ⬇️ 入站 (下载): $RX_HUMAN
    ⬆️ 出站 (上传): $TX_HUMAN"
    fi
    
    # ==========================================
    # 6. 发送 Gotify 通知
    # ==========================================
    echo "正在发送 Gotify 通知..."
    
    HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST "${GOTIFY_URL}/message?token=${GOTIFY_TOKEN}" \
      -F "title=${TITLE}" \
      -F "message=${MESSAGE}" \
      -F "priority=${GOTIFY_PRIORITY}" \
      -F "extras={\"client::display\": {\"contentType\": \"text/markdown\"}}")
    
    if [[ "$HTTP_STATUS" -eq 200 ]]; then
        echo "✅ 通知发送成功!"
        echo "--- 消息预览 ---"
        echo -e "$MESSAGE"
    else
        echo "❌ 发送失败,Gotify HTTP 状态码: $HTTP_STATUS"
    fi

    如果你在使用 1Panel 等面板,那直接把这部分代码添加到后台,执行和记录上会更方便点, 「1Panel后台」→「计划任务」→「脚本库」,并添加计划任务指定好触发时间

    效果

    我自己设置的是每天 0点0分 自动触发一次,这样就会把数据推送到我所有安装了 Gotify 的设备上

    注⚠️:脚本默认统计的「昨日已用」数据是基于上一次调用这个脚本时候的流量用量计算的,也就是说如果你不是让他自动在每天固定时间触发,而是手动触发的话,那「昨日已用」仅代表你上次执行到这次执行之间消耗的流量情况