systemd服务管理——让机器人程序开机自启

面试翻车现场

面试过一个做机器人项目的候选人,我问他:"你的机器人程序怎么实现开机自启?"

他说:"在rc.local里加一行。"

我问:"如果程序崩溃了怎么自动重启?"

他说:"写个脚本定期检查,挂了就重新启动。"

我又问:"如果程序启动失败,怎么收集日志排查问题?"

他沉默了。

rc.local是十年前的做法了。现代Linux系统用systemd管理服务,功能强大得多。做机器人开发,你的程序需要在机器人开机时自动启动、崩溃后自动重启、日志自动记录——这些systemd都能帮你搞定。

systemd是什么

systemd是Linux的系统和服务管理器。它是系统启动后运行的第一个进程(PID 1),负责启动和管理其他所有服务。

Ubuntu 16.04之后默认使用systemd。你用的ROS2、Docker、SSH,背后都是systemd在管理。

基本命令

systemctl status ssh # 查看服务状态 systemctl start ssh # 启动服务 systemctl stop ssh # 停止服务 systemctl restart ssh # 重启服务 systemctl enable ssh # 设置开机自启 systemctl disable ssh # 取消开机自启

查看系统上所有服务:

systemctl list-units --type=service # 列出所有正在运行的服务 systemctl list-unit-files --type=service # 列出所有已安装的服务

创建自定义服务

让你的机器人程序开机自启,需要创建一个service文件。

sudo vim /etc/systemd/system/robot-node.service

写入以下内容:

[Unit] Description=Robot Navigation Node After=network.target [Service] Type=simple User=robot WorkingDirectory=/home/robot/robot_ws ExecStart=/bin/bash -c "source /opt/ros/humble/setup.bash && source /home/robot/robot_ws/install/setup.bash && ros2 run nav2_node nav2_node" Restart=always RestartSec=5 Environment=ROS_DOMAIN_ID=0 [Install] WantedBy=multi-user.target

各部分含义:

[Unit]:服务的元数据和依赖关系。After=network.target表示在网络就绪后启动。

[Service]:服务的具体配置。Type=simple表示主进程就是服务进程;User=robot指定运行用户;ExecStart是启动命令;Restart=always表示崩溃后自动重启;RestartSec=5表示重启前等待5秒。

[Install]:安装配置。WantedBy=multi-user.target表示在多用户模式(正常启动)时启动。

创建完后,启用并启动服务:

sudo systemctl daemon-reload # 重新加载配置 sudo systemctl enable robot-node # 设置开机自启 sudo systemctl start robot-node # 立即启动 sudo systemctl status robot-node # 查看状态

日志管理

systemd自动收集服务的标准输出和标准错误,用journalctl查看:

journalctl -u robot-node # 查看服务日志 journalctl -u robot-node -f # 实时跟踪日志 journalctl -u robot-node --since today # 查看今天的日志 journalctl -u robot-node -n 50 # 查看最后50行

日志默认存储在/var/log/journal/目录下。如果日志太多占用磁盘空间,可以配置日志轮转:

sudo vim /etc/systemd/journald.conf
[Journal] SystemMaxUse=500M # 日志最大占用500MB SystemMaxFileSize=50M # 单个日志文件最大50MB MaxRetentionSec=7day # 保留7天

修改后重启journald:

sudo systemctl restart systemd-journald

和机器人开发的关系

systemd在机器人开发中非常实用。几个典型场景:

机器人主控程序开机自启:机器人上电后自动启动导航、感知等核心节点,不需要人工干预。

崩溃自动重启:Restart=always确保程序崩溃后自动恢复,提高系统可靠性。

依赖管理:After=network.target确保网络就绪后再启动需要网络的节点。还可以用Requires=声明硬性依赖。

日志集中管理:所有服务的日志统一用journalctl查看,不用自己写日志系统。

资源限制:可以限制服务的CPU、内存使用:

[Service] CPUQuota=50% # 最多使用50%的CPU MemoryMax=1G # 最多使用1GB内存

面试常见考点

"systemd和init有什么区别?"——systemd是现代Linux的初始化系统,支持并行启动、服务依赖管理、日志收集等功能;传统的SysVinit是串行启动,功能简单。

"怎么让一个程序开机自启?"——创建systemd service文件,配置ExecStart,然后systemctl enable。

"服务启动失败怎么排查?"——用systemctl status查看状态和错误信息,用journalctl -u查看详细日志。常见原因:路径错误、权限不足、依赖服务未启动。

"Restart=always和Restart=on-failure的区别?"——always无论什么原因退出都重启;on-failure只在非正常退出(退出码非0)时重启。

给你的建议

systemd是Linux系统管理的核心工具,做机器人开发必须掌握。

把机器人的核心程序都配置成systemd服务,实现开机自启和崩溃自动重启。这比写脚本定期检查靠谱得多。

日志用journalctl查看,不要自己写日志系统。systemd已经帮你做好了日志收集、轮转、持久化。

遇到问题先看systemctl status和journalctl,90%的问题都能从日志里找到答案。

调试服务时,可以临时把Restart=no,这样程序崩溃后不会自动重启,方便你用gdbattach上去调试。调试完再改回Restart=always。

systemd服务的编写实战

在机器人项目中,经常需要把某些程序设置为开机自启动,比如传感器驱动或通信中间件。systemd的service文件写法其实不复杂,关键是几个字段:[Unit]定义依赖关系,[Service]定义启动命令和重启策略,[Install]定义安装方式。一个实用的模板是设置Restart=always和RestartSec=5,这样进程崩溃后会自动重启。面试时如果能写出一个完整的service文件,会很有说服力。

systemd timer:替代cron的现代方案

systemd不仅能管理长期运行的服务,还能替代cron做定时任务。systemd timer比cron更强大——支持精确到秒的调度、可以和service联动、日志统一走journalctl。比如每小时清理机器人日志,创建一个oneshot service配合timer文件就行,用OnCalendar=hourly设置调度,Persistent=true确保错过的任务在重启后补执行。用systemctl list-timers查看所有活跃的定时器。


上一篇:第92篇 环境变量与路径——ROS2开发中必须搞懂的基础概念

下一篇预告:第94篇 cron定时任务——机器人日志清理和数据定期备份