Scrutiny Docker Compose 部署指南
在 Ubuntu 22.04 上用 Docker Compose 从零部署 Scrutiny 一体化服务(web 面板+采集器+内嵌 InfluxDB):镜像选型、端口与子网检查、真实磁盘采集验收、无盘环境官方样例数据上报与阈值状态实测、数据持久化、常用运维与 7 类常见问题排障
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 提供三类功能标签,选型前必须分清:
| 标签后缀 | 内容 | 适用场景 |
|---|---|---|
-omnibus | web 面板 + 采集器 + 内嵌 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/udevis 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/health200 表示 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),早于 InfluxDBmetrics桶 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_SCHEDULE | 0 0 * * *(每日 0 点) | 内置采集 cron 表达式,官方 README 说明项 |
COLLECTOR_API_ENDPOINT | http://localhost:8080 | 采集器上报地址;omnibus 内默认即本机 web |
COLLECTOR_HOST_ID | 空 | 主机分组标签,Hub/Spoke 多主机时用于区分来源 |
COLLECTOR_DEBUG / DEBUG | false | 采集器调试日志 |
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 命令),两者互不影响。
十三、参考链接
- 官方仓库与 README(部署命令来源):https://github.com/AnalogJ/scrutiny
- 官方 omnibus Compose 示例:https://github.com/AnalogJ/scrutiny/blob/v0.9.5/docker/example.omnibus.docker-compose.yml
- 镜像版本列表:https://github.com/AnalogJ/scrutiny/pkgs/container/scrutiny/versions
- 采集器排障文档:https://github.com/AnalogJ/scrutiny/blob/v0.9.5/docs/TROUBLESHOOTING_DEVICE_COLLECTOR.md
- NVMe 能力要求(issue #26):https://github.com/AnalogJ/scrutiny/issues/26
- 上报测试样例数据(官方 testdata):https://github.com/AnalogJ/scrutiny/tree/v0.9.5/webapp/backend/pkg/web/testdata
- v0.9.5 Release:https://github.com/AnalogJ/scrutiny/releases/tag/v0.9.5