核心内容摘要
解锁极致感官盛宴:2024年度最全Mofos软件下载及保姆级安装攻略
reboot后没生效测试开机启动脚本
常见问题解答你写好了启动脚本加了软链接也执行了reboot但系统起来后——脚本压根没跑。
日志里找不到痕迹进程列表里没有连临时文件都没生成。
这不是个例而是很多刚接触Linux服务管理的人踩得最深的一个坑脚本明明放对了位置、链接也建好了reboot之后却像没存在过一样。
这篇文章不讲抽象理论不堆概念只聚焦一个目标帮你快速定位、验证并解决“开机启动脚本不执行”这个高频故障。
我们以实际可复现的测试环境为基础即镜像“测试开机启动脚本”覆盖CentOS与Ubuntu两大主流发行版用真实操作步骤、典型错误现象和一针见血的排查逻辑带你把问题从“玄学”拉回“可验证”。
全文基于真实调试经验整理所有命令均可直接复制运行所有路径均经双系统验证所有结论都附带验证方法——不是“可能”而是“一定如此”。
脚本本身是否真的能跑通别急着查rc
d先确认最基础的一环你的脚本在当前用户下能不能手动执行成功。
很多脚本在/etc/init.d/目录下看似规范实则暗藏致命缺陷权限不对、解释器路径错误、依赖未就绪、甚至语法报错。
而这些错误在开机阶段会被静默吞掉根本不会出现在终端或日志里。
1 检查脚本权限与执行权限Linux开机启动脚本必须具备可执行权限。
即使内容完全正确缺少x位也会导致init系统直接跳过它。
# 查看脚本权限以mytest.sh为例 ls -l /etc/init.d/mytest.sh正常输出应类似-rwxr-xr-x 1 root root 248 Jun 10 15:30 /etc/init.d/mytest.sh关键看开头的-rwxr-xr-x——第三位必须是x。
如果显示为-rw-r--r--说明没有执行权限# 修复权限必须用root执行 sudo chmod x /etc/init.d/mytest.sh注意不要用chmod 777这会带来安全风险。
x是最小必要权限。
2 验证脚本能否独立运行别只看echo start这种空转逻辑。
真正要测的是它是否能在无交互、无当前用户环境、无shell历史的情况下完整走完。
# 切换到干净的最小环境执行模拟开机时的init环境 sudo env -i PATH/usr/bin:/bin:/usr/sbin:/sbin /etc/init.d/mytest.sh startenv -i清空所有环境变量显式指定PATH避免脚本内调用的curl、python等命令找不到直接传入start参数模拟系统调用方式如果报错command not found或Permission denied说明脚本内部有硬编码路径或缺失依赖必须修正后再继续。
3 检查shebang是否正确脚本第一行必须是有效的解释器声明。
常见错误包括写成#!/bin/bash但系统默认是dashUbuntu→ 改为#!/usr/bin/env bash写成#!/bin/sh但用了bash特有语法如[[→ 改为#!/bin/bashWindows换行符CRLF导致解析失败→ 用dos2unix转换验证方法head -1 /etc/init.d/mytest.sh file /etc/init.d/mytest.sh若显示CRLF line terminators立即修复sudo dos2unix /etc/init.d/mytest.sh
启动级别与rcN.d目录是否匹配runlevel命令返回的数字决定了系统加载哪个/etc/rcN.d/目录。
但这个数字不是固定不变的它取决于你的默认运行目标target而不同发行版默认值不同。
1 不要盲目信任runlevel输出在Ubuntu
1
04及CentOS 7中runlevel命令已逐渐被systemd接管其输出可能滞后于实际启动流程。
更可靠的方式是查当前默认target# 查看当前默认启动目标 sudo systemctl get-default # 常见输出 # multi-user.target → 对应传统runlevel 3无图形界面 # graphical.target → 对应传统runlevel 5带图形界面CentOS 7 / Ubuntu
1
04默认是graphical.target对应/etc/rc
d/Ubuntu Server无桌面默认是multi-user.target对应/etc/rc
d/极简容器或云主机可能连rc
d都不加载只走/etc/rc.local所以如果你在Ubuntu Server上执行runlevel看到N 3却去/etc/rc
d/建链接——脚本必然不会执行。
2 确认rcN.d目录是否被实际加载最直接的验证方式查看该目录下是否有其他已知生效的服务链接。
# 以rc
d为例Ubuntu Server常见 ls -l /etc/rc
d/ | grep S # 正常应看到类似 # S01rsyslog - ../init.d/rsyslog # S10network - ../init.d/networking # S99mytest - ../init.d/mytest.sh如果/etc/rc
d/下空空如也或者只有K开头的停止脚本说明系统根本没走这个目录——你需要切换到正确的rc目录或改用更现代的机制。
3 rcN.d目录的命名规则必须严格软链接名不是随便起的。
它必须满足两个硬性条件以S开头Start或K开头Kill不能是小写s或kS或K后紧跟两位数字00–99不能是S1或S100数字后必须跟服务名且服务名需与/etc/init.d/下脚本名一致大小写敏感错误示例s99mytest→ 小写s被忽略S999mytest→ 三位数超出范围被跳过S99mytest.sh→ 带.sh后缀init系统无法识别S99test→ 名称与/etc/init.d/mytest.sh不匹配可能导致依赖解析失败正确写法sudo ln -sf /etc/init.d/mytest.sh /etc/rc
d/S99mytest注意-f参数强制覆盖避免重复创建-s表示软链接路径必须用绝对路径。
rc.local机制是否被启用兼容性兜底方案当rcN.d机制失效或配置复杂时/etc/rc.local是Linux中最古老、最稳定、兼容性最好的启动入口。
它在所有服务启动完成后执行适合做最终检查、补丁加载或简单任务。
但要注意它在新版系统中默认是禁用的。
1 检查rc.local服务状态sudo systemctl status rc-local如果显示inactive (dead)或not-found说明未启用如果显示active (exited)说明已成功运行过
2 启用rc.localCentOS 7/Ubuntu
1
04#
确保rc.local文件存在且可执行 sudo touch /etc/rc.local sudo chmod x /etc/rc.local #
编辑文件加入你的命令必须以#!/bin/bash开头 sudo nano /etc/rc.local内容示例#!/bin/bash # 在 exit 0 之前添加你的命令 /etc/init.d/mytest.sh start /var/log/mytest_start.log 21 exit 0关键点exit 0必须是最后一行否则脚本会卡住重定向确保你能看到执行日志。
3 启用rc-local服务# 创建systemd服务单元如果不存在 sudo systemctl enable rc-local # 启动服务立即生效 sudo systemctl start rc-local # 验证是否激活 sudo systemctl is-enabled rc-local # 应返回 enabled现在无论rc
d还是rc
d是否工作rc.local都会在开机末尾执行你的脚本。
日志在哪里如何确认脚本到底有没有运行没有日志等于没有证据。
以下三个位置是定位执行失败的核心线索
1 系统启动日志最权威# 查看最近一次启动的完整日志 sudo journalctl -b | grep mytest # 或只看init相关日志 sudo journalctl -u rc-local -b-b表示本次启动boot如果grep无输出说明脚本根本没被调用如果有Failed to start说明执行时报错看紧随其后的几行错误信息
2 脚本自身日志最直接务必在脚本中加入日志记录。
不要依赖stdout因为init环境下stdout被重定向到/dev/null。
修改你的/etc/init.d/mytest.sh在关键位置插入# 开头加入 echo $(date): Starting mytest script /var/log/mytest.log # 执行核心命令后 your_command_here /var/log/mytest.log 21 echo $(date): Script finished /var/log/mytest.log然后检查sudo tail -20 /var/log/mytest.log如果文件为空说明脚本从未被执行如果有时间戳但无后续内容说明卡在某一步。
3 系统消息日志兜底排查sudo dmesg | grep -i mytest\|initdmesg记录内核和早期用户空间消息有时init加载失败的底层原因如权限拒绝、文件不存在会在这里留下痕迹。
终极验证不重启也能测开机行为每次reboot耗时长、干扰大。
其实有更高效的方法模拟开机执行流程
1 手动触发rcN.d链式调用# 模拟系统启动时对rc
d的遍历Ubuntu Server常用 for i in /etc/rc
d/S*; do [ -x $i ] echo Running $i sudo $i start done 2/dev/null这条命令会按数字顺序执行所有Sxx*脚本效果等同于开机过程。
如果这里你的脚本报错问题一定出在脚本本身或环境依赖上。