必须用 systemd 服务实现系统级自启:Ubuntu 22.04+ 默认弃用 rc.local,其兼容层启动顺序不可控、网络未就绪、日志缺失;正确做法是创建 /etc/systemd/system/myapp.service,设 After=network-online.target、User=ubuntu、StandardOutput=journal,并显式声明环境变量。

Ubuntu 20.04 及更新版本(包括 22.04、24.04)默认使用 systemd,rc.local 已被弃用或需手动启用,图形界面的“启动应用程序”只在用户登录后触发——如果你要的是**系统级、无登录依赖、稳定可查日志**的自启,必须用 systemd 服务方式,其他方法要么失效、要么时机不对、要么权限/环境缺失。
为什么 /etc/rc.local 在 Ubuntu 22.04+ 上不生效
新版 Ubuntu 默认不生成 /etc/rc.local,即使你手动创建并赋予权限,rc-local.service 单元也未启用。强行启用需额外配置 [Install] 段并 systemctl enable rc-local,但该机制本质是 systemd 对旧 SysV 的兼容层,启动顺序不可控、网络常未就绪、错误不进 journal 日志,排查困难。
常见错误现象:systemctl status rc-local 显示 inactive (dead) 或 failed;脚本里调用 curl 或 ping 失败;ps aux | grep 找不到进程。
- 不要硬改
/etc/rc.local,除非你明确需要兼容极老脚本且接受调试成本 - 若坚持使用,必须确保:
/etc/rc.local存在、可执行(chmod +x)、第一行是#!/bin/sh -e、末尾有exit 0、且已运行sudo systemctl enable rc-local -
After=network.target不等于网络可用——它只表示网络服务已启动,但 DHCP 可能还没完成分配 IP,更稳妥的是After=network-online.target
正确做法:写一个 .service 文件并启用
这是当前最可靠、可调试、可依赖管理的方式。核心是让 systemd 知道你的脚本何时跑、以谁身份跑、失败了怎么办。
假设你的脚本路径是 /home/ubuntu/myapp/start.sh,内容为:
#!/bin/bash cd /home/ubuntu/myapp ./main.bin >> /home/ubuntu/myapp/log.txt 2>&1
你需要:
Ubuntu 26.04 LTS(代号“Resolute Raccoon”)是Canonical于2026年4月23日发布的下一代长期支持版操作系统,提供长达10年的技术支持。它搭载Linux 7.0内核与GNOME 50桌面环境,全面转向Wayland协议,并引入Rust重写的核心工具以增强安全性。官方提供适用于AMD64和ARM64架构的桌面及服务器ISO镜像,是追求前沿技术与极致稳定的开发者
- 确保脚本有执行权限:
chmod +x /home/ubuntu/myapp/start.sh - 创建服务文件:
sudo nano /etc/systemd/system/myapp.service - 填入以下内容(注意替换
User和路径):
[Unit] Description=My App Service After=network-online.target Wants=network-online.target [Service] Type=simple User=ubuntu WorkingDirectory=/home/ubuntu/myapp ExecStart=/usr/bin/bash /home/ubuntu/myapp/start.sh Restart=on-failure RestartSec=5 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target
关键点说明:
-
Type=simple:适用于前台长期运行的程序(如 Python HTTP server、ROS node);若脚本只是启动后台进程后退出,应改用Type=forking并配合PIDFile= -
User=ubuntu:避免用root,尤其当脚本涉及 GUI、X11 或用户级路径(如~/.config)时,root用户无法访问普通用户的桌面会话 -
StandardOutput=journal:所有echo、printf输出都会进journalctl,查错直接运行journalctl -u myapp.service -f - 不要在
ExecStart中写bash -c "..."套壳——容易因引号、空格、变量扩展出错;直接调用解释器加脚本路径最稳
图形界面程序(如 Electron、Qt GUI)启动失败怎么办
这类程序依赖 X11 显示服务器和用户会话环境,systemd 的系统级服务默认没有 DISPLAY 和 XAUTHORITY,直接运行会报 Can't open display 或黑屏闪退。
解决办法不是降级回“启动应用程序”,而是用用户级 service:
- 服务文件放到用户目录:
~/.config/systemd/user/mygui.service - 启用用户 session:
loginctl enable-linger $USER(否则用户未登录时 service 不启动) - 服务中必须显式设置环境变量:
[Service] ... Environment=DISPLAY=:0 Environment=XAUTHORITY=/home/ubuntu/.Xauthority ExecStart=/usr/bin/bash /home/ubuntu/mygui/run.sh
然后启用:systemctl --user daemon-reload && systemctl --user enable mygui.service && systemctl --user start mygui.service
注意:--user 服务只在对应用户登录后启动,适合桌面场景;若需开机即启(无人值守登录),仍需结合自动登录 + user service。
最容易被忽略的一点:很多脚本在终端里能跑通,是因为 shell 自动加载了 ~/.bashrc 或 /etc/environment 里的 PATH、PYTHONPATH、ROS_PACKAGE_PATH 等——而 systemd 启动时环境极简。务必在 service 文件的 [Service] 段用 Environment= 显式声明所有依赖变量,或在脚本开头用 source /opt/ros/humble/setup.bash 这类语句补全环境。

















