一、巡检为什么要分层
巡检不是为了“跑一堆命令”,而是为了回答三个问题:站点能不能访问、服务是不是正常、机器有没有被拖垮或被人盯上。
我把它拆成两个视角:
- 外部视角:从公网用
curl访问真实域名,看到的是读者实际体验。它不关心服务器内部怎么配置,只关心“请求能不能拿到正确的响应”。 - 内部视角:SSH 登录服务器,看证书、服务、防火墙、负载、日志。它能解释“为什么外部看到的是这个结果”。
两个视角必须都看。只看外部,页面 200 也可能是缓存或旧内容;只看内部,服务全绿也可能因为证书过期、DNS 或防火墙问题,读者根本打不开。
下面的命令分两类:
- 在本地 Windows PowerShell 执行的,标
PowerShell; - 在服务器执行的,标
bash(通过 SSH 进入服务器后执行)。
本文命令与数值来自 2026-11-08 的实际采集。凡是未在本机验证过的写法,都会单独标注“未在本机验证”。
二、第一层:可达性
2.1 命令
curl.exe -s -o NUL -w "%{http_code} %{time_total}`n" https://notes.hokachi.top/
一次检查多个地址:
$urls = @(
'https://notes.hokachi.top/',
'https://notes.hokachi.top/internal/ncat-reverse-shell/',
'https://notes.hokachi.top/linux/ssh-hardening-practice/',
'https://notes.hokachi.top/contact/',
'https://notes.hokachi.top/favicon.svg'
)
foreach ($u in $urls) {
$r = curl.exe -s -o NUL -w "%{http_code} %{time_total}" $u
Write-Output "$r $u"
}
2.2 参数拆解
| 参数 | 含义 |
|---|---|
curl.exe | Windows 自带的真正 curl。必须写 .exe,原因见“三个实操陷阱” |
-s | silent,静默模式:不显示进度条和错误说明,只输出 -w 指定的内容 |
-o NUL | 把响应正文写到 NUL(Windows 的空设备),等于丢弃正文,只看状态码 |
-w "%{http_code} %{time_total}" | 请求结束后按模板输出:%{http_code} 是 HTTP 状态码,%{time_total} 是从发起到结束的总耗时(秒) |
| 末尾的 URL | 要访问的地址,注意文章地址结尾有 / |
2.3 正常 / 异常 / 先查什么
| 项目 | 正常 | 异常 | 异常时先查什么 |
|---|---|---|---|
| 状态码 | 全部 200 | 404、502、503、000 | 404 查页面是否构建/上传;502、503 查 nginx 与后端;000 查 DNS、网络、TLS |
| 耗时 | 多数 0.2~0.4 秒 | 连续多次 > 2 秒 | 看服务器负载、磁盘、nginx error log、网络线路 |
| 证书 | HTTPS 正常完成 | curl 报证书错误 | 看第二层的到期时间与 SAN |
本层判断的是“读者能不能打开”,不是“服务器内部健不健康”。
三、第二层:证书
3.1 命令
certbot certificates | grep -E 'Certificate Name|Expiry Date'
echo | openssl s_client -servername notes.hokachi.top -connect notes.hokachi.top:443 2>/dev/null \
| openssl x509 -noout -dates -subject -ext subjectAltName
systemctl list-timers --all --no-pager | grep -i certbot
3.2 参数拆解
certbot certificates:列出 certbot 管理的所有证书,包括名称、覆盖域名、到期时间、剩余有效天数和文件路径。
grep -E 'Certificate Name|Expiry Date':
-E:使用扩展正则表达式,才能让|表示“或”;- 这里只保留含
Certificate Name或Expiry Date的行,减少无关输出。
openssl s_client:
-servername notes.hokachi.top:发送 SNI,让服务器返回对应域名的证书;不写可能拿到默认证书;-connect notes.hokachi.top:443:连接目标主机和端口;echo |:向 openssl 输入一个空行,让握手流程完整结束,否则命令可能一直等待输入;2>/dev/null:丢弃 stderr 里的握手过程噪音;| openssl x509:把拿到的证书交给 x509 子命令解析。
openssl x509:
-noout:不打印完整 PEM 证书体;-dates:输出notBefore和notAfter;-subject:输出证书主体(通常是 CN);-ext subjectAltName:输出 SAN,即证书实际覆盖的域名列表。
systemctl list-timers --all --no-pager:见第三层。
3.3 正常 / 异常 / 先查什么
| 项目 | 正常 | 异常 | 异常时先查什么 |
|---|---|---|---|
| 剩余天数 | 大于 30 天 | 小于 30 天预警,小于 14 天必须处理 | certbot renew --dry-run 是否成功(该演练本轮未执行) |
| 覆盖域名 | notes.hokachi.top 与 www.hokachi.top | 缺少其中一个 | 签发时的 -d 参数、证书 SAN |
| 到期日 | 与上次续期后明显推进 | 多次检查日期不变 | certbot.timer 是否 active、certbot.service 日志 |
| 链验证 | 浏览器与 curl 均正常 | 报证书过期/不受信任 | 系统时间、证书链、SNI |
四、第三层:服务状态
4.1 命令
systemctl is-active nginx
systemctl is-enabled nginx
systemctl status nginx --no-pager
systemctl is-active certbot.timer
systemctl is-enabled certbot.timer
systemctl status certbot.timer --no-pager
systemctl list-timers --all --no-pager | grep -i certbot
systemctl is-active fail2ban
systemctl is-enabled fail2ban
systemctl is-active ssh
nginx -t
4.2 is-active、is-enabled、status、list-timers 的区别
| 命令 | 回答的问题 | 典型输出 |
|---|---|---|
systemctl is-active <unit> | 现在是否在运行 | active、inactive、failed |
systemctl is-enabled <unit> | 开机时是否自动启动 | enabled、disabled、masked |
systemctl status <unit> | 综合状态:描述、加载路径、运行时间、最近日志 | 多行详情 |
systemctl list-timers --all | 所有定时器及上次/下次触发时间 | 表格 |
几个细节:
is-active只回答当前运行状态,不代表开机自启;is-enabled只回答自启配置,不代表现在正在运行。两者要一起看。status默认会调用分页器,脚本或窄终端里容易卡住,所以加--no-pager,让它一次性输出。list-timers默认只显示还会再次触发的定时器;加--all才能看到已经停止或不活跃的定时器。nginx -t只做配置语法检查,不会启动、停止或重载 nginx。
4.3 正常 / 异常 / 先查什么
| 项目 | 正常 | 异常 | 异常时先查什么 |
|---|---|---|---|
| nginx | active、enabled、nginx -t 成功 | inactive、failed、配置测试失败 | systemctl status nginx、nginx -t 的具体报错行 |
| certbot.timer | active (waiting)、enabled,有下次触发时间 | inactive、masked、无下次触发 | systemctl status certbot.timer、journalctl -u certbot.timer |
| fail2ban | active、enabled | inactive、failed | systemctl status fail2ban、fail2ban-client status |
| SSH | ssh 与 sshd 均为 active | 任一异常 | 控制台/救援模式,避免直接断掉远程连接 |
五、第四层:访问控制
5.1 命令
ufw status numbered
fail2ban-client status sshd
ss -lntp
5.2 参数拆解
ufw status numbered:
status:显示防火墙状态和规则;numbered:给每条规则加序号,便于后续按序号删除或调整。
fail2ban-client status sshd:
fail2ban-client:fail2ban 的管理客户端;status:查看运行概况;sshd:指定 jail 名称。只写status会列出所有 jail。
ss -lntp 四个字母:
| 参数 | 含义 |
|---|---|
-l | 只显示处于 LISTEN(监听)状态的套接字 |
-n | 以数字显示地址和端口,不解析成服务名 |
-t | 只显示 TCP |
-p | 显示占用端口的进程(需要 root 才能看到别人的进程) |
5.3 正常 / 异常 / 先查什么
| 项目 | 正常 | 异常 | 异常时先查什么 |
|---|---|---|---|
| ufw | Status: active,只放行 22/80/443(IPv4 与 IPv6) | 出现未知端口放行、防火墙 inactive | 规则是否被误加、是否有其他防火墙层 |
| fail2ban | active,Currently banned 为 0 或少量 | banned 突然增多、jail 消失 | fail2ban-client status、/var/log/fail2ban.log |
| 监听端口 | 22、80、443 对外;53 与 6010 仅本机 | 出现未知的 0.0.0.0 监听 | ss -lntp 的进程名、systemctl status 对应服务 |
ss 只是“看谁在监听”,它不改变任何策略;真正决定“谁能进来”的是 ufw 与云厂商安全组。
六、第五层:机器健康
6.1 命令
uptime
nproc
df -h /
df -i /
free -m
ps aux --sort=-%mem | head -6
6.2 参数拆解
uptime:输出当前时间、已运行时长、登录用户数,以及 1、5、15 分钟平均负载。
nproc:输出可用 CPU 核心数。负载要和它对比,单看负载数字没有意义。
df -h / 与 df -i /:
| 命令 | 看什么 | 单位 |
|---|---|---|
df -h / | 根分区的磁盘块使用率 | -h 人类可读(G/M) |
df -i / | 根分区的 inode 使用率 | 个数 |
磁盘满和 inode 满都会导致写不进去文件,但原因不同:小文件极多时,磁盘还有空间,inode 可能先用完。
free -m 的各列:
| 列 | 含义 |
|---|---|
total | 总内存 |
used | 已使用 |
free | 完全空闲 |
shared | 共享内存 |
buff/cache | 缓存与缓冲区,可被回收 |
available | 估算的可用内存,新进程真正能拿到的量,优先看这一列 |
ps aux --sort=-%mem | head -6:
a:所有用户的进程;u:以用户友好格式显示;x:包含没有终端的进程;--sort=-%mem:按内存占用百分比降序,-表示倒序;head -6:表头 + 前 5 个进程。
6.3 正常 / 异常 / 先查什么
| 项目 | 正常 | 异常 | 异常时先查什么 |
|---|---|---|---|
| 负载 | 长期低于核数 | 15 分钟负载持续高于核数 | top、慢查询、备份任务、异常进程 |
| 磁盘 | 小于 80% | 大于 80% 预警,大于 90% 危险 | 大日志、缓存、未清理的备份 |
| inode | 小于 80% | 大于 80% | 小文件数量、会话文件、临时文件 |
| 内存 | available 充足 | 小于 200MB 预警,小于 100MB 危险 | 前几名进程、是否被 OOM kill |
| Swap | 有 swap 或确实不需要 | 无 swap 且内存吃紧 | dmesg 中的 OOM 记录 |
七、第六层:日志与异常流量
7.1 SSH 失败登录
journalctl -u ssh --since "24 hours ago" --no-pager | grep -ciE 'invalid user|failed password|authentication failure|maximum authentication attempts'
grep -ciE 'invalid user|failed password|authentication failure' /var/log/auth.log
参数:
journalctl -u ssh:只看ssh.service这个单元的日志;--since "24 hours ago":时间窗口为最近 24 小时;也支持"3 days ago"这类写法;--no-pager:不分页,适合管道和脚本;grep -c:统计匹配的行数,不是匹配次数;-i:忽略大小写;-E:扩展正则,使|表示多个关键词之一。
7.2 nginx 4xx / 5xx
先确认状态码在第 9 列:
awk '{print $1, $9}' /var/log/nginx/access.log | head -5
输出示例(第一列是客户端 IP,第二列是状态码):
39.105.14.55 "-"
45.198.224.125 404
39.105.14.55 404
再用 $9 统计当前日志文件:
awk '$9>=400 && $9<500 {c4++} $9>=500 && $9<600 {c5++} END {print c4+0, c5+0}' /var/log/nginx/access.log
awk 里的 $9 就是 access log 按空格切分后的第 9 列,即 HTTP 状态码。注意这个写法只统计单个文件;如果要跨轮转文件统计近 24 小时,需要按日志里的时间字段过滤,不能简单相加。
7.3 日志目录大小
du -sh /var/log
-s:只汇总总大小,不逐个列出子目录;-h:人类可读单位。
7.4 正常 / 异常 / 先查什么
| 项目 | 正常 | 异常 | 异常时先查什么 |
|---|---|---|---|
| SSH 失败 | 几百次/天属常见扫描 | 超过基线 2 倍或短时突增 | 来源 IP、fail2ban 是否封禁 |
| 5xx | 接近 0 | 持续出现 | nginx error log、后端服务、磁盘是否满 |
| 4xx | 有一定比例,多为扫描 | 超过基线 2 倍或占比过高 | 主要 404 路径,是否出现批量探测 |
/var/log | 百 MB 级 | 数百 MB 且快速增长 | 日志轮转配置、是否有服务疯狂报错 |
4xx 高不等于站点坏了。公网上的扫描器会不断请求不存在的路径,这部分请求会稳定存在,重点看趋势和突增。
八、第七层:内容完整性
8.1 命令
echo IP_COUNT=$(grep -o "206.187.208.43" /var/www/notes/index.html | wc -l)
echo DOMAIN_COUNT=$(grep -o "notes.hokachi.top" /var/www/notes/index.html | wc -l)
参数:
grep -o:只输出匹配到的文本,每处一行,而不是输出整行;wc -l:统计行数,也就是出现次数;IP_COUNT必须为 0;DOMAIN_COUNT必须大于 0。
8.2 为什么看这两个数字
站点构建时会把 baseURL 写进所有绝对链接。如果 baseURL 误写成服务器 IP,线上首页就会生成大量 http://206.187.208.43/... 链接:
- 读者点击会 404;
- HTTPS 证书与 IP 不匹配;
- 搜索引擎可能收录错误地址。
因此 IP_COUNT=0 是硬性要求,DOMAIN_COUNT>0 代表链接使用域名生成。
8.3 正常 / 异常 / 先查什么
| 项目 | 正常 | 异常 | 异常时先查什么 |
|---|---|---|---|
| IP 计数 | 0 | 大于 0 | config.toml 的 baseURL、是否重新构建并发布 |
| 域名计数 | 大于 0 | 0 或明显下降 | 构建配置、上传是否完整、首页模板 |
| 页面数量 | 与内容目录大致一致 | 明显减少 | public/ 是否残留旧产物、是否漏上传 |
九、2026-11-08 实测基线
以下数值是 2026-11-08 06:24 UTC 左右的一次真实采集,用于建立对照。这些数字会随访问量、日志轮转、系统负载变化,不能当成永久标准;只有量级和阈值有参考意义。
9.1 可达性
| URL | 状态码 | 总耗时 |
|---|---|---|
/ | 200 | 0.390634s |
/internal/ncat-reverse-shell/ | 200 | 0.249803s |
/linux/ssh-hardening-practice/ | 200 | 1.432453s |
/contact/ | 200 | 0.229885s |
/favicon.svg | 200 | 0.252819s |
9.2 证书
Certificate Name: notes.hokachi.top
Expiry Date: 2027-02-04 16:13:14+00:00 (VALID: 88 days)
notBefore=Nov 6 16:13:15 2026 GMT
notAfter=Feb 4 16:13:14 2027 GMT
SAN: DNS:notes.hokachi.top, DNS:www.hokachi.top
下次触发: 2026-11-08 08:00:45 UTC
上次触发: 2026-11-07 14:34:13 UTC
9.3 服务与访问控制
nginx: active;nginx -t 成功
certbot.timer: active (waiting)、enabled
fail2ban: active、enabled
ssh / sshd: active / active
ufw: active;放行 22、80、443(IPv4 与 IPv6)
fail2ban sshd: Currently failed 9;Total failed 258;Currently banned 0;Total banned 15
监听端口: 22、80、443 对外;53、127.0.0.1:6010 仅本机
9.4 机器健康
uptime: up 2 days, 20:09,load average 0.00 / 0.00 / 0.00
nproc: 2
df -h /: 29G 总量,2.3G 已用,27G 可用,8%
df -i /: 3870720 inodes,105512 已用,3%
free -m: total 1977;used 280;free 410;buff/cache 1286;available 1502
Swap: 0
内存前 5: systemd-journald 2.8%、snapd 1.8%、multipathd 1.3%、fail2ban-server 1.1%、unattended-upgrade 0.9%
9.5 日志与异常流量
SSH 失败类日志(24 小时,journal): 356
SSH 失败类日志(当前 auth.log): 138
nginx 近 24 小时: 总请求 2776;4xx 987;5xx 0
当前 access.log(非 24 小时): 4xx 385;5xx 0
4xx 主要路径: 404 "/" 62 次;400 无法解析 37 次;404 "/favicon.ico" 24 次;400 "/" 22 次;405 "/" 12 次
/var/log 总大小: 102M
9.6 内容完整性
IP_COUNT=0
DOMAIN_COUNT=29
9.7 时间同步
Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: no
NTP service: active
timesync-status: Offset +15.545ms;IPv6 NTP 服务器可用;IPv4 NTP 请求多次超时
这些数字的意义是“当前这个站点的正常量级”,不是所有服务器的通用标准。
十、三个实操陷阱
10.1 PowerShell 里 curl 和 curl.exe 不是一回事
在本机 Windows PowerShell 5 中实测:
Get-Command curl
# Name: curl
# CommandType: Alias
# Definition: Invoke-WebRequest
也就是说,直接输入 curl 调用的是 PowerShell 的 Invoke-WebRequest 别名,不是真正的 curl。它的参数体系完全不同:
-s、-o NUL、-w这些 curl 参数在Invoke-WebRequest上不存在;- 同样一条命令,写成
curl ...可能报“找不到参数”,让人误以为网络有问题。
而:
Get-Command curl.exe
# CommandType: Application
# Source: C:\Windows\system32\curl.exe
curl.exe --version
# curl 8.21.0
所以本手册统一写 curl.exe,确保执行的是真正的 curl,输出格式也可控。
10.2 nginx 和 nginx -t 后果不同
nginx -t:只检查配置语法和文件引用,不加载新配置,不影响运行中的服务。- 裸
nginx:尝试启动 nginx 主进程并加载配置。线上已有 nginx 在运行时,它会因为 80/443 端口被占用而报bind() ... failed;如果服务本来是停的,它可能启动一个不受 systemd 管理的进程,后续状态就难以判断。
本次采集过程中曾因引号转义问题误执行过一次裸 nginx,输出多行:
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Unknown error)
当时现有服务没有停止,systemctl is-active nginx 仍是 active,master PID 与启动时间未变。但这只是侥幸没有影响,正确做法是:
- 只检查配置:
nginx -t - 要重载配置:
systemctl reload nginx - 要重启服务:
systemctl restart nginx
说明:
systemctl reload nginx与systemctl restart nginx本轮未实际执行,仅作为正确操作方向列出;执行前应确认变更窗口。
不要把裸 nginx 当成测试命令。
10.3 systemctl is-active 对不存在的单元也打印 inactive
实测:
systemctl is-active no-such-unit-xyz.timer
# inactive
# 退出码 3
这就带来一个坑:如果在一台根本没有安装 certbot 的机器上执行 systemctl is-active certbot.timer,它同样会输出 inactive。看起来像“服务停了”,实际是“没有这个单元”。
判断方法:
hostname
systemctl status certbot.timer --no-pager
hostname确认你连的是不是目标服务器;systemctl status对不存在的单元会明确显示could not be found,对真实存在但停止的单元会显示inactive (dead),两者可以区分。
另外,is-active 的退出码也能辅助判断:0 表示 active,非 0 表示不是 active;脚本里不要只解析文本。
十一、ufw、fail2ban、curl 的职责边界
| 工具 | 管什么 | 不管什么 | 典型命令 |
|---|---|---|---|
ufw | 管“谁能连进来”:按端口和来源放行/拒绝,是常驻的包过滤策略 | 不分析登录行为,不会因为某人失败多次就自动封禁 | ufw status numbered |
fail2ban | 管“谁敲门太多次”:读日志,发现重复失败后临时封 IP | 不替代 ufw,不负责常规端口放行;规则通常由它自己写入防火墙 | fail2ban-client status sshd |
curl | 只是一个访问工具:发请求、看响应 | 不做任何拦截、封禁或策略控制 | curl.exe -s -o NUL -w "%{http_code}" URL |
可以这样记:
- ufw 是门禁:决定哪些门常开。
- fail2ban 是保安:看到有人反复撬锁,就临时把人拉黑。
- curl 是访客:只是去敲门,然后告诉你门开没开、等了多久。
本次基线中,ufw 放行 22/80/443;fail2ban 只启用了 sshd jail,当前封禁 0 个 IP;curl 只负责外部可达性验证。
十二、系统时间与 TLS 证书
TLS 证书有两个时间字段:
notBefore:证书生效时间;notAfter:证书到期时间。
浏览器和 curl 在握手时,会用本机或服务器的系统时间去判断“当前是否落在有效期内”。如果系统时间偏差过大:
- 证书可能被判定为“尚未生效”或“已过期”;
- HTTPS 握手失败,外部巡检会看到证书错误;
- ACME 签发/续期的签名与校验也可能失败;
- 日志时间错乱,排查事件时对不上先后顺序。
查看时间状态:
timedatectl
timedatectl timesync-status
journalctl -u systemd-timesyncd --since "3 days ago" --no-pager | tail -12
timedatectl 的关键字段:
| 字段 | 含义 |
|---|---|
Local time | 本机当前时间 |
Time zone | 时区 |
System clock synchronized | 系统时钟是否被确认同步 |
NTP service | 时间同步服务是否启用 |
RTC in local TZ | 硬件时钟是否按本地时区解释 |
System clock synchronized: no 的含义是:systemd-timesyncd 最近没有确认一次成功同步,不等于“时间一定错了”,也不等于“NTP 服务没开”。本次实测就是:
System clock synchronized: no
NTP service: active
timesync-status: Offset +15.545ms
IPv6 NTP 服务器可用;IPv4 NTP 请求多次超时
偏差只有 15.5 毫秒,证书和日志都不受影响。需要关注的是:
- 偏差持续增大(例如超过 1 秒);
synchronized: no长期不恢复;timesync-status里没有可用服务器或 offset 明显异常。
风险判断:
| 现象 | 风险 |
|---|---|
| 偏差毫秒级 | 基本无影响,记录即可 |
| 偏差秒级 | 日志对时困难,ACME 可能受影响 |
| 偏差分钟级以上 | 证书可能被判无效,续期与握手可能失败 |
| 时间跳变 | 定时器触发时间可能偏移,需检查 list-timers |
本次证书剩余 88 天,certbot.timer 状态正常,时间偏差毫秒级,因此 synchronized: no 目前只是一个待观察项,不构成证书失守风险。
十三、检查清单
每天 1 分钟
- 五个关键 URL 全部返回 200,耗时在正常量级
-
certbot.timer为active,且有下次触发时间 -
nginx、fail2ban、ssh均为active - 首页
IP_COUNT=0、DOMAIN_COUNT>0 - 证书剩余天数没有突然下降
每周 5 分钟
-
df -h /小于 80%,df -i /小于 80% -
free -m的available没有逼近危险线 -
uptime负载没有持续高于nproc -
fail2ban-client status sshd的 banned 数量没有异常增长 - nginx 5xx 仍接近 0,4xx 没有明显突增
- SSH 失败次数没有达到基线 2 倍
-
/var/log没有异常膨胀 -
timedatectl时间偏差正常 - 需要时做一次
certbot renew --dry-run(本轮未执行,属建议演练)
十四、命令速查块
本地 Windows PowerShell
cd d:\ProgramFilesFolder\Project\PersonalNotesBlog\blog-hugo
$urls = @(
'https://notes.hokachi.top/',
'https://notes.hokachi.top/internal/ncat-reverse-shell/',
'https://notes.hokachi.top/linux/ssh-hardening-practice/',
'https://notes.hokachi.top/contact/',
'https://notes.hokachi.top/favicon.svg'
)
foreach ($u in $urls) {
$r = curl.exe -s -o NUL -w "%{http_code} %{time_total}" $u
Write-Output "$r $u"
}
服务器
# 证书
certbot certificates | grep -E 'Certificate Name|Expiry Date'
echo | openssl s_client -servername notes.hokachi.top -connect notes.hokachi.top:443 2>/dev/null \
| openssl x509 -noout -dates -subject -ext subjectAltName
# 服务
systemctl is-active nginx fail2ban ssh
systemctl is-enabled nginx fail2ban
systemctl list-timers --all --no-pager | grep -i certbot
nginx -t
# 访问控制
ufw status numbered
fail2ban-client status sshd
ss -lntp
# 机器健康
uptime
nproc
df -h /
df -i /
free -m
ps aux --sort=-%mem | head -6
# 日志与攻击面
journalctl -u ssh --since "24 hours ago" --no-pager | grep -ciE 'invalid user|failed password|authentication failure'
awk '$9>=400 && $9<500 {c4++} $9>=500 && $9<600 {c5++} END {print c4+0, c5+0}' /var/log/nginx/access.log
du -sh /var/log
# 内容完整性
echo IP_COUNT=$(grep -o "206.187.208.43" /var/www/notes/index.html | wc -l)
echo DOMAIN_COUNT=$(grep -o "notes.hokachi.top" /var/www/notes/index.html | wc -l)
# 时间同步
timedatectl
timedatectl timesync-status
说明:以上命令均来自 2026-11-08 的真实执行记录。
awk那条只统计当前access.log,不等于“近 24 小时”;要统计 24 小时需按日志时间字段过滤access.log与access.log.1。本文没有给出未验证的跨文件统计脚本。