系统启动时systemd服务中cat任务无法运行的问题求助
串口服务启动阶段cat任务失效问题排查与解决
问题说明
在基于Debian的Linux微控制器上,通过UART将Nextion屏幕连接至/dev/ttyMOD1端口,编写脚本利用stty配置串口参数,通过cat读取屏幕数据并发布到MQTT主题。脚本在Shell直接运行、系统启动后通过SSH连接重启服务时均可正常工作,但系统启动阶段服务内的cat任务无法运行,仅重启服务后恢复正常。脚本与服务文件已配置+x权限,需解决启动时cat任务失效的问题。
相关文件内容
serial.service
[Unit] Description=Serial script on startup Requires=wb-mqtt-serial.service After=wb-mqtt-serial.service [Service] User=root WorkingDirectory=/mnt/data/root ExecStart=/mnt/data/root/serial.sh Restart=on-failure Type=simple [Install] WantedBy=multi-user.target
serial.sh
#!/bin/bash mqtt-delete-retained "/devices/screen/#" stty -F /dev/ttyMOD1 ospeed 9600 ispeed 9600 raw clocal -parenb -echo cs8 CR="$(echo -e '\r')" exec 4<> /dev/ttyMOD1 /bin/cat <&4 | while : do IFS="$CR" read -r line case "$line" in quit*) break ;; *) if [[ -n "$line" ]]; then mosquitto_pub -t /devices/screen/controls/raw/meta/type -r -m text mosquitto_pub -t /devices/screen/controls/raw -r -m "$line" fi ;; esac done
解决方案
1. 确保串口设备节点就绪后启动服务
系统启动阶段/dev/ttyMOD1可能尚未被udev完全创建,即使依赖了wb-mqtt-serial.service,也无法保证串口设备就绪。修改serial.service的[Unit]段,添加设备依赖:
[Unit] Description=Serial script on startup Requires=wb-mqtt-serial.service dev-ttyMOD1.device After=wb-mqtt-serial.service dev-ttyMOD1.device
systemd会等待/dev/ttyMOD1设备节点存在后,再启动当前服务。
2. 给串口初始化添加重试机制
启动阶段串口可能未完全初始化,直接执行stty可能失败。修改serial.sh中的stty配置部分,增加重试逻辑:
# 替换原stty单行命令 MAX_RETRIES=5 RETRY_COUNT=0 until stty -F /dev/ttyMOD1 ospeed 9600 ispeed 9600 raw clocal -parenb -echo cs8; do RETRY_COUNT=$((RETRY_COUNT+1)) if [ $RETRY_COUNT -ge $MAX_RETRIES ]; then echo "Failed to configure serial port after $MAX_RETRIES retries" exit 1 fi sleep 1 done
3. 调整服务预检查逻辑
在serial.service的[Service]段添加预检查,确保设备存在后再启动脚本:
[Service] # 其他配置不变 ExecStartPre=/bin/sh -c 'until [ -c /dev/ttyMOD1 ]; do sleep 0.5; done'
该命令会循环等待/dev/ttyMOD1字符设备创建完成。
4. 替换cat管道为直接读取
原脚本中cat管道可能在启动阶段因串口无数据或文件描述符问题导致异常。修改读取逻辑,直接从文件描述符读取:
# 替换原exec 4<>之后的代码 exec 4<> /dev/ttyMOD1 while IFS="$CR" read -r line <&4; do case "$line" in quit*) break ;; *) if [[ -n "$line" ]]; then mosquitto_pub -t /devices/screen/controls/raw/meta/type -r -m text mosquitto_pub -t /devices/screen/controls/raw -r -m "$line" fi ;; esac done
5. 检查启动日志定位具体错误
通过journalctl查看服务启动日志,确认是否存在stty失败、MQTT连接异常等问题:
journalctl -u serial.service -b
若发现MQTT服务未完全就绪,可修改serial.service的After字段,增加网络和MQTT服务的等待:
After=wb-mqtt-serial.service network.target
内容的提问来源于stack exchange,提问作者Planeptunia
相关产品推荐
相关产品推荐

