You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含自定义函数的Bash脚本无法通过systemd服务正常运行的问题排查

含自定义函数的Bash脚本无法通过systemd服务正常运行的问题排查

我来帮你一步步拆解和解决这个问题,从你描述的三种情况来看,核心是脚本语法错误、阻塞式函数的执行顺序和systemd对进程的管理逻辑这几个点在捣鬼。

一、先揪出最明显的问题:脚本语法错误

你脚本最后一行的代码是:

run_ffmpeg & run_rknn_yolov5_demo & &

这里多了一个多余的&,属于语法错误!Bash遇到这种错误会直接终止脚本执行,这就是Case1里htop看不到任何ffmpeg或rknn进程的根本原因——脚本连启动都没成功。

二、分析不同运行方式的问题根源

Case2:去掉所有&,只执行run_ffmpeg run_rknn_yolov5_demo

run_ffmpeg函数里是v380 | ffmpeg ...的组合,这是一个永远不会主动退出的阻塞式命令(它会一直从摄像头拉流转存图片)。当你去掉&让它前台运行时,脚本会彻底卡在这个函数里,后面的run_rknn_yolov5_demo根本没机会执行,所以你只能看到ffmpeg进程,rknn完全没启动。

Case3:run_ffmpeg & run_rknn_yolov5_demo(唯一能运行的情况)

这个写法是有效的:run_ffmpeg后台运行(脱离脚本的主执行流),run_rknn_yolov5_demo前台运行。此时systemd的Type=simple会把run_rknn_yolov5_demo作为服务的主进程监控,只要这个前台的while循环不退出,服务就会稳定运行;后台的ffmpeg会作为主进程的子进程继续存活。

而如果把两个函数都后台运行(run_ffmpeg & run_rknn_yolov5_demo &),脚本执行完这两行就会立刻退出,systemd会认为服务已经结束,再加上你设置了Restart=always,会反复重启服务,导致进程混乱。

三、给你一套完整的修复和优化方案

1. 修复脚本语法+调整进程运行逻辑

先把脚本最后一行改成下面的写法,确保systemd能监控到稳定的主进程:

# 把ffmpeg后台启动,让rknn处理逻辑作为脚本的前台主进程
run_ffmpeg &
run_rknn_yolov5_demo

同时给run_ffmpeg函数加个重启机制,避免摄像头断流后ffmpeg退出就再也不启动:

run_ffmpeg() {
    while true; do
        v380 -u xxxx -p xxxx -addr 192.168.1.xxx | ffmpeg -i - -f image2 -vf fps=3 -strftime 1 "$TEMP_DIR/%Y-%m-%d_%H-%M-%S_cap.jpg" -y
        # 如果ffmpeg意外退出,等2秒后自动重启
        echo "ffmpeg进程意外终止,2秒后重启..."
        sleep 2
    done
}

2. 解决权限问题(容易忽略的坑)

systemd默认会以root用户运行服务,但你的脚本里用的是$HOME/xxx的路径,还有/media/32GB的存储目录,可能会有权限冲突。给你的systemd服务添加用户指定:
编辑.service文件的[Service]段,加上:

User=xxx
Group=xxx

这样服务会以你自己的用户身份运行,避免读写图片目录时出现权限拒绝的错误。

3. 优化systemd服务的稳定性

可以给服务加个进程存活检查的逻辑,或者调整重启策略,比如在[Service]段添加:

# 只有当进程异常退出时才重启,正常退出不重启
Restart=on-failure
# 日志输出到journald,方便排查
StandardOutput=journal+console
StandardError=journal+console

另外,你原来的ExecStartPre=/bin/sleep 30是为了等网络,可以换成更智能的网络检查(需要先安装wait-for-it工具):

ExecStartPre=/usr/bin/wait-for-it 192.168.1.xxx:80 -t 30

这样会等摄像头的IP地址可以访问后再启动脚本,比固定sleep更靠谱。

四、验证修复效果

修改完脚本和服务文件后,执行以下命令生效:

sudo systemctl daemon-reload
sudo systemctl restart process_images_rknn.service
# 查看服务状态
sudo systemctl status process_images_rknn.service
# 实时查看服务日志,排查可能的错误
journalctl -u process_images_rknn.service -f

如果日志里没有报错,htop里就能看到ffmpeg和rknn_yolov5_demo两个进程正常运行了。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 07:53:06