1. 项目概述:一次RK3588边缘盒子掉线事故的完整还原
RK3588智能边缘盒子在工业现场部署后,连续运行72小时左右出现无规律整机掉线——不是网络中断,不是进程崩溃,而是整个系统突然失去响应:SSH连接断开、串口无输出、Web管理界面无法访问,但电源指示灯常亮,风扇仍在转动。重启后一切正常,日志里却找不到明确的panic或oops痕迹。这种“静默死亡”比蓝屏更让人抓狂,因为它不给你任何线索。我接手这个复盘任务时,第一反应不是查dmesg,而是先确认它是不是被OOM Killer盯上了——因为所有线索都指向内存:RTSP拉流服务持续占用高内存、systemd日志里反复出现unit状态异常、看门狗超时重置前最后几条记录全是内存分配失败。RK3588作为当前主流的AI边缘计算平台,其四核Cortex-A76+四核Cortex-A55大小核架构、6TOPS NPU、双千兆以太网口,本该稳如磐石,但一旦内存管理失序,再强的硬件也撑不过48小时。这次事故不是个例,而是大量基于RK3588部署RTSP视频分析服务的团队正在踩的坑:你以为你在跑YOLOv8,其实你是在给Linux内核的OOM Killer递简历。本文不讲RK3588芯片参数,不堆砌编译命令,只聚焦一个真实问题:当你的RK3588盒子在凌晨三点悄无声息地“死”在产线上,你该从哪一行日志开始读?怎么判断是软件逻辑泄漏,还是systemd配置缺陷,或是硬件看门狗误触发?我会带你逐帧回放整个故障链:从RTSP流解码缓冲区膨胀,到cgroup内存限制失效,再到OOM Killer选择kill哪个进程的底层逻辑,最后落到如何用硬件看门狗做最后一道保险。无论你是嵌入式工程师、AI算法部署人员,还是现场运维,只要你的RK3588盒子连着摄像头,这篇复盘就值得你花20分钟读完。
2. 故障链路拆解:从RTSP拉流到整机静默的五级坍塌
2.1 第一级坍塌:RTSP拉流缓冲区失控(根源起点)
事故始于一个看似无害的GStreamer pipeline:gst-launch-1.0 rtspsrc location=rtsp://10.255.207.85/pltv/888888 ... 000002343740_0.smil latency=100 ! rtph264depay ! h264parse ! omxh264dec ! videoconvert ! appsink。表面看,这是标准的RK3588硬解方案——用omxh264dec调用Rockchip的MPP库,走VPU硬解,CPU占用率应低于15%。但问题出在rtspsrc的默认行为上:它内部维护一个动态增长的接收缓冲区(receive buffer),用于应对网络抖动。在局域网稳定环境下,这个buffer通常维持在2~3MB;但一旦上游RTSP服务器偶发I帧间隔拉长(比如腾讯游戏直播流那种高动态场景),或网络出现微秒级丢包,rtspsrc就会不断扩容buffer,从3MB→12MB→48MB……而GStreamer 1.18.x在RK3588平台上的内存释放机制存在延迟,导致buffer实际占用的物理内存长期不归还。我们用pmap -x <pid>实测发现,单个rtspsrc实例在72小时后内存驻留高达312MB,其中289MB为anon-rss(匿名页),且cat /proc/<pid>/status | grep -E "VmRSS|VmSize"显示VmRSS稳定在300MB以上,说明这不是临时缓存,而是已锁定的物理内存。更致命的是,这个进程由systemd托管,其cgroup路径为/system.slice/gst-rtsp.service,而我们当时配置的MemoryMax=512M——看似充足,却忽略了Linux内存管理的两个关键事实:一是cgroup v2的MemoryMax是软限制,内核在内存压力下会优先回收其他cgroup的页,而非强制oom-kill本cgroup进程;二是RK3588的DDR带宽虽高,但当多个RTSP流并发时,内存碎片化会导致alloc_pages_slowpath频繁触发,进一步加剧延迟。所以第一级坍塌的本质,不是代码写错,而是对GStreamer在嵌入式环境下的内存行为缺乏敬畏——它不像桌面端那样有充足的swap空间兜底,每一MB都是板载LPDDR4X的硬资源。
2.2 第二级坍塌:systemd服务单元状态雪崩(放大器)
当rtspsrc进程吃掉300MB内存后,连锁反应立刻传导至systemd。我们检查journalctl -u gst-rtsp.service -n 100,发现大量Failed to set unit properties on gst-rtsp.service: Connection timed out错误。这不是服务本身的问题,而是systemd manager自身陷入内存饥饿。systemd作为一个用户态init系统,其核心数据结构(unit对象、job队列、cgroup监控句柄)全部驻留在内存中。当系统剩余可用内存跌破128MB(RK3588板载4GB内存,预留512MB给GPU,实际用户可用约3.3GB),systemd的manager_dispatch_signal_fd函数在处理SIGCHLD时因内存分配失败而阻塞,导致整个D-Bus消息总线卡死。此时systemctl status命令会hang住超过30秒,systemctl restart返回Connection timed out,但进程其实仍在运行——这正是“假死”的开端。我们通过strace -p $(pidof systemd) -e trace=memory捕获到关键证据:mmap(NULL, 8392704, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)连续失败17次后,systemd放弃重试,进入低功耗等待状态。更隐蔽的是,systemd默认启用DefaultLimitNOFILE=65536,但在高并发RTSP场景下,每个流会打开至少8个文件描述符(TCP socket、UDP socket、decoder device node、v4l2 capture node等),16路流就突破10万FD上限,触发Too many open files错误,而该错误被systemd静默吞掉,仅在/var/log/messages留下一行kernel: audit: type=1300 audit(1712345678.123:456): arch=cortex_a76 syscall=openat success=no exit=-24 a0=ffffff9c a1=0000000000a1b2c3 a2=0000000000000002 a3=0000000000000000 items=1 ppid=1 pid=1234 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="gst-launch-1.0" exe="/usr/bin/gst-launch-1.0" key=(null)。这种“静默失败”让运维人员误判为网络问题,反复检查交换机端口,却不知真正的敌人在内存子系统。
2.3 第三级坍塌:OOM Killer的误判与执行(临界点)
当systemd卡死后,系统并未立即崩溃,而是进入一个危险的“灰色地带”:内核仍能响应中断,但用户态几乎无法调度。此时/proc/meminfo显示MemAvailable: 42MB,/sys/fs/cgroup/memory/system.slice/memory.usage_in_bytes显示521234567(521MB),已超MemoryMax设定值。按理说OOM Killer该出手了,但它没有kill掉那个占300MB的rtspsrc,而是选择了/usr/lib/systemd/systemd-journald——一个仅占45MB内存的日志服务。为什么?因为OOM Killer的评分算法(oom_score_adj)不仅看RSS,更看重badness值,而journald因频繁写磁盘(/var/log/journal在eMMC上),其pgpgout(页面换出次数)极高,在内核oom_badness()函数中被判定为“更容易kill且影响小”。我们从dmesg -T | grep -A 20 "Killed process"提取到关键日志:
[Mon Apr 15 03:22:17 2024] Out of memory: Kill process 1234 (gst-launch-1.0) score 123 or sacrifice child [Mon Apr 15 03:22:17 2024] Killed process 5678 (systemd-journald) total-vm:123456kB, anon-rss:45678kB, file-rss:1234kB, shmem-rss:0kB注意:第一行说要kill gst-launch-1.0(score 123),第二行却kill了journald。这是因为内核在计算过程中,journald的nr_ptes(页表项数)和nr_pmds(页中间目录数)远高于rtspsrc(因其内存映射分散),导致最终badness值反超。journald死后,日志停止写入,/var/log/journal分区因ext4 journal模式被强制sync,触发eMMC写保护锁死——这才是整机“静默”的直接原因:不是CPU停摆,而是存储IO彻底阻塞,所有依赖磁盘的操作(包括SSH密钥验证、systemd unit reload)全部hang住。此时ping仍通(网络栈在内核态),但telnet 22端口无响应,因为sshd进程卡在write()系统调用上,等待eMMC完成journal commit。
2.4 第四级坍塌:硬件看门狗的失效与误触发(最后一道防线的崩坏)
RK3588板载硬件看门狗(WDT)本该在此时救场。我们配置了/etc/systemd/watchdog.conf:
WatchdogSec=30 RuntimeWatchdogSec=30 ShutdownWatchdogSec=120并启用systemctl enable systemd-watchdog.service。理论上,当systemd-journald挂掉后,systemd-watchdog会检测到/dev/watchdog设备无心跳,30秒后触发硬件复位。但实际复盘发现,WDT从未触发。原因有二:第一,systemd-watchdog服务本身依赖journald记录心跳日志,journald一死,watchdog service也因Failed to write entry而退出,失去喂狗能力;第二,RK3588的WDT寄存器映射在0xff110000地址,但U-Boot阶段未正确初始化WDT时钟源(CLK_WDT需从CLK_PLL_APLL分频),导致WDT计数器实际不工作。我们用devmem2 0xff110000读取寄存器值始终为0,证实了这一点。更讽刺的是,当eMMC IO hang住后,系统进入一种“伪死”状态:CPU仍在执行空循环,但所有外设中断被屏蔽。此时若手动短接主板WDT_RST引脚,机器会立即重启——证明WDT硬件完好,只是软件层完全失去了控制权。这暴露了嵌入式系统设计的根本矛盾:你把看门狗当成保命符,却忘了看门狗自己也需要被看护。
2.5 第五级坍塌:整机静默与恢复盲区(事故终点)
最终状态是:RK3588 SoC仍在供电运行,A76大核频率锁定在1.8GHz(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq),但所有用户态进程处于D状态(不可中断睡眠),ps aux | awk '$8 ~ /D/ {print}'列出23个进程,全卡在__wait_event_common。/proc/interrupts显示eth0中断计数停滞,但serial中断仍在增长(说明串口驱动还能收字符,但无进程读取)。此时唯一能做的就是长按电源键强制断电——但这会损坏eMMC文件系统。我们尝试过echo 1 > /proc/sys/kernel/sysrq然后echo s > /proc/sysrq-trigger同步磁盘,但因eMMC已锁死,该命令无响应。最终只能接受现实:整机掉线,且无法远程恢复。而最痛的教训是,这次掉线发生在客户验收前夜,所有调试日志因journald崩溃而丢失,我们手头只有/var/log/kern.log里最后100行,其中最关键的一行是[Mon Apr 15 03:22:17 2024] EXT4-fs error (device mmcblk2p1): ext4_journal_check_start:61: Detected aborted journal——它像一句遗言,宣告了整个故障链的终点:不是硬件故障,不是软件bug,而是资源管理策略的系统性失效。
3. 核心技术点深度解析:OOM、systemd、RTSP、看门狗的协同作用
3.1 OOM Killer的决策逻辑与RK3588平台适配要点
OOM Killer不是随机杀人,它的badness评分有一套严谨算法,理解它才能避免被误杀。核心公式在mm/oom_kill.c中:
points = 1000 * (task->signal->oom_score_adj + 1000) / 2000; points += (task->mm->nr_ptes + task->mm->nr_pmds) * 2; points += task->mm->nr_anon_pages * 8; points -= task->mm->nr_file_pages * 2;在RK3588平台上,有三个关键变量被放大:
第一,nr_ptes/nr_pmds权重翻倍。因为RK3588采用ARMv8.2 Large Page Support,GStreamer硬解器(omxh264dec)为提升DMA效率,会申请大量2MB大页(huge page),每个大页对应一个PMD(Page Middle Directory)项。实测一个rtspsrc进程nr_pmds达128,而普通进程仅2~3,这直接让它的badness基础分暴涨256分。
第二,nr_anon_pages乘数为8。RTSP流解码产生的YUV帧数据全部分配在匿名页(anon-rss),每帧1920×1080×3字节≈6MB,16路流每秒产生96MB匿名页,nr_anon_pages指数级增长。
第三,nr_file_pages减分失效。GStreamer的appsink回调函数中,我们用gst_buffer_map()获取帧数据指针后,未调用gst_buffer_unmap(),导致内核无法将这些页标记为file-backed,减分项归零。
因此,RK3588部署RTSP服务时,必须做三件事:
- 主动降低oom_score_adj:
echo -900 > /proc/$(pidof gst-launch-1.0)/oom_score_adj,将其置于“最后被kill”序列; - 强制使用标准页:在GStreamer pipeline中添加
! videoconvert ! videoscale ! capsfilter caps="video/x-raw, width=1920, height=1080, format=NV12, pixel-aspect-ratio=1/1",避免大页分配; - 严格管理buffer生命周期:在appsink的
new-sample回调中,gst_buffer_unmap()必须成对出现,否则内存永不释放。
提示:不要依赖
MemoryMax硬限制。RK3588的cgroup v2在内存压力下会优先压缩zram(如果启用),而非触发OOM。建议关闭zram,改用MemoryHigh=400M(软限制,超限则内存回收)+MemoryMax=450M(硬限制,超限则OOM)组合。
3.2 systemd服务单元的健壮性加固方案
systemd在RK3588上的脆弱性源于其过度依赖内存和磁盘IO。要让它扛住RTSP流冲击,需重构服务单元配置。原始/etc/systemd/system/gst-rtsp.service如下:
[Unit] Description=GStreamer RTSP Service After=network.target [Service] Type=simple ExecStart=/usr/bin/gst-launch-1.0 rtspsrc location=... ! ... Restart=always RestartSec=10 User=root [Install] WantedBy=multi-user.target这个配置有五个致命缺陷:
缺陷1:Type=simple导致启动即认为成功。GStreamer pipeline可能因网络延迟在30秒后才真正连接RTSP服务器,但systemd已在t=0秒标记service为active,后续RestartSec=10毫无意义。应改为Type=notify,并在pipeline中插入! fakesink sync=true,用gst_element_post_message()发送GST_MESSAGE_STATE_CHANGED通知systemd。
缺陷2:无资源隔离。所有RTSP流共享同一cgroup,一个流异常会拖垮全部。应为每路流创建独立service实例:gst-rtsp@1.service、gst-rtsp@2.service,用%i参数化location。
缺陷3:忽略FD泄漏。DefaultLimitNOFILE是全局设置,但单个service可单独限制:在[Service]段添加LimitNOFILE=1024,并用lsof -p $(pidof gst-launch-1.0)定期审计。
缺陷4:日志无保护。journald崩溃是连锁反应起点,必须将其与主服务解耦:systemctl mask systemd-journald.service,改用rsyslog写入/dev/shm/journal.log(内存文件系统,避免eMMC压力)。
缺陷5:无健康检查。添加ExecStartPost=/usr/local/bin/check-rtsp-health.sh %i,脚本用gst-discoverer-1.0 --timeout=5000000 rtsp://...验证流可达性,失败则systemctl stop gst-rtsp@%i.service。
加固后的配置关键段:
[Service] Type=notify NotifyAccess=all ExecStart=/usr/bin/gst-launch-1.0 --no-fault rtspsrc location=%i ! ... ! fakesink sync=true Restart=on-failure RestartSec=5 RestartPreventExitStatus=1 LimitNOFILE=1024 MemoryHigh=300M MemoryMax=350M OOMScoreAdjust=-900 # 关键:禁用journald,改用内存日志 StandardOutput=journal StandardError=journal SyslogIdentifier=gst-rtsp-%i # 健康检查 ExecStartPost=/usr/local/bin/check-rtsp-health.sh %i3.3 RTSP协议在RK3588上的性能瓶颈与规避策略
RTSP协议本身无错,但RK3588的实现有三大瓶颈:
瓶颈1:TCP传输层拥塞控制失灵。rtspsrc默认使用TCP传输,但RK3588的tcp_congestion_control内核参数为bbr,在局域网高带宽低延迟场景下,BBR会激进提升cwnd(拥塞窗口),导致接收缓冲区瞬间填满。解决方案:强制改用cubic算法,echo "net.ipv4.tcp_congestion_control = cubic" > /etc/sysctl.d/99-rk3588-rtsp.conf,并sysctl -p生效。
瓶颈2:RTP包重组开销过大。rtph264depay组件在解析H.264 Annex B格式时,需遍历每个NALU查找起始码0x00000001,在1080p@30fps下每秒处理32400个NALU,A55小核CPU占用率达92%。优化方案:上游RTSP服务器改用AVCC格式(H.264 bitstream with length prefix),rtph264depay可跳过起始码搜索,CPU占用降至18%。
瓶颈3:时间戳同步漂移。rtspsrc的latency参数(默认2000ms)与实际网络抖动不匹配,导致rtph264depay内部缓冲区持续扩容。实测发现,将latency=100改为latency=500,并配合do-timestamp=true,可使缓冲区稳定在8MB以内。
实操心得:不要迷信
gst-inspect-1.0 rtspsrc的文档。RK3588平台的rtspsrc有私有属性drop-on-latency(默认false),设为true后,当缓冲区超限时自动丢弃旧帧,而非无限扩容。命令:rtspsrc drop-on-latency=true latency=500 ! ...。
3.4 硬件看门狗的可靠启用与交叉验证
RK3588的硬件看门狗(WDT)要真正起效,必须跨越三个门槛:
门槛1:U-Boot阶段初始化。在rk3588_defconfig中确保CONFIG_WDT_RK3588=y,并在board/rockchip/rk3588/rk3588.c的board_init()函数中添加:
// 启用WDT时钟 writel(0x1, RK3588_CRU_BASE + 0x01a0); // CLK_WDT_GATE // 配置WDT时钟分频为1MHz writel(0x10000, RK3588_CRU_BASE + 0x01a4); // CLK_WDT_DIV编译U-Boot后,用fw_printenv wdt确认wdt=on。
门槛2:内核驱动加载。检查dmesg | grep wdt,应有rk3588-wdt 0xff110000.watchdog: initialized with timeout 30s, nowayout=0。若无,需在arch/arm64/boot/dts/rockchip/rk3588.dtsi中添加:
&wdt { status = "okay"; rockchip,disable-suspend; };门槛3:用户态可靠喂狗。systemd-watchdog不可靠,改用轻量级watchdogd:
# 编译watchdogd(需交叉编译工具链) git clone https://github.com/rockchip-linux/watchdogd.git cd watchdogd && make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- # 部署并配置 cp watchdogd /usr/local/bin/ echo "/dev/watchdog 30" > /etc/watchdog.conf # 创建systemd service cat > /etc/systemd/system/watchdogd.service << 'EOF' [Unit] Description=Hardware Watchdog Daemon Wants=multi-user.target Before=multi-user.target [Service] Type=simple ExecStart=/usr/local/bin/watchdogd -c /etc/watchdog.conf Restart=always RestartSec=5 # 关键:不依赖journald StandardOutput=null StandardError=null [Install] WantedBy=multi-user.target EOF systemctl daemon-reload && systemctl enable watchdogd.service此方案优势在于:watchdogd二进制仅12KB,无动态链接依赖,即使journald崩溃也能独立运行;其喂狗逻辑简单粗暴——每10秒向/dev/watchdog写入V字符,30秒无写入则硬件复位。
4. 实操复现与验证:从故障注入到防护上线的全流程
4.1 构建可复现的故障环境
要验证修复方案,必须先100%复现原故障。我们搭建了一个最小化测试环境:
- 硬件:正点原子RK3588开发板(4GB LPDDR4X,32GB eMMC)
- 软件:Buildroot 2023.02(Linux 6.1.16,GStreamer 1.22.0)
- RTSP源:用
ffmpeg模拟劣质流:ffmpeg -re -stream_loop -1 -i test.mp4 -c copy -f rtsp rtsp://0.0.0.0:8554/test,然后在test.mp4中插入10秒黑场(I帧缺失),制造rtspsrc缓冲区膨胀条件。
故障注入脚本inject-oom.sh:
#!/bin/bash # 模拟内存泄漏 dd if=/dev/zero of=/tmp/leak.bin bs=1M count=500 & LEAK_PID=$! # 启动RTSP服务 systemctl start gst-rtsp@1.service # 等待30分钟,观察内存 for i in {1..30}; do echo "$(date): RSS=$(ps -o rss= -p $(pidof gst-launch-1.0)) KB" sleep 60 # 检查是否掉线 if ! ping -c1 -W1 10.255.207.85 &>/dev/null; then echo "CRASH DETECTED at $(date)" break fi done kill $LEAK_PID rm /tmp/leak.bin实测结果:未加固前,平均22.3分钟触发OOM;加固后,连续运行168小时无掉线。
4.2 关键参数调优与效果对比
我们对四个核心参数进行AB测试,每组运行72小时,统计掉线次数:
| 参数组合 | MemoryHigh | oom_score_adj | rtspsrc latency | drop-on-latency | 72小时掉线次数 |
|---|---|---|---|---|---|
| 原始配置 | 512M | 0 | 2000 | false | 3.2 ±0.4 |
| 方案A | 300M | -900 | 2000 | false | 1.8 ±0.3 |
| 方案B | 300M | -900 | 500 | false | 0.6 ±0.2 |
| 方案C(推荐) | 300M | -900 | 500 | true | 0 |
方案C的drop-on-latency=true是决胜手。它让rtspsrc在缓冲区达到latency阈值时,不再等待网络恢复,而是主动丢弃最早入队的RTP包。这牺牲了极少量画面(<0.1%帧率),但换来内存占用的绝对可控。我们用Wireshark抓包验证:开启该选项后,rtspsrc的recv-q(接收队列长度)稳定在1200~1500个RTP包(约4.2MB),而关闭时峰值达23000包(78MB)。
4.3 防护措施上线checklist
将修复方案部署到生产环境,必须执行以下12项检查,缺一不可:
- U-Boot验证:
minicom连接串口,开机时按Ctrl+C进入U-Boot,执行mw.l 0xff110000 0x12345678 1写入测试值,再md.l 0xff110000 1读回,确认WDT寄存器可读写。 - 内核驱动验证:
ls /dev/watchdog*应有/dev/watchdog设备节点;cat /sys/class/watchdog/watchdog0/status应为running。 - systemd版本:
systemctl --version必须≥249,低版本不支持MemoryHigh。 - cgroup v2启用:
mount | grep cgroup应显示cgroup2 on /sys/fs/cgroup type cgroup2。 - GStreamer插件验证:
gst-inspect-1.0 omxh264dec输出中必须含rockchip字样,确认调用的是RK3588硬解器。 - RTSP流格式验证:用
ffprobe rtsp://...检查codec_name为h264且profile为Main或High,避免Baseline profile(无B帧,带宽浪费)。 - 内存日志路径:
mkdir -p /dev/shm/journal,chown root:root /dev/shm/journal,chmod 755 /dev/shm/journal。 - 服务实例化:
systemctl list-units --type=service | grep gst-rtsp@应列出所有实例,且systemctl is-active gst-rtsp@1.service返回active。 - OOM分数验证:
cat /proc/$(pidof gst-launch-1.0)/oom_score_adj必须为-900。 - 看门狗守护进程:
systemctl status watchdogd.service应为active (running),且ps aux | grep watchdogd显示进程存在。 - 健康检查脚本:手动执行
/usr/local/bin/check-rtsp-health.sh 1,应返回OK,且journalctl -u gst-rtsp@1.service -n 10无ERROR。 - 压力测试:运行
stress-ng --vm 2 --vm-bytes 1G --timeout 300s模拟内存压力,同时curl http://localhost:8080/health验证Web服务仍响应。
注意:第12项压力测试必须在所有其他项通过后执行。我们曾因跳过第4项(cgroup v2未启用),导致
MemoryHigh参数被内核忽略,压力测试中依然OOM。
4.4 线上监控与告警体系搭建
修复不是终点,监控才是常态。我们在RK3588盒子上部署了三层监控:
第一层:内核级指标采集
用procps-ng工具集定时采集:
# 每30秒采集一次 */30 * * * * root /usr/bin/awk '/^MemAvailable:/ {print $2/1024 " MB"}' /proc/meminfo >> /var/log/monitor/mem.log */30 * * * * root /usr/bin/cat /sys/fs/cgroup/memory/system.slice/memory.current >> /var/log/monitor/cgroup.log第二层:systemd服务健康度
编写check-systemd.sh:
#!/bin/bash # 检查关键服务状态 for svc in gst-rtsp@1.service watchdogd.service; do if systemctl is-active --quiet $svc; then echo "$svc OK" else echo "$svc FAILED" | logger -t SYSTEMD-ALERT # 触发告警(此处对接企业微信机器人) curl -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx" \ -H 'Content-Type: application/json' \ -d "{\"msgtype\": \"text\", \"text\": {\"content\": \"RK3588 $svc down on $(hostname)\"}}" fi done第三层:RTSP流质量监测
用ffprobe每分钟检测:
ffprobe -v quiet -show_entries format=duration -of default=nw=1 "rtsp://10.255.207.85/pltv/888888" 2>/dev/null | grep -q "duration=" || \ echo "RTSP STREAM LOST" | logger -t RTSP-ALERT所有日志统一写入/dev/shm/内存分区,避免eMMC磨损;logrotate配置为每小时轮转一次,保留最近24小时日志。
5. 常见问题与排查技巧实录:来自17次现场排障的血泪总结
5.1 典型问题速查表
| 现象 | 可能原因 | 排查命令 | 解决方案 |
|---|---|---|---|
systemctl status卡住30秒以上 | systemd内存饥饿或journald崩溃 | strace -p $(pidof systemd) -e trace=memory | 重启systemd:systemctl kill --signal=SIGUSR2 1(需提前配置KillMode=mixed) |
dmesg无OOM日志,但free -h显示MemAvailable<50MB | zram压缩启用,OOM被zram缓解 | zramctl查看zram状态 | echo 0 > /sys/block/zram0/reset禁用zram,改用MemoryHigh |
gst-launch-1.0启动后立即退出,无错误输出 | rtspsrc连接超时,但-v参数未启用 | gst-launch-1.0 -v rtspsrc location=... ! fakesink | 在pipeline末尾加fakesink sync=false,避免时间戳同步失败退出 |
看门狗配置正确,但/dev/watchdog写入后无反应 | WDT时钟未使能或复位引脚悬空 | `devmem2 0xff |