AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 79575288
Accepted
Planeptunia
Planeptunia
Asked: 2025-04-15 21:34:59 +0800 CST2025-04-15 21:34:59 +0800 CST 2025-04-15 21:34:59 +0800 CST

运行 shell 脚本的 systemd 服务在启动时不会运行 cat 任务

  • 772

我有一个运行基于 Debian 的 Linux 发行版的微控制器。
我有一个 Nextion 屏幕,通过 /dev/ttyMOD1 端口上的 UART 连接到它。我有一个脚本,它使用 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
linux
  • 1 1 个回答
  • 78 Views

1 个回答

  • Voted
  1. Best Answer
    Charles Duffy
    2025-04-15T23:18:00+08:002025-04-15T23:18:00+08:00

    ttyMOD1出现问题的最明显方式是,如果服务在可用之前尝试启动;这会导致cat失败,但由于即使失败,循环仍会继续进行read,管道运算符右侧的进程不知道cat失败并继续尝试运行,从而阻止Restart=on-failure服务配置中的指令产生任何效果。


    您可以向 systemd 服务定义添加一些额外的依赖项和排序指令:

    [Unit]
    BindsTo=dev-ttyMOD1.device
    Requires=mnt-data.mount
    After=dev-ttyMOD1.device
    After=mnt-data.mount
    

    ...告诉 systemd 稍后再启动它,等到它更有可能成功的时候(After=network-online.target如果 mqtt 命令在没有网络的情况下无法运行,你可能也需要这个选项)。(这BindTo=告诉 systemd,如果设备消失后又恢复,你的服务将需要重新启动)。


    为确保在满足依赖关系之前运行脚本时系统能够恢复,请考虑:

    #!/usr/bin/env bash
    die() { rc=$?; echo "$*" >&2; exit $(( rc ? rc : 1 )); }
    
    mqtt-delete-retained "/devices/screen/#"
    
    exec 4<>/dev/ttyMOD1 || die "could not open serial device"
    stty ospeed 9600 ispeed 9600 raw clocal -parenb -echo cs8 <&4 \
      || die "could not configure serial device"
    
    while IFS=$'\r' 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
    

    笔记:

    • 如果失败,我们将退出- 这样 systemd 可以重新启动服务,而不是在设备未打开、连接丢失(或者在原始代码中,如果因任何原因退出)read时让它死亡但失败。cat
    • 如果打开 TTY 的尝试失败,我们将退出stty;同样,这可以防止脚本卡在损坏但仍在运行的状态。
    • cat我们这里根本不使用,而是read直接从设备中使用。
    • 6

相关问题

  • 如何在 Linux 上使用 Duplicity 将我的文件备份到 Google 驱动器?

  • Linux 中大型 TSV 的条件编辑

  • 计算与文件第一列相对应的第二列中的字符串出现次数[关闭]

  • 在 Linux 中从磁盘映像文件中提取输出值作为字符串[关闭]

  • 需要帮助通过 bsub 在 Windows 命令行上运行涉及多个单引号和双引号的命令

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve