Scrutiny Docker Compose 部署指南

在 Ubuntu 22.04 上用 Docker Compose 从零部署 Scrutiny 一体化服务(web 面板+采集器+内嵌 InfluxDB):镜像选型、端口与子网检查、真实磁盘采集验收、无盘环境官方样例数据上报与阈值状态实测、数据持久化、常用运维与 7 类常见问题排障

ScrutinyScrutinyDocker监控2026/10/18

Scrutiny Docker Compose 部署指南

目标:在一台 Ubuntu 22.04 服务器上用 Docker Compose 从零部署 Scrutiny 一体化服务(web 面板 + 采集器 + 内嵌 InfluxDB),完成真实磁盘采集、健康探活、面板验收与阈值状态实测。已在 Ubuntu 22.04 实测通过。

一、环境信息

本章列出本次部署实测的完整环境基准,读者按相同版本操作可获得一致结果。

  • 操作系统:Ubuntu 22.04(x86_64,内核 6.8.0-138-generic)
  • Docker:29.8.1;Docker Compose:v5.5.1
  • Scrutiny 版本:v0.9.5(官方最新稳定版,2026-09-30 发布)
  • 镜像:ghcr.io/analogj/scrutiny:v0.9.5-omnibus(摘要 sha256:6ee271ee531458f134220ca8b2c5c8ccc2711a799c827fef953fa865d91e312f)
  • 内嵌组件:InfluxDB v2.2.0、smartmontools(smartctl 7.5 r5714)
  • 部署目录:/opt/scrutiny-deploy/(含 config/、influxdb/ 两个持久化子目录)
  • 宿主端口:8102 → 8080(Web 面板)、8103 → 8086(InfluxDB 管理端口)
  • 自定义网络:Compose 项目默认网络,显式子网 10.89.28.0/24
  • 磁盘设备:/dev/sda(本次实测直通给采集器,真实物理盘场景同理)
  • 数据库文件:/opt/scrutiny-deploy/config/scrutiny.db(SQLite,设备元数据)

二、镜像选型说明

Scrutiny 官方在 GitHub Container Registry(ghcr.io)发布镜像,仓库名 ghcr.io/analogj/scrutiny。官方 README 提供三类功能标签,选型前必须分清:

标签后缀内容适用场景
-omnibusweb 面板 + 采集器 + 内嵌 InfluxDB 三合一单机自监控,最常用
-web仅 web 面板 + API(需另配 InfluxDB)Hub/Spoke 中心节点
-collector仅采集器 + smartctl + cron 调度多台被监控主机各跑一个

标签形态与官方建议:

  • 版本化标签遵循 semver 拼接规则,如 v0.9.5-omnibus、v0.9-web、v0-collector;另有 latest-omnibus、nightly-omnibus 等滚动标签。
  • 官方 README 原文警告:「Using latest- tags is dangerous as it can update your image without warning. It is a best practice to pin a specific version.」——本文固定使用 v0.9.5-omnibus。
  • 架构支持(官方 README 矩阵):linux-amd64 与 linux-arm64 提供全部三类标签;linux-arm-7 仅 web/collector(issue #236)。

关键差异与选型结论:监控本机磁盘选 -omnibus 一步到位;多台服务器集中监控时中心机用 -web + 独立 InfluxDB、被监控机用 -collector。本文演示单机 omnibus 方案,Hub/Spoke 属进阶形态,配置要点在第九章有对应说明。

三、前置条件

部署前需完成三项检查:磁盘可被 smartctl 识别、宿主端口空闲、网段不与现有网络冲突。逐项执行并记录结果。

3.1 确认磁盘可被 smartctl 识别

omnibus 镜像内置 smartctl 7.5,可先在部署前用一次性容器验证(也可部署后进服务内执行,见第四章)。查询设备清单:

smartctl --scan

本次实测环境回显(omnibus 内置 smartctl,与宿主同一块盘):

/dev/sda -d scsi # /dev/sda, SCSI device

版本确认:

smartctl --version

实测回显(首行):

smartctl 7.5 2025-04-30 r5714 [x86_64-linux-6.8.0-138-generic] (local build)

💡 技术拓展:smartctl --scan 输出的设备类型决定采集质量。常见类型对比:

输出类型含义注意事项
-d satATA 盘经 SAT 层直通属性最全,含 ATA 属性表
-d scsiSCSI/SAS 盘或虚拟盘属性集合不同,虚拟盘常无 SMART 状态
-d nvmeNVMe 盘需要 CAP_SYS_ADMIN 能力(官方 issue #26)
-d megaraid,NRAID 卡后第 N 块物理盘需在 collector 配置中显式声明

本文实测机为虚拟机,/dev/sda 识别为 -d scsi(VMware 虚拟盘),仍可完成完整部署链路验证;真实物理盘通常识别为 -d sat 或 -d nvme。

3.2 确认宿主端口空闲

Scrutiny web 默认监听 8080、InfluxDB 管理端口 8086。先查看目标端口占用情况,冲突则顺延换端口:

ss -ltn | grep -E ':(8080|8086|810[0-9])\b'

本次实测回显(8100–8101 及更早号段已被其他服务占用,故 Web 端口顺延选用 8102、InfluxDB 管理端口选用 8103):

LISTEN 0      4096         0.0.0.0:8100       0.0.0.0:*
LISTEN 0      4096         0.0.0.0:8101       0.0.0.0:*
LISTEN 0      4096            [::]:8100          [::]:*
LISTEN 0      4096            [::]:8101          [::]:*

8102/8103 无输出即空闲,可直接使用。

3.3 确认自定义网段未占用

Compose 显式声明子网可避免与现有网络冲突。检查现有网络的子网清单:

docker network inspect $(docker network ls -q) --format '{{.Name}} {{range .IPAM.Config}}{{.Subnet}} {{end}}' | grep 10.89.

本次实测回显(节选,10.89.28.0/24 未被占用):

adguardhome-net 10.89.22.0/24
authelia_authnet 10.89.23.0/24
s3-activepieces_apnet 10.89.27.0/24

四、部署步骤

本章从建目录到面板可访问完整走一遍,每步配实测回显。

4.1 创建部署目录

持久化数据(SQLite 与 InfluxDB 文件)通过绑定挂载落在部署目录下,升级或重建服务数据不丢:

mkdir -p /opt/scrutiny-deploy/config
mkdir -p /opt/scrutiny-deploy/influxdb

4.2 编写 docker-compose.yml

在 /opt/scrutiny-deploy/docker-compose.yml 写入以下内容(与官方 docker/example.omnibus.docker-compose.yml 同构,按本文环境固定了版本标签、端口与子网):

services:
  scrutiny:
    image: ghcr.io/analogj/scrutiny:v0.9.5-omnibus   # 固定版本,勿用 latest-
    container_name: scrutiny-v095-web
    restart: unless-stopped
    cap_add:
      - SYS_RAWIO        # SATA/SAS 盘查询 SMART 必需;NVMe 盘另需 SYS_ADMIN
    ports:
      - "8102:8080"      # web 面板(左侧宿主端口按 §3.2 检查结果调整)
      - "8103:8086"      # InfluxDB 管理端口(排障用,可不映射)
    volumes:
      - /run/udev:/run/udev:ro        # 设备元数据(官方要求,缺它 collector 无法取盘信息)
      - ./config:/opt/scrutiny/config # SQLite 数据库 + 配置文件
      - ./influxdb:/opt/scrutiny/influxdb  # 指标时序数据
    devices:
      - "/dev/sda"       # 每块要监控的盘都列在这里(smartctl --scan 的结果逐行照抄)
    networks:
      default:
        ipv4_address: 10.89.28.10

networks:
  default:
    ipam:
      config:
        - subnet: 10.89.28.0/24   # 显式子网,避免自动分配冲突

配置要点逐项说明:

  • image:固定 v0.9.5-omnibus,保证升级可控(滚动标签会在无人操作时引入新版本)。
  • cap_add: SYS_RAWIO:smartctl 读取 SATA 盘 SMART 数据需要原始 IO 能力,官方 README 明确此项必需。
  • /run/udev 只读挂载:官方说明「/run/udev is necessary to provide the Scrutiny collector with access to your device metadata」。
  • devices:把 smartctl --scan 列出的每块盘逐一传入;NVMe 盘还需在 cap_add 中追加 SYS_ADMIN(官方 issue #26)。
  • subnet:显式指定 10.89.28.0/24,与 §3.3 检查结果一致;给服务固定 IP 便于网络排障。

4.3 启动服务

cd /opt/scrutiny-deploy && docker compose up -d

实测回显:

 Network scrutiny-deploy_default Created
 Container scrutiny-v095-web Creating
 Container scrutiny-v095-web Created
 Container scrutiny-v095-web Starting
 Container scrutiny-v095-web Started

4.4 启动状态自查

确认容器运行与端口映射:

docker compose ps

实测回显:

NAME                IMAGE                                     COMMAND   SERVICE    CREATED          STATUS          PORTS
scrutiny-v095-web   ghcr.io/analogj/scrutiny:v0.9.5-omnibus   "/init"   scrutiny   14 minutes ago   Up 14 minutes   0.0.0.0:8102->8080/tcp, [::]:8102->8080/tcp, 0.0.0.0:8103->8086/tcp, [::]:8103->8086/tcp

确认子网与宿主默认路由未被影响(网段硬性自查两步):

docker network inspect scrutiny-deploy_default --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'

实测回显:

10.89.28.0/24
ip route get 192.168.1.62

实测回显(默认路由仍走物理网卡 ens33,未被新网桥劫持):

192.168.1.62 via 192.168.146.2 dev ens33 src 192.168.146.128 uid 0
    cache

4.5 健康探活

等待约 10 秒(内部 InfluxDB 初始化),依次验证 API 与前端:

curl -s -i http://127.0.0.1:8102/api/health

实测回显:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-utf-8
Date: Sun, 18 Oct 2026 09:34:10 GMT
Content-Length: 16

{"success":true}

InfluxDB 管理端口探活:

curl -s http://127.0.0.1:8103/health

实测回显:

{"name":"influxdb", "message":"ready for queries and writes", "status":"pass", "checks":[], "version": "v2.2.0", "commit": "a2f8538837"}

⚠️ 注意:/api/health 200 表示 web 进程、SQLite、InfluxDB 三者全部就绪(该接口在源码中会实际检查两个存储的连通性),是判断部署成功的唯一权威探针。

4.6 首次采集与数据确认

omnibus 形态的采集器随服务启动自动执行一轮采集(内置 cron 每日 0 点全量采集)。查看启动日志确认采集完成:

docker compose logs scrutiny | grep -E 'Main: Completed|smartctl'

实测回显(节选):

time="2026-10-18T09:33:56Z" level=info msg="Main: Completed" type=metrics

用 Dashboard 汇总接口确认设备已注册并有指标:

curl -s http://127.0.0.1:8102/api/summary

实测回显(节选,本次实测机的虚拟盘):

{"data":{"summary":{"e6b5c5a4-c639-5164-af24-c22f28696ef6":{"device":{"archived":false,"wwn":"","device_name":"sda","model_name":"VMware, VMware Virtual S","capacity":858993459200,"device_protocol":"SCSI","device_status":1,"scrutiny_uuid":"e6b5c5a4-c639-5164-af24-c22f28696ef6"},"smart":{"collector_date":"2026-10-18T09:33:56Z"},"temp_history":[{"date":"2026-10-18T09:34:26.093438199Z","temp":0}]}}},"success":true}

浏览器打开 http://<服务器IP>:8102/(自动跳转 /web/)即可看到磁盘卡片面板。前端探活验证:

curl -s -o /dev/null -w 'GET /web/ -> %{http_code}\n' http://127.0.0.1:8102/web/

实测回显:

GET /web/ -> 200

五、部署验收与阈值状态实测

本章解决两个验收问题:一是无真实 SMART 设备的环境(虚拟机、无盘测试机)如何验证上报链路与面板;二是阈值判定机制是否真的会改变设备状态。两者都通过官方 API 与官方仓库自带测试数据完成,全程实测。

5.1 上报链路说明(无盘环境验收口径)

真实环境由采集器自动发现磁盘并上报,无需人工干预。无盘环境验证时,Scrutiny 的上报 API 是公开契约(官方采集器就是这两个接口的调用方):

  • POST /api/devices/register:注册设备清单,返回服务端过滤结果;
  • POST /api/device/<scrutiny_uuid>/smart:上报单盘 smartctl JSON 数据。

官方仓库 webapp/backend/pkg/web/testdata/ 目录提供了与采集器上报格式完全一致的测试样例(register-devices-req.json、upload-device-metrics-req.json,v0.9.5 源码树),本文直接引用官方样例数据驱动验收,不引入任何第三方伪造数据。

⚠️ 说明:官方当前 Release 并未发布独立的「mock 采集器」二进制;源码树中保留的 scrutiny-collector-selftest 命令在 v0.9.5 为空实现(Run() 直接返回,不推送数据)。因此无盘验收的正确口径是:官方样例数据 + 官方上报 API。真实环境仍用真实采集器读取磁盘设备。

5.2 注册测试设备并上报健康数据

从官方注册样例中提取 sdb 设备(WDC WD140EDFZ-11A0VA0,14TB 机械盘,scrutiny_uuid=3ea22b35-682b-49fb-a655-abffed108e48):

curl -s -X POST -H 'Content-Type: application/json' \
  -d @register-sdb.json http://127.0.0.1:8102/api/devices/register

实测回显(节选):

{
    "success": true,
    "errors": null,
    "data": [
        {
            "device_name": "sdb",
            "model_name": "WDC WD140EDFZ-11A0VA0",
            "capacity": 14000519643136,
            "device_status": 0,
            "scrutiny_uuid": "3ea22b35-682b-49fb-a655-abffed108e48"
        }
    ]
}

上报该盘的官方健康样例数据(smartctl 7.0 JSON 格式,18 个 ATA 属性全部健康,温度 32℃):

curl -s -X POST -H 'Content-Type: application/json' \
  -d @upload-sdb-healthy.json http://127.0.0.1:8102/api/device/3ea22b35-682b-49fb-a655-abffed108e48/smart

实测回显:

{"success":true}

验证面板数据(device_status: 0 即健康,温度已入库):

curl -s http://127.0.0.1:8102/api/summary | python3 -c "
import json,sys
d=json.load(sys.stdin)
ent=d['data']['summary']['3ea22b35-682b-49fb-a655-abffed108e48']
print('status:', ent['device']['device_status'], '| temp_history:', ent.get('temp_history'))
"

实测回显:

status: 0 | temp_history: [{'date': '2026-10-18T09:38:30.689231338Z', 'temp': 32}]

⚠️ 注意:直接使用官方样例原始文件会报错——样例数据内的采集时间是 2020 年(local_time.time_t=1592697810),早于 InfluxDB metrics 桶 15 天的保留策略,服务端日志会记录 points beyond retention policy dropped=1 并返回 {"success":false}(排障过程详见第十二章)。本文实测前已把样例中的 local_time 更新为当前时间。

5.3 阈值状态实测:healthy → failed

v0.9.5 的健康判定分两层,且阈值不在 scrutiny.yaml 中配置(v0.8 时代的 thresholds 配置段已在 0.9 系列移除,改为代码内置 + 面板运行时设置,详见《Scrutiny 0.9.5 配置参数详解》):

  • 厂商 SMART 阈值层:设备整体 smart_status.passed=false 时置 device_status=1(FailedSmart);
  • Scrutiny 观察阈值层:属性值落入高年化故障率区间时置 device_status=2(FailedScrutiny)。

用例一(Scrutiny 观察阈值):把官方样例中属性 5(Reallocated_Sector_Ct,重映射扇区数)的 raw 值从 0 改为 999。按官方内置元数据,999 落入 260–1100 区间,年化故障率约 56.8%,超过关键属性 10% 判定线:

curl -s -X POST -H 'Content-Type: application/json' \
  -d @upload-sdb-scrutiny-fail.json http://127.0.0.1:8102/api/device/3ea22b35-682b-49fb-a655-abffed108e48/smart

实测回显与状态核对:

{"success":true}
sdb device_status: 2

单属性明细(状态位 4 = FailedScrutiny,附判定原因与故障率):

{
  "attribute_id": 5,
  "value": 100,
  "thresh": 1,
  "raw_value": 999,
  "when_failed": "",
  "status": 4,
  "failure_rate": 0.5676621428968173,
  "status_reason": "Observed Failure Rate for Critical Attribute is greater than 10%"
}

用例二(厂商 SMART 阈值):恢复属性 5 为健康值,改设 smart_status.passed=false 模拟「盘体报告 SMART 失败」:

curl -s -X POST -H 'Content-Type: application/json' \
  -d @upload-sdb-smartstatus-fail.json http://127.0.0.1:8102/api/device/3ea22b35-682b-49fb-a655-abffed108e48/smart

实测回显与状态核对:

{"success":true}
sdb device_status: 1

两条用例证明:设备状态会随上报数据在 0(健康)→ 2(Scrutiny 判定失败)→ 1(厂商判定失败) 之间真实变化,Dashboard 卡片同步变色。

5.4 恢复健康数据

实测结束后重新上报原始健康样例,确认状态复位:

curl -s -X POST -H 'Content-Type: application/json' \
  -d @upload-sdb-healthy.json http://127.0.0.1:8102/api/device/3ea22b35-682b-49fb-a655-abffed108e48/smart

实测回显与最终状态:

{"success":true}
sdb status: 0

💡 说明:测试设备会一直保留在 Dashboard 中(与真实盘并列展示)。如不需要,可在面板设置中将该设备归档(POST /api/device/<uuid>/archive),或删除 ./config/scrutiny.db 后重建服务回到初始状态。

六、数据持久化说明

Scrutiny 的全部状态都在两个绑定挂载目录里,服务重建、升级、宿主机重启都不丢数据:

挂载点内容说明
./config(→ /opt/scrutiny/config)scrutiny.db(SQLite:设备清单、设置)、scrutiny.yaml、collector.yaml(如有)删除即回到初始状态(设备重新自动注册)
./influxdb(→ /opt/scrutiny/influxdb)InfluxDB 全部时序数据(metrics 等 4 个桶)与自动初始化的管理员凭据删除即丢失全部历史趋势

本次实测中,容器停止后以等价单命令方式重建(见第十章)再切回 Compose,/api/summary 中设备与温度历史均完整保留,持久化行为已实测验证。

备份建议:停服状态下(docker compose stop)打包 config/ 与 influxdb/ 两个目录即可获得一致快照;运行中备份 SQLite 存在锁风险,不建议。

七、环境变量表

omnibus 服务内的环境变量分两组:采集器变量(内置 cron 调度与上报行为)与服务端变量。下表变量名均来自官方 README 与采集器 --help 实测回显:

变量默认值作用
COLLECTOR_CRON_SCHEDULE0 0 * * *(每日 0 点)内置采集 cron 表达式,官方 README 说明项
COLLECTOR_API_ENDPOINThttp://localhost:8080采集器上报地址;omnibus 内默认即本机 web
COLLECTOR_HOST_ID空主机分组标签,Hub/Spoke 多主机时用于区分来源
COLLECTOR_DEBUG / DEBUGfalse采集器调试日志
COLLECTOR_LOG_FILE空(输出 STDOUT)采集器日志落盘路径
SCRUTINY_LOG_FILE空服务端日志落盘路径

采集器 run 子命令的帮助回显(docker exec scrutiny-v095-web /opt/scrutiny/bin/scrutiny-collector-metrics run --help,实测)证实了上表变量名:

OPTIONS:
   --config value        Specify the path to the devices file
   --api-endpoint value  The api server endpoint [$COLLECTOR_API_ENDPOINT, $SCRUTINY_API_ENDPOINT]
   --log-file value      Path to file for logging. Leave empty to use STDOUT [$COLLECTOR_LOG_FILE]
   --debug               Enable debug logging (default: false) [$COLLECTOR_DEBUG, $DEBUG]
   --host-id value       Host identifier/label, used for grouping devices [$COLLECTOR_HOST_ID]
   --help, -h            show help

服务端配置还支持 SCRUTINY_ 前缀的环境变量覆盖(配置键层级用下划线连接,如 SCRUTINY_WEB_LISTEN_PORT=8080 覆盖 web.listen.port),适合不落配置文件的临时调整。

调整采集频率示例(每日 8 点采集):

    environment:
      - COLLECTOR_CRON_SCHEDULE=0 8 * * *

八、配置参数说明

omnibus 形态默认零配置即可运行(服务启动日志会明确提示使用默认值,实测回显:No configuration file found at /opt/scrutiny/config/scrutiny.yaml. Using Defaults.)。需要定制时,在部署目录放两个可选配置文件:

  • /opt/scrutiny-deploy/config/scrutiny.yaml:服务端配置(监听端口/数据库位置/InfluxDB 连接/通知渠道);
  • /opt/scrutiny-deploy/config/collector.yaml:采集端配置(设备类型覆写、忽略设备、上报地址、smartctl 参数)。

最常用的两个定制场景:

其一,接入通知渠道(服务端 scrutiny.yaml,以 Telegram 为例,其余渠道写法见官方 example.scrutiny.yaml 的 notify.urls 注释清单):

version: 1

web:
  listen:
    port: 8080
    host: 0.0.0.0
  database:
    location: /opt/scrutiny/config/scrutiny.db
  influxdb:
    host: localhost
    port: 8086

notify:
  urls:
    - "telegram://<token>@telegram?chats=<chat-id>"

⚠️ 注意:notify.urls 中的 token/chat-id 属于真实凭据,正式环境建议用环境变量或密钥管理注入,不要提交到代码仓库。本文不落真实值。

其二,RAID 卡场景声明虚拟设备(采集端 collector.yaml,官方 example.collector.yaml 原样写法):

version: 1

devices:
  - device: /dev/bus/0
    type:
      - megaraid,14
      - megaraid,15

配置全量键位、默认值与运行时阈值机制的逐项详解,见《Scrutiny 0.9.5 配置参数详解》。

九、配置文件挂载

两个配置文件都挂载自部署目录 ./config(即服务内 /opt/scrutiny/config),放好文件重启服务即生效,无需改 Compose:

cp scrutiny.yaml /opt/scrutiny-deploy/config/
docker compose -f /opt/scrutiny-deploy/docker-compose.yml restart

验证配置已被加载(服务端启动日志两种状态,实测均有):

  • 未放置配置:No configuration file found at /opt/scrutiny/config/scrutiny.yaml. Using Defaults.
  • 已放置配置:Loading configuration file: /opt/scrutiny/config/scrutiny.yaml

配置错误会导致服务启动失败的回退行为:服务端对已废弃键(如 notify.level)直接拒绝启动并报配置校验错误,此时修正配置文件后 restart 即可。

十、等价 docker run

与第四章 Compose 完全等价的单命令启动形态(官方 README 的 omnibus 命令 + 本文端口/路径),可用于无 Compose 环境或快速验证。本次实测执行的完整命令:

docker run -d --name scrutiny-v095-run --restart unless-stopped \
  -p 8102:8080 -p 8103:8086 \
  -v /opt/scrutiny-deploy/config:/opt/scrutiny/config \
  -v /opt/scrutiny-deploy/influxdb:/opt/scrutiny/influxdb \
  -v /run/udev:/run/udev:ro \
  --cap-add SYS_RAWIO \
  --device=/dev/sda \
  ghcr.io/analogj/scrutiny:v0.9.5-omnibus

实测回显(容器 ID 哈希 + 健康探活):

390e6dc48b7228b40cc96394a4336cd7ff05b4249fa75e3ff92c1871d6b5163a
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 16

{"success":true}

与 Compose 的对应关系:ports ↔ ports:、-v ↔ volumes:、--cap-add ↔ cap_add:、--device ↔ devices:,逐项一一映射。验证通过后删除该容器再切回 Compose,避免两个服务同时读写同一数据目录:

docker rm -f scrutiny-v095-run

⚠️ 注意:等价单命令与 Compose 服务不可同时运行——两者挂载同一 SQLite 数据库与 InfluxDB 目录,同时启动会引发数据竞争。

十一、常用运维命令

以下命令均在 docker-compose.yml 所在目录执行(或加 -f 指定路径)。

查看实时日志(服务端 + 采集器混合输出):

docker compose logs --tail 5 scrutiny

实测回显(节选):

scrutiny-v095-web  | time="2026-10-18T09:49:13Z" level=info msg="Checking Influxdb & Sqlite health" type=web
scrutiny-v095-web  | time="2026-10-18T09:49:29Z" level=info msg="::1 - a810b3ac7911 [18/Oct/2026:09:49:29 +0000] \"POST /api/devices/register\" 200 590 \"\" \"Go-http-client/1.1\" (1ms)" clientIP="::1" hostname=a810b3ac7911 latency=1 method=POST path=/api/devices/register referer= respLength=590 statusCode=200 type=web userAgent=Go-http-client/1.1
scrutiny-v095-web  | time="2026-10-18T09:49:29Z" level=info msg="::1 - a810b3ac7911 [18/Oct/2026:09:49:29 +0000] \"POST /api/device/e6b5c5a4-c639-5164-af24-c22f28696ef6/smart\" 200 16 \"\" \"Go-http-client/1.1\" (8ms)" clientIP="::1" hostname=a810b3ac7911 latency=8 method=POST path=/api/device/e6b5c5a4-c639-5164-af24-c22f28696ef6/smart referer= respLength=16 statusCode=200 type=web userAgent=Go-http-client/1.1

手动立即触发一轮采集(不等每日 cron):

docker compose exec scrutiny /opt/scrutiny/bin/scrutiny-collector-metrics run --debug

实测回显(末段,正常完成时以 Main: Completed 收尾):

time="2026-10-18T09:49:29Z" level=info msg="Publishing smartctl results for e6b5c5a4-c639-5164-af24-c22f28696ef6\n" type=metrics
time="2026-10-18T09:49:29Z" level=info msg="Main: Completed" type=metrics

服务重启与升级(版本升级 = 改 image 标签 + pull + up):

docker compose pull
docker compose up -d

docker compose pull 实测回显(已是最新版时):

 Image ghcr.io/analogj/scrutiny:v0.9.5-omnibus Pulling
 Image ghcr.io/analogj/scrutiny:v0.9.5-omnibus Pulled

升级完成后核对版本:curl -s http://127.0.0.1:8102/api/health 返回 200 且 Dashboard 页脚版本号已更新。数据目录不变,历史自动保留。

停服与彻底清理(数据目录是否删除决定是否保留历史):

docker compose down      # 停止并移除服务与网络,./config 与 ./influxdb 保留
docker compose down -v   # 连同命名卷清理(本文全为绑定挂载,实际数据仍在宿主目录)

十二、常见问题

以下问题均为本次实测真实遇到或依据官方排障文档沉淀,附现场证据与解法。

Q1:目标端口被占用导致启动失败怎么办? 现象:docker compose up 报 Bind for 0.0.0.0:8102 failed: port is already allocated。定位:ss -ltn | grep 8102 确认占用方。解决:把 Compose 中 ports 左侧宿主端口顺延更换(本文实测环境 8091–8101 已被占用,顺延选用 8102/8103),改完 docker compose up -d 重建即可,数据不受影响。

Q2:面板上虚拟盘/无 SMART 设备显示「失败」(红色)? 现象:本次实测机的 VMware 虚拟盘在 Dashboard 标记为失败,/api/summary 返回 device_status: 1。原因:设备无法返回 smart_status.passed=true(虚拟盘无 SMART 状态上报),源码判定逻辑为「SmartStatus 不通过即置 FailedSmart」,属机制使然。解决:真实物理盘不受影响;虚拟盘建议在面板中归档,或从 Compose devices: 中移除、collector 配置中 ignore: true。

Q3:采集器日志出现 smartctl returned an error code (4)? 现象:手动采集实测回显——

time="2026-10-18T09:49:29Z" level=error msg="smartctl returned an error code (4) while processing sda\n" type=metrics
time="2026-10-18T09:49:29Z" level=error msg="smartctl detected a checksum error" type=metrics
time="2026-10-18T09:49:29Z" level=info msg="Publishing smartctl results for e6b5c5a4-c639-5164-af24-c22f28696ef6\n" type=metrics

原因:smartctl 对虚拟盘返回校验和警告(退出码 4)。关键结论:采集器会照常推送已取得的数据(随后一行 Publishing ...),不影响面板。物理盘出现退出码 4 时,官方 docs/TROUBLESHOOTING_DEVICE_COLLECTOR.md 建议结合 -T permissive 参数与设备类型覆写排查。

Q4:手动上报测试数据返回 {"success":false} 且日志报 points beyond retention policy dropped? 现象与定位(服务端日志实测回显):

time="2026-10-18T09:37:29Z" level=error msg="An error occurred while saving smartctl metrics unprocessable entity: failure writing points to database: partial write: points beyond retention policy dropped=1" type=web

原因:官方样例数据的采集时间戳是 2020 年(local_time.time_t=1592697810),早于 metrics 桶 15 天保留期,InfluxDB 拒绝写入。解决:把上报 JSON 中 local_time.time_t 改为当前 Unix 秒级时间戳(date +%s 取值)、asctime 改为当前 UTC 字符串后重推,实测返回 {"success":true}。

Q5:NVMe 盘读不到 SMART 数据? 官方 README 说明:NVMe 盘在 CAP_SYS_RAWIO 之外还需 CAP_SYS_ADMIN(issue #26)。Compose 写法:

    cap_add:
      - SYS_RAWIO
      - SYS_ADMIN

同时确认 NVMe 设备已加入 devices:(如 /dev/nvme0)。

Q6:启动后 Dashboard 一片空白、/api/summary 无设备? 排查顺序:① devices: 是否漏挂磁盘(对照宿主 smartctl --scan 输出逐行补齐);② /run/udev 是否只读挂载(缺它采集器拿不到设备元数据);③ 看采集器日志 docker compose logs scrutiny | grep -E 'detected|register',正常应出现 Sending N/N detected devices to API 与 Main: Completed。

Q7:采集频率太低(默认每日一次),想改成每小时? 在 Compose 中加环境变量后重建:environment: - COLLECTOR_CRON_SCHEDULE=0 * * * *,随后 docker compose up -d。也可随时手动触发(见第十一章 exec 命令),两者互不影响。

十三、参考链接

  1. 官方仓库与 README(部署命令来源):https://github.com/AnalogJ/scrutiny
  2. 官方 omnibus Compose 示例:https://github.com/AnalogJ/scrutiny/blob/v0.9.5/docker/example.omnibus.docker-compose.yml
  3. 镜像版本列表:https://github.com/AnalogJ/scrutiny/pkgs/container/scrutiny/versions
  4. 采集器排障文档:https://github.com/AnalogJ/scrutiny/blob/v0.9.5/docs/TROUBLESHOOTING_DEVICE_COLLECTOR.md
  5. NVMe 能力要求(issue #26):https://github.com/AnalogJ/scrutiny/issues/26
  6. 上报测试样例数据(官方 testdata):https://github.com/AnalogJ/scrutiny/tree/v0.9.5/webapp/backend/pkg/web/testdata
  7. v0.9.5 Release:https://github.com/AnalogJ/scrutiny/releases/tag/v0.9.5