feat(fam-notifier): 补开机自启脚本,NAS 重启后推送不再静默断流

NAS 上没有 systemd,rc.d 是唯一的守护手段。旁边 frpc / nas-monitor / comic-api
都有 S99 脚本,唯独这个推送进程没有——它一旦随重启消失,运动事件就悄无声息地
断流,而且不打开网站根本发现不了。2026-09-04 到 09-12 断档整整十天就是这个剧本
(当时它还在 fam-core 里,fam-core 挂了没人重启)。

- 照抄 S99nas-monitor.sh 的写法:等 volume1 挂载就绪(最多 90s)、pidfile 判重
- 以 ericwyuan 而非 root 运行,保持 logs/ 与 data/cursor.json 属主跟手动启动一致
- DSM 上没有 pgrep,用 grep 字符类找 pid
- su 自身的 stdio 也断开:否则通过 SSH 执行时命令跑完了会话却不退出(实测踩到)

已装到 NAS 的 /usr/local/etc/rc.d/ 并验证 start/stop/restart/status;
restart 后游标从本地文件正确读回(33081),没有被重置成 SS 当前最大 id。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
ericwyuan
2026-09-13 08:35:36 +08:00
parent 1964e976f4
commit da60365214

View File

@@ -0,0 +1,72 @@
#!/bin/sh
# fam-notifier 开机自启DSM 没有 systemd/usr/local/etc/rc.d/ 是唯一的守护手段)
#
# 部署sudo cp 到 /usr/local/etc/rc.d/S99fam-notifier.sh && sudo chmod 755 同路径
#
# 为什么非有不可:这个进程是摄像头系统在 NAS 上唯一保留的东西(轮询
# Surveillance Station把运动事件单向推给甲骨文。它没起来的话事件就悄无声息
# 地断流——2026-09-04 到 09-12 断档整整十天,就是因为当时它还在 fam-core 里、
# fam-core 挂了没人重启,而且不打开网站根本发现不了。
#
# 以 ericwyuan 而不是 root 运行:保持 logs/ 和 data/cursor.json 的属主跟手动启动
# 时一致,免得 root 建出来的文件之后普通用户改不动。
RUN_USER=ericwyuan
APP_DIR=/volume1/web/sentinel-home-ai/fam-notifier
START="$APP_DIR/scripts/start_notifier.sh"
LOG="$APP_DIR/logs/start.log"
PIDFILE="$APP_DIR/fam-notifier.pid"
# DSM 上没有 pgrep用 grep 字符类找 pid[f] 写法避免匹配到 grep 自己)
find_pid() {
ps aux | grep "[f]am_notifier" | awk '{print $2}' | head -1
}
start() {
RUNNING=$(find_pid)
if [ -n "$RUNNING" ]; then
echo "fam-notifier 已在运行 (PID $RUNNING)"; echo "$RUNNING" > "$PIDFILE"; return 0
fi
# 等待数据卷 volume1 挂载就绪(最多 90 秒),避免开机时脚本早于卷挂载而静默失败
n=0
while [ ! -f "$START" ] && [ $n -lt 90 ]; do
sleep 1; n=$((n+1))
done
if [ ! -f "$START" ]; then
echo "等待 $START 超时(数据卷可能未挂载),启动放弃"; return 1
fi
# su 自身的 stdio 也要断开:否则通过 SSH 执行本脚本时,子进程继承了连接的管道,
# 命令跑完了 SSH 会话却迟迟不退出(开机时无所谓,手动敲的时候很烦)
su "$RUN_USER" -c "cd '$APP_DIR' && setsid nohup sh scripts/start_notifier.sh >> '$LOG' 2>&1 < /dev/null &" > /dev/null 2>&1 < /dev/null
sleep 4
PID=$(find_pid)
if [ -n "$PID" ]; then
echo "$PID" > "$PIDFILE"
echo "fam-notifier 已启动 (PID $PID)"
else
echo "启动失败,请查看 $LOG$APP_DIR/logs/fam-notifier.log"; return 1
fi
}
stop() {
if [ -f "$PIDFILE" ]; then kill "$(cat "$PIDFILE")" 2>/dev/null; rm -f "$PIDFILE"; fi
for p in $(ps aux | grep "[f]am_notifier" | awk '{print $2}'); do kill "$p" 2>/dev/null; done
echo "fam-notifier 已停止"
}
status() {
PID=$(find_pid)
if [ -n "$PID" ]; then
echo "运行中 (PID $PID)"
tail -3 "$APP_DIR/logs/fam-notifier.log" 2>/dev/null
else
echo "未运行"; return 1
fi
}
case "$1" in
start) start ;;
stop) stop ;;
restart) stop; sleep 2; start ;;
status) status ;;
*) echo "用法: $0 {start|stop|restart|status}"; exit 1 ;;
esac