一看就会的操作指南:Linux开机自启这样配
1. 引言
1.1 业务场景描述
在实际的服务器运维和嵌入式设备管理中,经常需要让某些脚本或服务在系统启动时自动运行。例如,启动一个数据采集程序、初始化环境变量、挂载特定文件系统,或者运行一个Python监控脚本。传统上,/etc/rc.local是实现这一目标的简单而有效的方式。
然而,随着 systemd 成为现代 Linux 发行版(如 Ubuntu 18.04 及以后版本)的默认初始化系统,rc.local不再默认启用,直接编辑该文件将无法实现开机自启功能。本文将手把手教你如何在基于 systemd 的系统中重新激活rc.local,并配置自定义脚本开机运行。
1.2 痛点分析
- 旧方法失效:Ubuntu 18.04+ 默认不再支持
/etc/rc.local自动执行。 - 权限与路径问题:即使创建了 rc.local 文件,若未正确设置权限或服务未启用,仍无法执行。
- 调试困难:脚本出错时无明确提示,需通过 systemctl status 查看日志排查。
- 编码与依赖问题:如 Python 脚本包含中文注释、缺少 shebang 或依赖未安装,会导致执行失败。
1.3 方案预告
本文将介绍一种兼容性强、结构清晰的解决方案: 1. 创建rc-local.service单元文件以恢复rc.local功能; 2. 编写并授权/etc/rc.local脚本; 3. 启用并测试服务状态; 4. 通过调用外部.sh脚本的方式实现灵活的开机任务管理。
该方案适用于 Ubuntu 18.04、20.04、Debian 等主流发行版,具有良好的可维护性和扩展性。
2. 技术方案选型
2.1 为什么选择 rc.local 兼容模式?
尽管 systemd 支持直接编写 service 文件来注册自启动服务,但对于初学者或轻量级需求而言,这种方式学习成本较高,且每个脚本都需要单独配置 unit 文件。
相比之下,使用rc.local作为“启动索引”具有以下优势:
| 对比维度 | 直接编写 systemd service | 使用 rc.local 兼容模式 |
|---|---|---|
| 配置复杂度 | 高(需了解 unit 结构) | 低(类 Shell 脚本) |
| 维护成本 | 每个服务独立配置 | 统一入口集中管理 |
| 调试便捷性 | 需 systemctl 命令查日志 | 日志输出直观 |
| 适用场景 | 复杂服务依赖控制 | 简单脚本/命令启动 |
| 兼容性 | 所有 systemd 系统 | 需手动启用 rc-local |
因此,在不需要精细控制依赖关系和服务生命周期的场景下,启用rc.local兼容模式是更高效的选择。
3. 实现步骤详解
3.1 建立 rc-local.service 文件
systemd 并不默认加载/etc/rc.local,我们需要手动创建一个 service 单元文件来激活它。
执行以下命令创建服务文件:
sudo vim /etc/systemd/system/rc-local.service将以下内容粘贴进去:
[Unit] Description=/etc/rc.local Compatibility ConditionPathExists=/etc/rc.local [Service] Type=forking ExecStart=/etc/rc.local start TimeoutSec=0 StandardOutput=tty RemainAfterExit=yes SysVStartPriority=99 [Install] WantedBy=multi-user.target参数说明:
ConditionPathExists:确保/etc/rc.local存在才启动服务;Type=forking:表示脚本会 fork 子进程后退出主进程,符合 rc.local 行为;RemainAfterExit=yes:服务被视为“仍在运行”,即使脚本已执行完毕;WantedBy=multi-user.target:在多用户模式下启动,即常规登录环境。
3.2 创建并配置 /etc/rc.local 脚本
接下来创建实际执行的脚本文件:
sudo vim /etc/rc.local填入以下内容:
#!/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. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. echo "看到这行字,说明添加自启动脚本成功。" > /usr/local/test.log exit 0注意: -
#!/bin/sh -e中的-e表示一旦某条命令出错就立即终止脚本,避免错误扩散; - 最后必须有exit 0,否则 systemd 会认为脚本执行失败; - 若不写exit 0,可能导致服务状态显示为 failed。
3.3 设置权限并启用服务
赋予脚本可执行权限:
sudo chmod +x /etc/rc.local启用rc-local.service,使其在开机时自动启动:
sudo systemctl enable rc-local输出应类似:
Created symlink /etc/systemd/system/multi-user.target.wants/rc-local.service → /etc/systemd/system/rc-local.service.这表明服务已成功注册到开机启动项。
3.4 启动服务并检查状态
为了验证配置是否生效,可以立即启动服务而不必重启系统:
sudo systemctl start rc-local.service查看服务状态:
sudo systemctl status rc-local.service正常状态下应显示:
● rc-local.service - /etc/rc.local Compatibility Loaded: loaded (/etc/systemd/system/rc-local.service; enabled; vendor preset: enabled) Active: active (exited) since ...如果出现failed状态,请根据提示信息进行排查,常见原因包括: -/etc/rc.local没有执行权限; - 脚本中存在语法错误; - 缺少exit 0; - 文件编码为 UTF-8 with BOM,导致解析异常。
3.5 重启并验证日志输出
重启系统以确认开机自启效果:
sudo reboot系统重启后,检查日志文件是否存在:
cat /usr/local/test.log预期输出:
看到这行字,说明添加自启动脚本成功。若能正确读取该内容,则证明rc.local已成功执行。
4. 进阶实践:通过 rc.local 调用外部脚本
4.1 设计思路
建议不要直接在/etc/rc.local中编写复杂逻辑,而是将其作为“启动调度器”,仅用于调用外部脚本。这样做的好处是: - 提高可读性与可维护性; - 避免污染系统级配置文件; - 便于权限隔离与独立调试。
4.2 创建自定义 Shell 脚本
假设我们有一个 Python 脚本需要开机运行,先创建对应的 shell 包装脚本:
sudo vim /opt/start_my_script.sh内容如下:
#!/bin/bash cd /home/lbw/ python3 ce.py exit 0赋予执行权限:
sudo chmod +x /opt/start_my_script.sh4.3 编写测试用 Python 脚本
创建 Python 测试脚本:
vim /home/lbw/ce.py内容为:
with open("sb.txt", "w") as f: f.write("SB")确保 Python 环境可用,并推荐使用绝对路径调用解释器(如/usr/bin/python3)以避免 PATH 问题。
4.4 修改 rc.local 调用外部脚本
编辑/etc/rc.local,将原来的 echo 替换为调用自定义脚本:
#!/bin/sh -e # 调用外部启动脚本 /opt/start_my_script.sh exit 0保存后再次重启系统:
sudo reboot检查/home/lbw/sb.txt是否生成:
cat /home/lbw/sb.txt输出应为:
SB4.5 常见问题与解决方法
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| rc-local.service 显示 inactive 或 failed | 权限不足或缺少 exit 0 | 检查/etc/rc.local是否有+x权限,确认末尾有exit 0 |
| Python 脚本报错“找不到命令” | python 命令未链接或 PATH 不对 | 使用which python3获取完整路径并在脚本中使用绝对路径 |
| 脚本中有中文字符报错 | 文件编码问题或 shell 不支持 | 保存为 UTF-8 无 BOM 格式,或移除中文注释 |
| 写入文件失败 | 目标目录不存在或权限不足 | 确保目标路径存在,必要时提前 mkdir 并赋权 |
| systemctl status 显示 timeout | 脚本长时间阻塞未返回 | 在 service 文件中添加TimeoutSec=0(已设置) |
可通过以下命令实时查看服务执行情况:
journalctl -u rc-local.service --since "1 hour ago"5. 总结
5.1 实践经验总结
本文详细演示了如何在现代 Linux 系统(如 Ubuntu 18.04+)中恢复rc.local的开机自启功能。核心要点包括: - 必须创建rc-local.service单元文件以兼容 systemd; -/etc/rc.local必须具备可执行权限且以exit 0结尾; - 推荐使用rc.local作为“启动入口”,调用外部脚本提升可维护性; - 出现问题优先使用systemctl status rc-local.service和journalctl排查。
5.2 最佳实践建议
- 统一管理启动脚本:将所有自定义脚本放在
/opt/或/usr/local/bin/下,便于集中维护; - 使用绝对路径:在脚本中尽量使用绝对路径调用命令和文件,避免因环境变量差异导致失败;
- 添加日志记录:可在脚本中加入时间戳日志,便于追踪执行过程:
bash echo "$(date): 自启动脚本开始执行" >> /var/log/boot.log
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。