我制作了一个 systemd 服务,它启动一个简单的 .sh 来从串行连接读取数据。如果我在启动后手动运行该服务,它工作正常,但是当我尝试在启动时自动运行它时,它会失败,因为 .sh 还无法从 ttyUSB0 ( awk: fatal: cannot open file /dev/ttyUSB0' for reading (No such file or directory
) 读取。
有没有办法让服务等待 ttyUSB0 然后运行 .sh?我尝试了类似 after=ttyUSB0 的方法,但这不起作用。
[Unit]
Description=Serial logger
[Service]
ExecStart=/serial_script.sh
[Install]
WantedBy=default.target
答案1
考虑使用没关系,因为不建议从 udev 启动长时间运行的进程,并且较新的 udev 版本可能会主动尝试通过对 udev 事务和由它们生成的进程设置严格的时间限制来阻止这种情况。udev
规则而不是systemd
服务来启动脚本。
但是,如果您需要在 udev 中执行此操作(例如,在具有旧版本的旧系统中),则应该可以使用systemd
类似以下内容:/etc/udev/rules.d/99-serial-logger.rules
SUBSYSTEM=="tty", ACTION=="add", KERNEL=="ttyUSB0", RUN+="/serial_script.sh"
当将此作为 systemd 服务实现时(当前推荐的方式),请WantedBy=default.target
从您的服务中删除该行并制定udev
如下规则:
SUBSYSTEM=="tty", KERNEL=="ttyUSB0", TAG+="systemd", ENV{SYSTEMD_WANTS}+="your-serial-logger.service"
因此,udev
应该告诉systemd
在设备出现时启动服务,并在设备被删除时停止服务。
答案2
UDEV 中的此类规则不起作用
SUBSYSTEM=="tty", ACTION=="add", KERNEL=="ttyUSB0", RUN+="/serial_script.sh"
用于serial_script.sh | at now
运行与 udev 进程分离的作业。 UDEV 会阻止您在 RUN 或 PROGRAM 脚本中启动长期存在的后台进程。但是,执行此操作的“正确方法”是使用 systemd。我推荐阅读使用 systemd 实例化服务和在 udev 事件上启动长时间运行的 systemd 服务的正确方法和从 udev 启动设备的 systemd 服务实例