news 2026/4/3 4:23:28

开机启动脚本踩坑记录:这些错误千万别再犯

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
开机启动脚本踩坑记录:这些错误千万别再犯

开机启动脚本踩坑记录:这些错误千万别再犯

你有没有遇到过这样的情况:辛辛苦苦写好一个服务脚本,加进开机启动,重启后却发现——它根本没跑?日志查不到,进程找不到,系统安静得像什么都没发生过。更糟的是,有时候它甚至导致系统卡在启动界面,连终端都进不去。

这不是玄学,是 Linux 系统启动机制和脚本编写规范之间那些“看不见的约定”在作祟。本文不是教你怎么写第一个脚本,而是聚焦于真实生产环境中反复踩过的坑——全部来自实际部署“测试开机启动脚本”镜像时的血泪经验。每一个错误,我们都复现过、定位过、修复过,并给出可验证的解决方案。

你不需要记住所有技术细节,但请务必避开这六个最致命的错误。它们足以让一个本该自动运行的服务,永远停留在“理论上能跑”的阶段。

1. 脚本权限缺失:不是写了就能执行,而是要“被允许执行”

很多人以为把脚本丢进/etc/init.d/目录就万事大吉,却忽略了 Linux 最基础的安全机制:执行权限

1.1 错误现场还原

假设你创建了/etc/init.d/myapp.sh,内容完整,注释齐全,update-rc.d也成功执行。但重启后ps aux | grep myapp一片空白。

检查发现:

ls -l /etc/init.d/myapp.sh # 输出:-rw-r--r-- 1 root root 1234 May 20 10:00 /etc/init.d/myapp.sh

权限是644,没有x(执行)位。init系统在扫描/etc/init.d/时,会直接跳过所有不可执行的文件。

1.2 正确做法:三步缺一不可

必须显式赋予执行权限,且推荐使用755(所有者可读写执行,组和其他人可读可执行):

sudo chmod 755 /etc/init.d/myapp.sh # 验证 ls -l /etc/init.d/myapp.sh # 应输出:-rwxr-xr-x 1 root root 1234 May 20 10:00 /etc/init.d/myapp.sh

关键提醒chmod必须在update-rc.d之前执行。如果顺序颠倒,update-rc.d可能静默失败或注册一个无效链接。

2. INIT INFO 注释块不完整:少一行,全盘皆输

Ubuntu 的init.d启动机制严重依赖脚本开头的### BEGIN INIT INFO块。它不是可选注释,而是update-rc.d解析脚本元信息的唯一依据。

2.1 致命缺失项:Default-StartDefault-Stop

参考博文中的示例虽然包含了这两行,但很多开发者会下意识删掉,认为“反正默认就行”。错!update-rc.d在解析时,如果发现Default-Start缺失,会直接拒绝注册,且不报任何错误

错误写法(缺少 Default-Start):

### BEGIN INIT INFO # Provides: myapp # Required-Start: $local_fs $network # Short-Description: My Application ### END INIT INFO

执行sudo update-rc.d myapp defaults后,看似成功,实则/etc/rc?.d/下没有任何SxxmyappKxxmyapp链接。

2.2 完整且安全的 INIT INFO 模板

请直接复制使用,已通过 Ubuntu 20.04/22.04 实测:

#!/bin/sh ### BEGIN INIT INFO # Provides: myapp # Required-Start: $local_fs $remote_fs $network $syslog # Required-Stop: $local_fs $remote_fs $network $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start and stop myapp # Description: Myapp is a background service for data processing. ### END INIT INFO
  • Required-Start$network是关键:确保你的脚本在网络就绪后才启动。
  • Default-Start: 2 3 4 5覆盖了所有标准多用户运行级别。
  • Description字段必须有,且不能为空,否则update-rc.d可能解析失败。

3. 路径硬编码陷阱:cd不等于“我在项目目录”

脚本中常见的写法是:

cd /home/ubuntu/myproject ./start.sh

这在手动执行时完全没问题。但当它作为init.d服务启动时,当前工作目录是/(根目录),而非你的用户家目录。

3.1 错误后果

  • cd /home/ubuntu/myproject失败(因为/home/ubuntu可能尚未挂载,或权限不足)
  • 后续所有相对路径操作(如./start.sh,config.ini)全部失效
  • 进程可能静默退出,/var/log/syslog中只有一行myapp: cd: /home/ubuntu/myproject: No such file or directory

3.2 绝对路径 + 存在性校验才是王道

# 定义绝对路径(用变量提高可读性) APP_HOME="/home/ubuntu/myproject" START_SCRIPT="$APP_HOME/start.sh" # 关键:校验路径是否存在且可访问 if [ ! -d "$APP_HOME" ]; then echo "ERROR: APP_HOME directory does not exist: $APP_HOME" >&2 exit 1 fi if [ ! -x "$START_SCRIPT" ]; then echo "ERROR: Start script is not executable: $START_SCRIPT" >&2 exit 1 fi # 确保以正确用户身份运行(避免root权限过大风险) su -c "$START_SCRIPT" -s /bin/sh ubuntu

为什么用su -c而非sudo
sudoinit.d环境中常因缺少 TTY 或配置缺失而失败;su更底层、更可靠,且-s /bin/sh明确指定了 shell,避免环境变量污染。

4. 启动超时与后台化:别让 init 等你等到天荒地老

init.d脚本默认是同步阻塞执行的。如果你的start.sh是一个长期运行的守护进程(比如 Python Flask 服务),它必须主动转入后台,否则init会一直等待,最终触发超时,强制杀死进程并标记服务启动失败。

4.1 典型错误:忘记&nohup

错误写法:

# 这会让 init 一直卡在这里,直到进程退出或超时 /home/ubuntu/myproject/start.sh

4.2 正确的后台化三要素

# 1. 使用 nohup 忽略挂起信号,防止终端关闭影响 # 2. 使用 & 将进程放入后台 # 3. 重定向 stdout/stderr 到日志文件,避免输出丢失 nohup /home/ubuntu/myproject/start.sh > /var/log/myapp.log 2>&1 & # 记录 PID,便于后续 stop 操作 echo $! > /var/run/myapp.pid

同时,在脚本的stop函数中,必须读取并 kill 这个 PID:

stop() { if [ -f /var/run/myapp.pid ]; then kill $(cat /var/run/myapp.pid) rm -f /var/run/myapp.pid fi }

5. rc.local 的“伪可靠”:它比你想的更脆弱

参考博文提到rc.local方法“尝试了两次没有成功”,这不是偶然。rc.local在现代 Ubuntu(18.04+)中已被 systemd 弱化,其执行时机和可靠性远不如init.d

5.1 两个隐藏雷区

雷区一:exit 0缺失或位置错误
rc.local脚本末尾必须exit 0,且必须是最后一行。如果exit 0被注释掉,或后面还有空行/命令,整个rc.local会被 systemd 视为失败,从而跳过执行。

雷区二:/etc/rc.local文件本身未启用
Ubuntu 20.04+ 默认不启用rc.local服务。必须手动启用:

sudo systemctl enable rc-local # 并确保 /etc/rc.local 存在且可执行 sudo chmod +x /etc/rc.local

5.2 如果坚持用 rc.local,请这样写

#!/bin/sh -e # # rc.local # # 确保在所有网络服务之后执行 sleep 5 # 使用绝对路径,并添加错误处理 if [ -x /home/ubuntu/myproject/start.sh ]; then su -c "/home/ubuntu/myproject/start.sh > /var/log/myapp_rclocal.log 2>&1 &" -s /bin/sh ubuntu fi exit 0

强烈建议:除非有特殊兼容性要求,否则优先选择init.d方案。rc.local应作为临时调试手段,而非生产方案。

6. 日志缺失 = 黑盒调试:没有日志,等于没有真相

所有上述错误,最终都会表现为“服务没起来”。但如果你没有日志,就只能靠猜。/var/log/syslog是第一线索,但它只记录init层面的信息(如Starting myapp...),不记录你的脚本内部发生了什么。

6.1 必须建立的三层日志体系

层级位置记录内容查看命令
系统层/var/log/sysloginit启动状态、update-rc.d操作sudo grep myapp /var/log/syslog
服务层/var/log/myapp.log脚本自身 stdout/stderrsudo tail -f /var/log/myapp.log
进程层/var/run/myapp.pid当前运行进程 IDcat /var/run/myapp.pid

6.2 一个健壮的日志初始化函数

在你的init.d脚本开头加入:

# 日志配置 LOG_FILE="/var/log/myapp.log" PID_FILE="/var/run/myapp.pid" mkdir -p /var/log /var/run # 写入启动时间戳 echo "=== $(date) ===" >> "$LOG_FILE"

并在每个关键步骤后追加日志:

echo "[$(date)] Starting application..." >> "$LOG_FILE" su -c "$START_SCRIPT > $LOG_FILE 2>&1 &" -s /bin/sh ubuntu echo "[$(date)] Application started with PID \$!" >> "$LOG_FILE"

总结:一份可立即执行的自查清单

当你完成一个开机启动脚本的编写,不要急着reboot。请按此清单逐项核对,90% 的问题都能在重启前发现:

7. 自查清单:六步确认法

7.1 权限与位置

  • [ ] 脚本文件位于/etc/init.d/目录下
  • [ ] 脚本权限为755sudo chmod 755 /etc/init.d/myapp.sh

7.2 INIT INFO 完整性

  • [ ] 包含完整的### BEGIN INIT INFO### END INIT INFO
  • [ ]Default-StartDefault-Stop行存在且值正确
  • [ ]Provides:字段名称与文件名一致(myapp.shProvides: myapp

7.3 路径与用户

  • [ ] 所有路径均为绝对路径,无~$HOME
  • [ ] 使用su -c ... -s /bin/sh <username>以普通用户身份运行,而非sudo

7.4 后台化与 PID

  • [ ] 启动命令包含nohup ... &,并重定向日志
  • [ ] 成功写入PID_FILE,且stop函数能正确读取并 kill

7.5 日志与反馈

  • [ ]/var/log/myapp.log文件存在且可写
  • [ ]rc.local方案已确认systemctl enable rc-localchmod +x

7.6 验证流程

  • [ ] 先手动执行sudo /etc/init.d/myapp start,确认无报错且进程存在
  • [ ] 执行sudo /etc/init.d/myapp status(需自行实现),确认状态正常
  • [ ] 最后执行sudo reboot,观察启动过程

获取更多AI镜像

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

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

热键冲突效率神器:3分钟定位Windows快捷键占用问题完全指南

热键冲突效率神器&#xff1a;3分钟定位Windows快捷键占用问题完全指南 【免费下载链接】hotkey-detective A small program for investigating stolen hotkeys under Windows 8 项目地址: https://gitcode.com/gh_mirrors/ho/hotkey-detective 【问题发现&#xff1a;那…

作者头像 李华
网站建设 2026/3/20 2:34:04

卡顿掉帧频发?专业玩家都在用的《鸣潮》性能调校方案

卡顿掉帧频发&#xff1f;专业玩家都在用的《鸣潮》性能调校方案 【免费下载链接】WaveTools &#x1f9f0;鸣潮工具箱 项目地址: https://gitcode.com/gh_mirrors/wa/WaveTools 在《鸣潮》的游玩过程中&#xff0c;你是否经常遇到帧率波动剧烈、画面卡顿、多账号切换繁…

作者头像 李华
网站建设 2026/4/3 3:30:00

DLSS管理工具:突破性能瓶颈,释放显卡全部潜力

DLSS管理工具&#xff1a;突破性能瓶颈&#xff0c;释放显卡全部潜力 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 当你在《赛博朋克2077》的夜之城疾驰&#xff0c;却因帧率骤降错失关键剧情&#xff1b;当《艾尔登…

作者头像 李华
网站建设 2026/3/26 1:35:40

百度网盘极速下载技术解析:从原理到实战的高效解决方案

百度网盘极速下载技术解析&#xff1a;从原理到实战的高效解决方案 【免费下载链接】pan-baidu-download 百度网盘下载脚本 项目地址: https://gitcode.com/gh_mirrors/pa/pan-baidu-download 在当今云存储普及的时代&#xff0c;百度网盘作为国内用户量庞大的云存储服务…

作者头像 李华
网站建设 2026/3/4 17:11:49

如何彻底解决Windows热键被占用的难题?Hotkey Detective实战指南

如何彻底解决Windows热键被占用的难题&#xff1f;Hotkey Detective实战指南 【免费下载链接】hotkey-detective A small program for investigating stolen hotkeys under Windows 8 项目地址: https://gitcode.com/gh_mirrors/ho/hotkey-detective 你是否经历过这样的…

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

免费工具三步搞定Steam创意工坊模组下载:零基础使用指南

免费工具三步搞定Steam创意工坊模组下载&#xff1a;零基础使用指南 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 还在为无法访问Steam创意工坊的精彩模组而头疼吗&#xff1…

作者头像 李华