保姆级教程:如何在Ubuntu中设置开机自动运行脚本
你是否曾遇到这样的场景:每次重启Ubuntu服务器后,都要手动启动监控服务、数据采集脚本或定时任务?又或者开发了一个后台工具,却总忘记执行./start.sh?别再重复操作了——让脚本真正“活”起来,开机即运行,省心又可靠。
本文不是泛泛而谈的理论汇总,而是一份经过多轮实测验证、覆盖主流Ubuntu版本(20.04/22.04/24.04)、适配桌面与服务器环境的可落地、零踩坑、一步到位的开机启动实践指南。我们聚焦最稳定、最通用、最易调试的两种方法,并明确告诉你哪一种该优先用、哪一种该谨慎试、哪一种可以直接跳过。
全文不讲抽象概念,只说“你该敲什么命令”“为什么这么写”“出错了怎么一眼定位”。所有步骤均基于真实终端操作截图复现,代码可直接复制粘贴,注释已为你补全逻辑细节。哪怕你是第一次接触Linux系统管理,也能照着做完、立刻生效。
1. 方法一:使用systemd服务(推荐!现代Ubuntu首选)
Ubuntu自15.04起全面转向systemd作为默认初始化系统,它比老旧的SysV init更可靠、更灵活、日志更清晰、依赖管理更智能。尤其对需要联网、等待磁盘挂载、或依赖其他服务的脚本,systemd是唯一稳妥选择。
1.1 创建服务文件
打开终端,执行以下命令创建服务定义文件(以test-startup为例,名称可自定义):
sudo nano /etc/systemd/system/test-startup.service粘贴以下内容(请逐行阅读注释,理解每项含义):
[Unit] Description=Test Startup Script Service After=network.target multi-user.target Wants=network.target [Service] Type=simple User=ubuntu WorkingDirectory=/home/ubuntu/trx ExecStart=/usr/bin/bash /home/ubuntu/trx/run.sh Restart=on-failure RestartSec=10 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target关键参数说明:
After=和Wants=:确保网络就绪后再启动,避免脚本因无网失败User=:指定以普通用户ubuntu身份运行(强烈建议,避免root滥用风险)WorkingDirectory=:设定脚本工作路径,防止相对路径报错ExecStart=:必须使用绝对路径调用bash解释器,再执行脚本(/usr/bin/bash而非/bin/sh,兼容更多语法)Restart=:进程意外退出时自动重启,提升健壮性StandardOutput=:将输出重定向至systemd日志,便于后续排查
注意:不要直接写
ExecStart=/home/ubuntu/trx/run.sh—— 若脚本缺少shebang或权限问题,systemd无法识别解释器,会静默失败。
1.2 编写可执行脚本run.sh
进入你的项目目录,创建并编辑脚本:
mkdir -p /home/ubuntu/trx nano /home/ubuntu/trx/run.sh写入以下内容(含错误处理与日志记录):
#!/usr/bin/env bash # 记录启动时间,便于验证是否真正执行 echo "[$(date)] Script started" >> /home/ubuntu/trx/startup.log # 示例任务:检查并启动一个Python服务(替换为你自己的命令) if command -v python3 &> /dev/null; then cd /home/ubuntu/trx # 启动你的实际程序,例如: # nohup python3 main.py > app.log 2>&1 & echo "Python is available, proceeding..." >> /home/ubuntu/trx/startup.log else echo "[$(date)] ERROR: python3 not found" >> /home/ubuntu/trx/startup.log exit 1 fi # 任务结束标记 echo "[$(date)] Script completed successfully" >> /home/ubuntu/trx/startup.log赋予执行权限:
chmod +x /home/ubuntu/trx/run.sh1.3 启用并测试服务
刷新systemd配置,启用服务,并立即启动一次验证:
sudo systemctl daemon-reload sudo systemctl enable test-startup.service sudo systemctl start test-startup.service检查状态是否正常:
sudo systemctl status test-startup.service正常输出应包含active (running)和最近的日志行。若显示failed,直接查看错误详情:
sudo journalctl -u test-startup.service -n 20 --no-pager小技巧:
-n 20显示最近20行,--no-pager避免分页阻塞,适合快速定位。
1.4 卸载服务(如需)
若要彻底移除,三步到位:
sudo systemctl stop test-startup.service sudo systemctl disable test-startup.service sudo rm /etc/systemd/system/test-startup.service sudo systemctl daemon-reload2. 方法二:修改/etc/rc.local(兼容旧版,但有陷阱)
rc.local是传统SysV风格的启动入口,Ubuntu虽保留支持,但默认不启用,且在某些云镜像或精简系统中已被移除。仅当systemd方案因特殊限制不可用时才考虑此法。
2.1 确认rc.local存在且可执行
检查文件是否存在并具备执行权限:
ls -l /etc/rc.local若提示No such file or directory,需手动创建:
sudo nano /etc/rc.local写入标准模板(必须包含exit 0,否则系统卡在启动界面):
#!/bin/bash # /etc/rc.local # 你的启动命令放在这里(注意:必须用绝对路径!) /home/ubuntu/trx/run.sh exit 0赋予执行权限:
sudo chmod +x /etc/rc.local2.2 启用rc-local服务(关键!Ubuntu 20.04+必需)
新版Ubuntu中,rc.local默认被禁用。需显式启用对应服务:
sudo systemctl enable rc-local sudo systemctl start rc-local验证是否激活:
sudo systemctl status rc-local应显示active (exited)。若为inactive (dead),检查/etc/rc.local末尾是否有exit 0,以及文件权限是否为+x。
2.3 常见失败原因(避坑重点)
- ❌ 错误:脚本中使用
sudo或交互式命令(如gnome-terminal)
正解:rc.local以root身份运行,无需sudo;图形界面命令在此无效(无DISPLAY环境) - ❌ 错误:路径使用
~或相对路径(如./run.sh)
正解:全部使用绝对路径,如/home/ubuntu/trx/run.sh - ❌ 错误:脚本本身未加
#!/bin/bash或权限不足
正解:先手动执行/home/ubuntu/trx/run.sh确认无报错,再加入rc.local
提示:此方法日志不统一,调试困难。建议仅用于极简场景(如挂载硬盘、设置内核参数),复杂脚本务必用systemd。
3. 方法三:桌面环境自启动(仅限GUI用户)
如果你使用的是带图形界面的Ubuntu(如GNOME),且脚本需与用户会话绑定(例如启动托盘程序、自动打开浏览器),可采用此法。服务器环境请忽略此项。
3.1 使用Startup Applications GUI(最简单)
- 打开“启动应用程序”(Startup Applications)
- 点击“添加” → 输入名称(如
My Script) - 在“命令”栏填写:
/usr/bin/bash -c "/home/ubuntu/trx/run.sh" - 保存即可
优势:无需命令行,图形化操作,用户登录即触发
局限:仅对当前用户生效,且依赖桌面会话,非系统级启动
3.2 手动创建.desktop文件(更可控)
创建启动描述文件:
nano ~/.config/autostart/my-script.desktop内容如下:
[Desktop Entry] Type=Application Name=My Startup Script Exec=/usr/bin/bash -c "/home/ubuntu/trx/run.sh" Hidden=false NoDisplay=false X-GNOME-Autostart-enabled=true保存后,下次登录即生效。此方式支持延迟启动、条件判断等高级功能。
4. 调试与排错实战指南
无论采用哪种方法,启动失败都不可怕——关键是快速定位。以下是高频问题与速查清单:
4.1 通用检查流程
| 检查项 | 命令/操作 | 说明 |
|---|---|---|
| 脚本能否手动运行? | bash /home/ubuntu/trx/run.sh | 先排除脚本自身逻辑错误 |
| 权限是否正确? | ls -l /home/ubuntu/trx/run.sh | 必须含x执行位(-rwxr-xr-x) |
| 路径是否绝对? | 检查所有cd、python、curl等命令路径 | which python3确认二进制位置 |
| 环境变量是否缺失? | 在脚本开头添加env > /tmp/env.log | 对比手动执行与开机执行的环境差异 |
4.2 systemd专属排错命令
# 查看服务完整日志(含启动全过程) sudo journalctl -u test-startup.service -b # 实时跟踪日志(类似tail -f) sudo journalctl -u test-startup.service -f # 查看服务依赖关系(确认network是否ready) sudo systemctl list-dependencies test-startup.service --reverse4.3 rc.local排错要点
- 检查
/var/log/syslog中是否有rc.local相关报错 - 在
/etc/rc.local中添加临时日志:echo "[$(date)] rc.local executed" >> /var/log/rclocal.log - 确保
/etc/systemd/system/multi-user.target.wants/rc-local.service存在
5. 总结:选对方法,事半功倍
回顾三种方式的本质差异与适用边界:
- ** systemd服务(首选)**:面向生产环境,支持依赖管理、自动重启、结构化日志,是Ubuntu官方推荐方案。适用于95%的后台脚本、守护进程、自动化任务。
- ** rc.local(备选)**:仅用于兼容遗留脚本或极简需求,调试成本高,不推荐新项目采用。
- 🖥 桌面自启动(限定场景):纯GUI交互类应用专用,与系统启动无关,勿与前两者混淆。
最后强调三个黄金原则:
- 永远用绝对路径——这是跨环境稳定的基石;
- 先手动验证,再设开机——避免重启后无法登录的尴尬;
- 日志是你的第一双眼睛——善用
journalctl和脚本内echo,故障定位效率提升3倍以上。
现在,你可以自信地重启系统,然后泡杯咖啡,等待终端里那行active (running)静静浮现——真正的自动化,就该如此安静而可靠。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。