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

系统启动时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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 09:37:33