推荐用 systemd 服务方式,它能精准控制启动时机、用户身份和依赖关系,是当前主流发行版(ubuntu 16.04+、centos 7+、debian 8+ 等)的官方标准做法。

写一个健壮的脚本
脚本必须能在精简的启动环境中稳定运行:
- 第一行写明解释器,例如 #!/bin/bash 或 #!/usr/bin/env python3
- 所有命令用绝对路径,比如 /bin/date、/usr/bin/python3,避免因 PATH 缺失而失败
- 加日志输出,把关键信息写入文件或用 logger 记录,别依赖终端显示
- 避免交互式操作(如 read、sudo -p),否则会卡住整个启动流程
- 检查必要依赖是否就绪,例如用 timeout 3 ping -c 1 1.1.1.1 判断网络是否可用
创建并启用 systemd 服务
把脚本当作正规服务来管理,步骤清晰可控:
- 将脚本保存为可执行文件,例如 /usr/local/bin/myscript.sh,然后运行 sudo chmod +x /usr/local/bin/myscript.sh
- 新建服务文件:sudo vim /etc/systemd/system/myscript.service
- 填入标准配置,关键字段包括:
[Unit] 中写 After=network.target(需网络时)或 After=multi-user.target(普通后台任务)
[Service] 中写 Type=oneshot(一次性脚本)或 Type=simple(常驻进程),ExecStart= 后跟脚本绝对路径
[Install] 中写 WantedBy=multi-user.target - 重载配置:sudo systemctl daemon-reload
- 启用开机自启:sudo systemctl enable myscript.service
- 立即测试:sudo systemctl start myscript.service,用 journalctl -u myscript.service -n 20 查看日志
备选:恢复并使用 /etc/rc.local
适合轻量任务或临时验证,但需手动激活,且环境较简陋:
- 确认文件存在:ls -l /etc/rc.local;若不存在,运行 sudo touch /etc/rc.local && sudo chmod +x /etc/rc.local && echo '#!/bin/bash' | sudo tee /etc/rc.local
- 编辑该文件:sudo vim /etc/rc.local,在 exit 0 前添加脚本调用,例如:/usr/local/bin/myscript.sh > /var/log/myscript.log 2>&1
- 启用系统级支持:sudo systemctl enable rc-local(部分发行版默认未启用)
- 检查状态:sudo systemctl status rc-local,失败时看日志定位问题
不推荐的做法
有些方法看似简单,实际隐患多,容易白忙活:
- crontab @reboot:启动时环境极简,PATH 很短,多数命令找不到,且无统一日志入口
- /etc/profile.d/ 下放脚本:只对登录 Shell 生效,系统启动阶段完全不执行,根本不是开机自启机制
- 直接改 /etc/init.d/(旧 SysV 方式):在 systemd 系统中兼容性差,管理复杂,已逐步淘汰











