尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Linux uptime 与系统运行时间:重启排查及监控采集

发布时间:2026/9/29 1:01:08

资讯中心
01
ARTICLE

Linux uptime 与系统运行时间:重启排查及监控采集

Linux uptime 与系统运行时间:重启排查及监控采集
凌晨两点被电话叫醒SSH 登进机器敲下第一条命令十有八九是uptime。屏幕上回一行02:13:47 up 187 days, 14:22, 3 users, load average: 0.08, 0.11, 0.09绝大多数人扫一眼 load average 那三个数觉得不高就转头去翻应用日志了。但前面那半截up 187 days, 14:22其实信息量更大——它直接告诉你这台机器上一次启动是什么时候结合你自己记忆里的发布窗口一眼就能判断这次是不是非计划内的重启。很多应用莫名其妙变慢的案子最后都追到机器其实半夜重启过缓存全冷上。这篇就把 Linux 查看系统运行时间这件事从表层讲到里层uptime那一行每个字段的来历、/proc下面几个数据源的精度差别、容器和云主机里为什么数字会骗人、脚本里怎么把秒数换算成人能读的格式、以及机器是不是偷偷重启过该怎么一层层查下去。刚接触 Linux 的同学能拿到一套能直接抄的命令写监控采集的开发者能避开几个经典坑被容器里uptime显示几百天坑过的人也能找到原因。1. 从 uptime 一行输出里能读出哪些信息1.1 四个字段逐段拆开看拿上面那行输出举例从左到右是四块完全不同的东西字段示例值含义数据来源当前时间02:13:47执行命令那一刻的系统墙上时间系统时钟运行时长up 187 days, 14:22自上次内核启动至今经过的时间/proc/uptime登录会话3 users当前 utmp 里的登录会话条数/run/utmp平均负载0.08, 0.11, 0.09最近 1/5/15 分钟的 runnable D 状态进程平均数内核 loadavg有几个细节值得单独说。3 users统计的是会话数而不是用户数同一个人开三个终端就是 3一台只跑服务的机器这里通常是 0。load average在 Linux 上把TASK_UNINTERRUPTIBLE也就是ps里 D 状态的进程典型的是卡在磁盘 IO 上的进程也算进去了这一点和很多传统 Unix 不一样所以磁盘慢的时候 load 一样会飙哪怕 CPU 是空的。还有一个常被忽略的点load average 是整机维度的不分核。一台 2 核机器 load 2.0 和一台 32 核机器 load 2.0含义完全不同。要判断负载高低得先nproc拿到核数再除。1.2 -p、-s、-V 三个参数的取舍procps-ng 版本的uptime带几个实用参数可惜很多人不知道uptime -p # up 3 days, 2 hours, 15 minutes uptime -s # 2024-05-01 09:12:33 uptime -V # uptime from procps-ng 3.3.17-p把运行时间翻译成3 天 2 小时 15 分钟这种人话适合贴在值班通报里。-s直接打出开机时刻等价于读/proc/stat里的btime再格式化它不是去读 wtmp所以哪怕 wtmp 被清了它照样有输出。注意-p的输出走 gettext 本地化在中文 locale 下会变成中文。任何脚本都别去解析它的字符串换了语言环境就崩了。还有一个现实问题-p和-s是 procps-ng 3.3.10 之后才有的BusyBox 自带的uptime完全不支持这两个参数很多精简容器镜像、路由器固件、嵌入式系统里跑的就是 BusyBox。写脚本前先uptime --version确认一下别写出只能在你自己机器上跑的代码。1.3 直接解析 uptime 输出为什么是个坏主意我见过太多这样的脚本uptime | awk {print $3, $4, $5}它在机器跑了好几天的时候碰巧能work但只要运行时间掉到一天以内字段位置就全错位了运行时长uptime 输出片段awk $3 $4 $5 拿到的东西187 天up 187 days, 14:22, 3 users187 days, 14:22,3 小时up 3:15, 1 user, load3:15, 1 user, load5 分钟up 5 min, 1 user, load5 min, 1 user, load不足 1 分钟up 0 min, 1 user, load0 min, 1 user, load注意最后两行——运行时间不足一小时的时候uptime会退化成up 5 min这种格式连冒号都没有不到一分钟干脆显示up 0 min秒数彻底丢失。你按固定字段位置去切必然踩雷。更稳的路子是绕开uptime这个命令本身直接读内核暴露的文件。uptime、w、top第一行本质上都是从同一个地方取数然后排版你完全可以自己做排版。2. 运行时间的四条取数路径与精度对照2.1 /proc/uptime唯一带小数的那个来源cat /proc/uptime # 16184523.47 64592318.12两个数字空格分隔。第一个是系统启动至今经过的秒数带两位小数也就是 10 毫秒精度——这是所有方式里精度最高的。第二个是所有 CPU 的累计空闲时间注意是累加值。这里有个经典误解很多人把它当空闲百分比用。在一台 4 核机器全空闲的情况下第二个数会接近第一个数的 4 倍。想要一个平均空闲率得这么算read -r up idle /proc/uptime awk -v u$up -v i$idle -v n$(nproc) \ BEGIN{printf 开机以来平均空闲率: %.2f%%\n, i/(u*n)*100}但要清楚这算的是从开机到现在的平均不是当前瞬时值。一台机器上午被压满、下午全闲这个数字照样是五十几。要看瞬时 CPU还是top、vmstat、mpstat。内核侧对应的实现是ktime_get_boottime_ts64()也就是CLOCK_BOOTTIME这个时钟。它的特点是把系统挂起suspend to RAM / suspend to disk的时间也算进去。老版本内核大约 5.x 之前的一段时间这里用的是CLOCK_MONOTONIC不含挂起时间所以同一台笔记本合盖一天再打开新老内核给出的uptime数字是不一样的。这个差别在服务器上一般看不出来但在笔记本、边缘盒子上会很直观。2.2 /proc/stat 的 btime 与 sysinfo 系统调用awk /^btime/{print $2} /proc/stat # 1714525953 date -d 1714525953 # 2024-05-01 09:12:33btime是开机那一刻的墙上时间的 Unix 时间戳精度只有整秒。uptime -s打印的就是它。另一条路是sysinfo(2)系统调用返回的struct sysinfo里有个uptime字段单位是秒#include sys/sysinfo.h #include stdio.h int main(void) { struct sysinfo si; if (sysinfo(si) ! 0) { return 1; } printf(uptime %ld s\n, si.uptime); return 0; }这两条路都要留意几个坑。sysinfo的uptime是整秒截断的别指望它给你小数。btime则是内核拿当前墙上时钟减去开机以来经过的时间反推出来的——如果机器启动的时候没有可用 RTC或者 RTC 电池没电、时间飘得离谱那btime一开始就是错的。等 NTP 把系统时间拉回正轨之后btime的读数会不会跟着变不同内核版本表现并不一致我实测过同一个大版本的不同小版本上就有差异。所以拿btime做跨机器的精确比对心里得留个底。2.3 utmp/wtmp 那条路who -b 与 last reboot 为什么经常失准who -b # 系统引导 2024-05-01 09:12 last -x reboot | head -5 # reboot system boot 5.15.0-91-generic Wed May 1 09:12 still runningwho -b读的是/run/utmp以前是/var/run/utmp现在/var/run基本都软链到/run而/run是 tmpfs记录类型是BOOT_TIME。这条记录由systemd-update-utmp或者老式的 sysvinit 在启动流程里写进去。last reboot读的是/var/log/wtmp能翻出历史记录所以更常用于回溯。问题是这两条路都依赖记录确实被写下来了而这在下面几种场景里不成立容器里的/run/utmp和/var/log/wtmp通常是打镜像时留下的静态文件who -b会告诉你系统引导于 2023-08-15那是造镜像那天。极简系统为了省事把 utmp 写入服务裁掉了命令直接无输出退出码还是 0脚本里根本发现不了。wtmp被 logrotate 按月轮转默认保留几份就删重启记录跟着一起没了。rootfs 只读的嵌入式设备写不进去。还有个容易忽略的点who -b只保留最近一次启动查不了历史last reboot虽然能给历史但给出的时间受时区、-F参数影响脚本里解析又是一堆活。2.4 四种方式实测对照取数方式数据源精度容器内是否可信外部依赖/proc/uptime 第一列内核 BOOTTIME 时钟10 ms否无uptime -s / /proc/stat btime内核反推1 s否无sysinfo(2)内核1 s否无who -b / last rebootutmp / wtmp1 s否写入服务 可写磁盘把这张表记住结论就一句话只要是要计算、要采集、要监控一律读/proc/uptime第一列。要显示成人话再自己格式化who和last只在人肉排查历史的时候用。3. 容器、云主机、嵌入式设备上 uptime 为什么会骗人3.1 容器共享内核你看到的是宿主机的运行时间/proc/uptime从来就不是被 namespace 隔离的资源。你在 Docker 或 K8s 的 Pod 里执行cat /proc/uptime拿到的是宿主机内核从启动到现在的秒数。验证方法特别简单同一台宿主机上起两个容器docker run --rm alpine cat /proc/uptime # 16204893.12 65332110.44 docker run --rm ubuntu cat /proc/uptime # 16204893.15 65332114.88数字一模一样第二列的空闲时间会有微小差异因为中间隔了几十毫秒。这就是最快的判断依据。顺便说uptime那一行里的用户数在容器里也很迷。它读的是/run/utmp而容器里这个文件通常是镜像自带的写于构建时刻跟当前会话毫无关系。last reboot同理。那容器里想知道容器本身跑了多久怎么办几个可选方案ps -o etimes -p 1——PID 1 的存活秒数只要容器主进程没被换掉这就是容器启动时长。Kubernetes 里kubectl get pod pod -o jsonpath{.status.startTime}。Docker 里docker inspect -f {{.State.StartedAt}} container。例外情况是 LXC/LXD。它通过 lxcfs 把伪造过的/proc/uptime、/proc/stat挂进容器这样容器里看到的才是自己的数字。Docker 默认不做这件事所以别指望。3.2 虚拟化场景下的暂停、快照与在线迁移虚拟机这块有几个会让uptime数字跳变的场景遇到了别慌挂起恢复。笔记本合盖、企业里给测试 VM 做 suspend to disk。因为/proc/uptime现在用的是 BOOTTIME 时钟恢复之后数字会一次性往前跳把挂起那段时间补齐。如果你看到监控曲线在某个时间点整个台阶式上移多半是这个原因。快照回滚。把一台跑了 100 天的机器回滚到 30 天前的快照uptime会退回到那天的值btime也会跟着退回去。这种回滚最麻烦的地方在于系统内部数据是自洽的——/proc/uptime和/proc/stat的btime加一下正好等于当前时间——但你外部监控系统记录的最后一次重启时间跟它对不上。所以判断快照回滚光看机器内部是看不出来的必须拿外部记录比。在线迁移。迁移期间 guest 会有很短的停机毫秒到秒级现代虚拟化的时钟源比如 kvm-clock会跟着宿主机走正常情况只会看到很小的台阶。但如果迁移过程中时钟同步出了问题可能会看到几个小时的偏移这时候要去看 guest 的dmesg里有没有clocksource相关的告警。3.3 嵌入式与老设备上的精度和计数回绕问题维护边缘盒子、路由器、工控机的人会碰到一些服务器上遇不到的情况BusyBox 的精简。BusyBox 的uptime只输出标准那一行没有-p、-s、-V。有些版本的 BusyBox 连w都没有。写采集脚本时只能老老实实读/proc/uptime。没有 RTC 的设备。部分 ARM 开发板、路由器开机时系统时间是 1970 或者内核编译时间等 NTP 同步完才纠正。这种机器上btime完全不可信但/proc/uptime依然准因为它走的是单调时钟跟墙上时间无关。这也是为什么我一直推荐用/proc/uptime。32 位 jiffies 回绕的历史遗留。32 位系统上 jiffies 是 32 位的HZ100时大约 497 天回绕一次HZ1000时大约 49.7 天回绕一次。这在上古内核上出过不少奇怪的计时 bug。现在主流的 64 位内核用 64 位 jiffies基本不用担心。但如果手上还有跑了十年没重启的老设备遇到某天开始定时任务集体错乱这种玄学问题可以把这条列进怀疑清单。从/proc/uptime读数的原子性。内核文件一般一次读就能拿全但用read内建或者head的时候偶尔会遇到只读到一半的情况。稳妥点用一次cat或者一次read把整行吃下来。4. 把秒数变成能看懂的格式脚本与代码实现4.1 Shell 版本的换算与几个边界坑最直白的写法直接读内核文件不碰uptime命令#!/bin/bash read -r up _ /proc/uptime up_int${up%.*} # 去掉小数部分 d$(( up_int / 86400 )) h$(( up_int % 86400 / 3600 )) m$(( up_int % 3600 / 60 )) s$(( up_int % 60 )) printf up %d days, %02d:%02d:%02d\n $d $h $m $s几个容易翻车的点${up%.*}在字段没有小数点的时候不会报错会原样返回所以不用担心/proc/uptime的格式变动。read -r up _里的_是个合法的变量名用来吃掉第二个字段。不加-r的话反斜杠会被转义虽然这个文件里不会有反斜杠但养成习惯没坏处。别写成cat /proc/uptime | awk ...多做一次 fork 不说管道还可能把内核文件的一次性读取拆成两次。bash 的$(( ))是有符号 64 位用来算运行秒数绰绰有余一百万年都不会溢出。printf的%02d只是为了对齐好看。如果结果要拼进 JSON记得别把冒号带进去。给监控采集用的 JSON 版本read -r up idle /proc/uptime printf {uptime_seconds:%s.%s,idle_seconds:%s.%s}\n \ ${up%.*} ${up#*.} ${idle%.*} ${idle#*.}用${var%.*}和${var#*.}把整数部分和小数部分拆开再拼回去是为了在不停用浮点运算的前提下保留原始精度。这个技巧在 shell 里拼 JSON 时很好用。4.2 Python/Go/Node 里拿运行时间的正确姿势Python直接调用 POSIX 时钟不需要读文件import time # 含系统挂起时间和 /proc/uptime 第一列对应 boottime time.clock_gettime(time.CLOCK_BOOTTIME) # 不含挂起时间 monotonic time.clock_gettime(time.CLOCK_MONOTONIC) # 反推开机那一刻的墙上时间 boot_epoch time.time() - boottime print(fuptime{boottime:.2f}s boot_epoch{boot_epoch:.0f})注意time.monotonic()返回的是一个起点未定义的值在 Linux 上它就是CLOCK_MONOTONIC只能用来算差值千万别当成 uptime 用。Java 里ManagementFactory.getRuntimeMXBean().getUptime()返回的是JVM 自己的运行时间不是操作系统运行时间。这个坑我见过太多次了尤其在容器里排查问题时一看 JVM uptime 只有几分钟就以为机器刚重启其实只是应用刚重启。想知道 OS uptime老老实实读/proc/uptime。Go版本package main import ( fmt os strconv strings time ) func main() { data, err : os.ReadFile(/proc/uptime) if err ! nil { panic(err) } fields : strings.Fields(string(data)) sec, _ : strconv.ParseFloat(fields[0], 64) d : time.Duration(sec * float64(time.Second)) fmt.Println(d.Round(time.Second)) // 例如 187d14h22m3s }这个只在 Linux 上有效跨平台项目要用 build tag 分文件其他平台走各自的系统调用。另一个选择是用golang.org/x/sys/unix里的Sysinfo()好处是不依赖文件系统坏处是精度只有秒。Node.js最简单os模块直接给const os require(os) console.log(os.uptime()) // 秒浮点Linux 上等价于 /proc/uptime 第一列4.3 系统运行时间、服务运行时间、进程运行时间别搞混这四个概念特别容易混我整理成一张表想知道什么命令说明操作系统运行了多久awk {print $1} /proc/uptime内核启动至今某个进程活了多久ps -o etimes -p pid单位秒etime是易读格式systemd 服务活跃了多久systemctl show -p ActiveEnterTimestamp unit是进入当前状态的时间可能会变systemd 服务真正启动的时间systemctl show -p ExecMainStartTimestamp unit这个才是不变的容器活了多久ps -o etimes -p 1PID 1 的存活时长JVM 活了多久getRuntimeMXBean().getUptime()不是系统时间ps -o etimes是 procps 的扩展BusyBox 的 ps 大多不支持。这时候可以退回到读/proc/pid/stat的第 22 个字段starttime单位是时钟滴答自己算pid$$ clk$(getconf CLK_TCK) up$(awk {print $1} /proc/uptime) st$(awk {print $22} /proc/$pid/stat) awk -v c$clk -v u$up -v s$st \ BEGIN{printf 该进程已运行 %.0f 秒\n, u - s/c}这段的推导过程值得说一下starttime记录的是进程启动那一刻的系统启动以来经过的滴答数乘以1/CLK_TCK秒就换算成了启动时刻的 uptime再用当前 uptime 一减就是进程存活时长。CLK_TCK一般是 100也就是每滴答 10 毫秒。这个算法不依赖ps的版本在精简系统上特别管用。5. 判断机器是不是偷偷重启过的完整排查链路应用响应变慢了这类模糊故障第一步永远应该是确认机器有没有重启。下面是我自己用的一套三层排查法。5.1 第一层boot_id 与 btime 快照对比内核每次启动都会生成一个新的 UUID放在/proc/sys/kernel/random/boot_idcat /proc/sys/kernel/random/boot_id # 3f2c1a4e-8b9d-4a11-9d3c-7e0f2b6c8a55这个值在同一次启动周期内绝对稳定跨启动基本不会重复随机 UUID 的碰撞概率可以忽略。它比btime更好用的地方在于btime在时钟被调整、快照回滚的时候会跟着变而 boot_id 是纯粹的一次性标识只跟这次内核启动绑定。把它落到磁盘上做快照对比#!/bin/bash STATE/var/lib/uptime-monitor/boot_id mkdir -p $(dirname $STATE) cur$(cat /proc/sys/kernel/random/boot_id) prev$(cat $STATE 2/dev/null) if [ -n $prev ] [ $prev ! $cur ]; then echo [$(date -Iseconds)] 检测到重启新 boot_id$cur旧 boot_id$prev fi printf %s\n $cur $STATE注意STATE一定要放在重启后仍然存在的位置。放在/tmp、/run、/dev/shm这些 tmpfs 上重启后文件就没了脚本永远检测不到变化——我自己就在这上面浪费过半个下午。配合btime做二次确认boot_epoch$(awk /^btime/{print $2} /proc/stat) now$(date %s) echo 已运行 $(( now - boot_epoch )) 秒开机时刻 $(date -d $boot_epoch %F %T)两者对得上基本可以下结论。5.2 第二层journalctl 与 dmesg 里找重启原因确认了确实重启过接下来要回答为什么重启。journalctl --list-boots是第一站journalctl --list-boots # IDX BOOT ID FIRST ENTRY LAST ENTRY # -2 8a1f... Wed 2024-05-01 09:12:31 CST Wed 2024-05-01 09:12:31 CST # -1 3f2c... Wed 2024-05-01 09:12:33 CST Fri 2024-05-03 22:41:08 CST # 0 9d4e... Fri 2024-05-03 22:41:11 CST Sat 2024-05-04 02:13:47 CST关键看两次启动之间的时间差。如果-1这次启动的 LAST ENTRY 是 22:41:08而0的 FIRST ENTRY 是 22:41:11间隔只有 3 秒说明是很快的一次重启。如果-1的 LAST ENTRY 离下一次启动隔了很久那这段时间机器是不通的。再去上一次启动的最后几条日志里翻有没有正常关机journalctl -b -1 --no-pager | grep -i -E Shutting down|Reached target .*Shutdown|systemd-shutdown如果一条都没有基本可以判定是非正常重启——断电、硬复位、宿主机故障、内核 panic 都有可能。看上次启动有没有报错journalctl -b -1 -p warning --no-pager | tail -50 journalctl -k -b -1 -p err --no-pagerlast -x也能交叉验证-x会显示 shutdown、runlevel、reboot 这些非登录记录last -x -F | head -20提示dmesg -T显示的墙上时间是用当前系统时间减去 uptime反推的NTP 校正过时钟之后这些时间会整体漂移。做精确时间对齐时别用它用journalctl -k更靠谱。5.3 第三层内核崩溃、OOM 与硬件告警的痕迹到这一层是在找谁把机器弄挂了。按可能性从高到低排内核崩溃。找Kernel panic、BUG:、Oops这类关键字。前提是 journald 开了持久化/var/log/journal存在否则重启后日志就没了。ls /var/log/journal 2/dev/null echo journal 持久化已开启 grep -i -E Kernel panic|Oops|general protection fault /var/log/messages* 2/dev/nullOOM。内存打满之后 OOM killer 动手通常杀几个进程就完事但如果被杀的是关键进程再加上看门狗就会导致整机重启。journalctl -k -b -1 --no-pager | grep -i -E Out of memory|oom-kill|Killed process看门狗。硬件看门狗或者 systemd 的RuntimeWatchdogSec超时后会强制复位这种重启在日志里往往啥都看不到因为日志还没来得及刷盘。systemctl show -p RuntimeWatchdogUSec grep -i watchdog /etc/systemd/system.conf硬件层。服务器的带外管理日志里会有掉电、内存 ECC 错误、温度超限的记录ipmitool sel list | tail -20云主机。控制台上的宿主机维护事件、实例重启记录这些在系统内部完全看不到必须去控制台翻。最后把现象和原因对应起来方便快速定位现象更可能的原因下一步看什么两次 boot 之间没有 shutdown 记录间隔很短断电、硬复位、宿主机故障IPMI SEL、云控制台事件有 panic / Oops 记录内核崩溃完整调用栈、最近装过的驱动有 oom-kill 且随后重启OOM 触发看门狗或人为介入内存用量曲线、cgroup 限制有正常的 shutdown target 记录计划内重启、补丁窗口变更管理系统内部数据自洽但和外部记录对不上快照回滚或时钟被调整虚拟化平台快照记录6. 接入监控与告警时容易踩的坑6.1 node_exporter / SNMP / Zabbix 的口径差异各家监控采集运行时间的方式并不统一混用会出问题。node_exporter暴露的是node_boot_time_seconds也就是开机时刻的 Unix 时间戳不是运行时长。要算 uptime 得自己减time() - node_boot_time_seconds它底层读的是/proc/stat的btime或者sysinfo()精度是秒级。想让精度更高得自己写 textfile collector 从/proc/uptime抓。Zabbix有system.uptime秒和system.boottime时间戳两个 key。老的 agent 在部分平台上system.uptime会去读 utmp容器里就会得到一个离谱的值。换平台或者升级 agent 之后建议实际跑一次确认口径。SNMP这个坑最经典。OID1.3.6.1.2.1.1.3.0sysUpTimeInstance的单位是 TimeTicks也就是百分之一秒而且是32 位无符号整数。算一下2^32 / 100 42,949,672.96 秒 ≈ 496.99 天也就是说一台跑满 497 天的设备SNMP 上报的 uptime 会直接回绕归零。网络设备监控里这个现象特别常见某台交换机明明没重启uptime 图表突然从 400 多天掉到几天。解决办法是用snmpEngineTime1.3.6.1.6.3.10.2.1.3.0做交叉验证它的单位是秒2^32 秒约等于 136 年实际不会回绕。不过它只在 SNMPv3 下可用v2c 环境就只能自己在采集侧做累计修正了。snmpget -v2c -c public 10.0.0.1 1.3.6.1.2.1.1.3.0 # DISMAN-EVENT-MIB::sysUpTimeInstance Timeticks: (123456789) 14 days, 6:56:07.896.2 开机耗时的测量systemd-analyze 与 journalctl --list-boots搞清楚机器什么时候重启之后下一个问题通常是这次启动花了多久为什么这么慢。这套工具在 systemd 系统上非常好用systemd-analyze # Startup finished in 2.118s (firmware) 1.204s (loader) 1.972s (kernel) 8.316s (userspace) 13.611s # graphical.target reached after 8.281s in userspace. systemd-analyze blame | head -20 systemd-analyze critical-chain systemd-analyze critical-chain nginx.servicesystemd-analyze的四段耗时分别对应固件、引导加载器、内核、用户空间单位是毫秒级。它的数据来源是内核启动时间戳本质上就是/proc/uptime和 systemd 自己打的点全都是单调时钟不受 NTP 影响所以比dmesg -T靠谱得多。要注意它只反映本次启动看不了历史。想比较多次启动的耗时得自己采集上报。非 systemd 的系统上一个土办法是用dmesg | head的第一条时间戳做粗略估计但那个精度很差只能当参考。6.3 告警阈值怎么定才不至于天天误报用运行时间小于某个阈值来做重启告警是最容易误报的做法。发布窗口一重启告警就响时间长了没人看。我现在的做法是分层groups: - name: host-uptime rules: - alert: HostRebooted expr: (time() - node_boot_time_seconds) 600 for: 2m labels: severity: warning annotations: summary: {{ $labels.instance }} 疑似刚重启确认是否在发布窗口 - alert: HostUptimeTooLong expr: (time() - node_boot_time_seconds) 86400 * 180 for: 1h labels: severity: info annotations: summary: {{ $labels.instance }} 已连续运行超过 180 天建议安排窗口打内核补丁第一层是重启提醒阈值 600 秒、持续 2 分钟能把刚重启这个状态稳住又不会在 uptime 刚好卡在阈值边界时抖动。第二层是低频的合规提醒只做 info不打扰值班。比阈值更稳的做法是直接对 boot_id 变化告警。boot_id 变化是个确定事件阈值只是猜测。做法是在采集侧把 boot_id 作为 label 暴露出来告警规则写成与上一次采集相比 label 变了。这样发布窗口内的重启也能被记录只是通过标签或者静默规则过滤掉噪音。还有两条经验。别把 load average 和 uptime 组合成一个复合表达式做告警低配机器上负载一高就误报而且这两个指标根本不相关。另外如果你们用的是云主机宿主机计划内维护导致实例重启这类事件在系统内部完全无痕只能靠云厂商的事件通知来过滤这一点在做告警抑制的时候一定要考虑进去。最后分享一个我自己用了三年的采集脚本思路就三行核心逻辑从/proc/uptime拿秒数、从/proc/sys/kernel/random/boot_id拿本次启动标识、把两个值按分钟写到远端存储。重启告警基于 boot_id 变化触发运行时长只用来做展示和长期趋势分析。这套逻辑跑了三年多误报次数是零比之前用 uptime 阈值那套省心太多。要真想少加班采集口径选对比调多少次阈值都管用。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。