news 2026/3/29 21:58:51

不用再搜了!这才是Ubuntu开机启动脚本的正确写法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
不用再搜了!这才是Ubuntu开机启动脚本的正确写法

不用再搜了!这才是Ubuntu开机启动脚本的正确写法

1. 开机自启没你想的那么简单

你是不是也遇到过这种情况:写了个脚本,想让它开机自动运行,结果重启后发现根本没执行?或者明明配置好了rc.local,却始终不生效?

别急,这在 Ubuntu 上太常见了。尤其是从 16.04 开始,systemd 成为默认初始化系统后,很多老方法都失效或变得不稳定。网上搜一圈,各种教程五花八门,有的说改rc.local,有的教写 service 文件,还有的推荐用cron @reboot——但真正能稳定工作的少之又少。

今天这篇文章就是来终结混乱的。我会手把手带你实现一个稳定、可靠、可维护的开机启动方案,并告诉你为什么其他方式容易翻车。

我们以一个实际需求为例:
假设你有一个 Python 程序放在/home/ubuntu/myapp/start.py,希望它在每次开机时自动启动,并且有日志记录、失败能自动重启。

接下来,我会介绍三种主流方式,重点分析它们的优缺点,最后给出强烈推荐的最佳实践


2. 方法一:通过 /etc/rc.local 启动(兼容性尚可,但已过时)

2.1 原理简介

/etc/rc.local是传统的 Unix/Linux 开机脚本,在系统进入多用户模式前执行。虽然 Ubuntu 已转向 systemd,但仍保留了对它的兼容支持。

2.2 操作步骤

  1. 编辑文件:
sudo nano /etc/rc.local
  1. exit 0之前添加你的命令:
#!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # 任务开始 /home/ubuntu/myapp/start.py & echo "My app started via rc.local" >> /var/log/rc-local.log exit 0
  1. 给予执行权限:
sudo chmod +x /etc/rc.local
  1. 确保服务启用(某些版本需要):
sudo systemctl enable rc-local

2.3 存在的问题

  • 执行时机不确定:网络、挂载点可能还没准备好。
  • 无进程管理:程序崩溃后不会自动重启。
  • 权限问题多:普通用户路径下的脚本可能因环境变量缺失而失败。
  • Ubuntu 20.04+ 默认不启用:必须手动创建rc-local.service才能生效。

小贴士:如果你看到rc.local根本没运行,大概率是因为rc-local.service没被激活。可以用systemctl status rc-local查看状态。


3. 方法二:使用 cron 的 @reboot(简单但局限大)

3.1 原理说明

Cron 支持一种特殊语法@reboot,表示“仅在系统重启后运行一次”。适合轻量级任务。

3.2 配置方法

  1. 编辑当前用户的 cron 表:
crontab -e
  1. 添加一行:
@reboot /usr/bin/python3 /home/ubuntu/myapp/start.py >> /home/ubuntu/logs/boot.log 2>&1

3.3 优点与缺陷

优点缺点
配置简单,无需 root 权限只运行一次,无法监控进程
用户级配置,灵活脚本崩溃后不会重启
自带日志重定向方便环境变量可能不完整

实测反馈:这种方式看似简单,但在桌面环境或 GUI 登录前,GUI 相关操作会失败;服务器环境下倒是可用,但缺乏健壮性。


4. 方法三:编写 Systemd Service(强烈推荐!这才是正确姿势)

4.1 为什么这是最佳选择?

Systemd 是现代 Linux 的核心组件,具备以下优势:

  • 精确控制启动顺序(比如等网络就绪后再启动)
  • 自动重启机制
  • 资源隔离和限制
  • 完整的日志追踪(journalctl)
  • 状态管理(start/stop/status/restart)

这才是符合当前技术趋势的正规军打法。

4.2 创建服务文件

  1. 新建服务配置:
sudo nano /etc/systemd/system/myapp.service
  1. 写入以下内容(请根据实际情况修改路径和用户名):
[Unit] Description=My Custom Startup Application After=network.target syslog.target Wants=network.target [Service] Type=simple User=ubuntu WorkingDirectory=/home/ubuntu/myapp ExecStart=/usr/bin/python3 /home/ubuntu/myapp/start.py Restart=always RestartSec=10 StandardOutput=journal StandardError=journal SyslogIdentifier=myapp [Install] WantedBy=multi-user.target
参数解释:
  • After=network.target:确保网络已启动
  • User=ubuntu:指定运行用户,避免权限问题
  • Restart=always:崩溃后自动重启
  • RestartSec=10:每次重启间隔 10 秒
  • StandardOutput=journal:日志由 systemd 统一收集

4.3 启用并测试服务

  1. 重载 systemd 配置:
sudo systemctl daemon-reexec sudo systemctl daemon-reload
  1. 启动服务:
sudo systemctl start myapp
  1. 查看状态:
sudo systemctl status myapp
  1. 设置开机自启:
sudo systemctl enable myapp
  1. 实时查看日志:
journalctl -u myapp -f

你会发现输出非常清晰,包括时间戳、PID、错误信息等,调试起来极其方便。


5. 常见坑点与避坑指南

5.1 路径问题导致脚本找不到

很多人写的脚本里用了相对路径或~,但在 systemd 环境下工作目录不一定是家目录。

正确做法:

  • 使用绝对路径
  • 显式设置WorkingDirectory

❌ 错误示例:

ExecStart=python3 ~/myapp/start.py

正确写法:

WorkingDirectory=/home/ubuntu/myapp ExecStart=/usr/bin/python3 start.py

5.2 权限不足无法访问设备或端口

如果程序要绑定 80 端口、访问 GPIO 或 USB 设备,可能会因权限不足失败。

解决方案:在[Service]中添加能力声明。

例如允许绑定低端口:

AmbientCapabilities=CAP_NET_BIND_SERVICE

或访问串口设备:

ReadWritePaths=/dev/ttyUSB0

5.3 依赖服务未就绪就启动

比如数据库还没启动完,你的应用就开始连接,必然失败。

解决方案:合理使用AfterWants

常见组合:

After=network.target postgresql.service Wants=postgresql.service

5.4 日志看不见?学会用 journalctl

别再盲目查.log文件了!systemd 提供强大的日志工具:

# 查看服务最新日志 journalctl -u myapp -n 50 # 实时跟踪日志 journalctl -u myapp -f # 查看某次启动的日志 journalctl -u myapp --since today # 查看上次启动的日志 journalctl -u myapp -b -1

这些命令比 grep 文本高效得多。


6. 总结:这才是你应该掌握的正确姿势

6.1 三种方式对比一览表

方式是否推荐适用场景稳定性可维护性
/etc/rc.local❌ 不推荐快速验证、临时任务
cron @reboot谨慎使用用户级简单脚本
systemd service强烈推荐所有生产级应用

6.2 最佳实践清单

  1. 优先使用 systemd service,这是现代 Linux 的标准方式
  2. 写清楚DescriptionAfter,提升可读性和可靠性
  3. 设置Restart=always,让程序具备自愈能力
  4. journalctl查日志,告别分散的日志文件
  5. 测试时先手动start,确认无误再enable
  6. 避免在服务中调用 GUI 程序(除非是桌面服务)

6.3 给新手的建议

如果你刚接触 Linux 自启动,记住一句话:

“凡是能用 systemd service 实现的,就不要再碰rc.localcron @reboot。”

这不是炫技,而是为了系统的长期稳定。你现在花半小时学会写 service 文件,未来能省下无数个凌晨爬起来修故障的时间。

而且一旦掌握,你会发现它比那些“简单”的方法更直观、更可控、更专业。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/27 0:04:21

json.dumps()默认无序?教你3步实现Python中JSON文件的有序存储与读取

第一章:JSON序列化默认行为的底层探源 在现代Web开发中,JSON序列化是数据交换的核心机制。理解其默认行为的底层实现,有助于开发者规避潜在的类型丢失与结构异常问题。大多数编程语言内置的JSON库在序列化对象时,遵循一套通用规则…

作者头像 李华
网站建设 2026/3/26 21:58:07

小白也能懂:用Gradio快速调用Qwen3-Reranker-4B服务

小白也能懂:用Gradio快速调用Qwen3-Reranker-4B服务 1. 为什么你需要了解这个模型? 你有没有遇到过这样的问题:在一堆搜索结果里,真正有用的信息总是藏在后面?尤其是在做多语言内容检索、技术文档查找,或…

作者头像 李华
网站建设 2026/3/27 16:07:58

高效语音增强落地|FRCRN单麦16k模型镜像全解析

高效语音增强落地|FRCRN单麦16k模型镜像全解析 1. 快速上手:三步实现专业级语音降噪 你是否遇到过这样的场景?在嘈杂的办公室录制会议纪要,背景风扇声、键盘敲击声混成一片;或是户外采访中,风噪和车流声盖…

作者头像 李华
网站建设 2026/3/27 10:50:56

多协议支持物联网平台

物联网平台 - Thinglinks-iot ## 🌟 项目简介 一个功能完备、高可扩展的物联网平台,提供完整的设备接入、管理和数据处理解决方案。支持多种网络协议,具备强大的消息解析和实时告警能力,帮助企业快速构建物联网应用。 该项目现已纳…

作者头像 李华
网站建设 2026/3/27 14:32:39

5分钟部署Z-Image-Turbo,文生图AI开箱即用实战指南

5分钟部署Z-Image-Turbo,文生图AI开箱即用实战指南 你是否还在为文生图模型下载慢、配置复杂、显存不够而头疼? 现在,只需5分钟,就能在本地跑起一个无需下载权重、启动即用、9步极速生成1024高清图的AI绘画引擎——Z-Image-Turbo…

作者头像 李华
网站建设 2026/3/27 10:46:27

资源高效+高精度识别|PaddleOCR-VL-WEB在实际场景中的应用探索

资源高效高精度识别|PaddleOCR-VL-WEB在实际场景中的应用探索 你有没有遇到过这样的问题:公司每天要处理成百上千份合同、发票、报表,内容五花八门,格式千奇百怪?传统OCR工具虽然能“识字”,但面对表格、公…

作者头像 李华