2026/5/21 19:40:41
网站建设
项目流程
一家专做特卖的网站,做网站编辑,婚纱摄影网页,甘肃省建设厅官方网站造价总站不用再查命令了#xff0c;测试开机启动脚本一篇讲清楚
你是不是也遇到过这样的情况#xff1a;写好了一个监控脚本、日志清理任务或者服务守护程序#xff0c;想让它开机自动运行#xff0c;结果翻遍文档、查了又查#xff0c;还是搞不清/etc/rc5.d和/etc/init.d到底谁先…不用再查命令了测试开机启动脚本一篇讲清楚你是不是也遇到过这样的情况写好了一个监控脚本、日志清理任务或者服务守护程序想让它开机自动运行结果翻遍文档、查了又查还是搞不清/etc/rc5.d和/etc/init.d到底谁先谁后软链接名字里那个S99到底是啥意思重启之后发现脚本根本没执行连日志都没留下一行别折腾了。这篇博客不讲抽象概念不堆术语就用最直白的方式带你从零开始——写一个脚本、放对位置、加个链接、验证成功全程可复制、可验证、不踩坑。无论你是刚接触Linux的新手还是被不同发行版差异搞晕的运维老手都能照着做一次搞定。我们用的是最通用、最稳定的方式SysV init风格的开机启动管理CentOS 6/7兼容模式、Ubuntu 16.04及更早版本原生支持现代系统也可通过sysv-rc-conf或update-rc.d适配。整个过程不依赖systemd复杂语法不改配置文件不装额外工具只用系统自带命令。1. 先写一个能“看见效果”的测试脚本光说原理没用得让脚本一启动你就知道它真跑了。我们不写空转的echo hello而是让它在系统启动时往一个固定位置写入时间戳——这样你只要看文件有没有更新就知道脚本是否生效。1.1 创建脚本文件打开终端执行以下命令无需sudo也能操作路径我们先建在临时目录验证sudo tee /etc/init.d/mytest.sh EOF #!/bin/bash ### BEGIN INIT INFO # Provides: mytest # Required-Start: $local_fs $network # Required-Stop: $local_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Test startup script # Description: Writes boot timestamp to /var/log/mytest.log ### END INIT INFO case $1 in start) echo [$(date %Y-%m-%d %H:%M:%S)] Service started at boot. /var/log/mytest.log ;; stop) echo [$(date %Y-%m-%d %H:%M:%S)] Service stopped. /var/log/mytest.log ;; restart) $0 stop $0 start ;; *) echo Usage: $0 {start|stop|restart} exit 1 ;; esac exit 0 EOF说明这个脚本带标准的LSB头### BEGIN INIT INFO部分能让系统识别它的依赖关系和默认运行级别start分支会在开机时执行向/var/log/mytest.log追加一行带时间戳的日志脚本支持start/stop/restart命令方便手动调试使用sudo tee直接写入避免权限问题。1.2 设置可执行权限sudo chmod x /etc/init.d/mytest.sh1.3 手动运行一次确认脚本能工作sudo /etc/init.d/mytest.sh start然后检查日志是否生成sudo cat /var/log/mytest.log你应该看到类似这样的一行[2024-06-15 14:22:38] Service started at boot.成功说明脚本本身没问题接下来就是让它“开机自动跑”。2. 理清关键概念不是所有目录都管用也不是所有名字都有效很多教程一上来就让你ln -s /etc/init.d/xxx /etc/rc5.d/S99xxx却没告诉你为什么是rc5.d为什么叫S99如果系统是runlevel 3你链到rc5.d就完全无效。我们不猜直接查。2.1 查当前运行级别不是“默认级别”是“实际启动级别”执行runlevel你会看到类似输出N 5其中第二个数字5就是系统本次启动所进入的运行级别N表示之前没有运行级别即开机状态。注意这不是配置文件里写的“默认级别”而是真实加载的级别。Ubuntu桌面版通常是5CentOS服务器版通常是3但必须以runlevel命令结果为准。2.2 理解/etc/rcX.d/目录的真实作用/etc/init.d/只是脚本存放地放在这里 ≠ 自动执行/etc/rcX.d/X为数字才是真正决定哪些脚本开机运行的地方每个rcX.d目录下都是指向/etc/init.d/中脚本的软链接链接名格式必须是S##name或K##name##是两位数字name是任意标识S Start启动时执行K Kill关机或切换级别时执行数字##决定执行顺序S10比S99先执行S99最晚。所以如果你的runlevel是5就必须把链接放进/etc/rc5.d/如果是3就得进/etc/rc3.d/——错一个目录脚本就永远不会运行。3. 创建软链接三步到位不靠记忆全靠验证我们已经知道运行级别是5现在正式把脚本“注册”进开机流程。3.1 进入目标目录并确认存在cd /etc/rc5.d/ ls -l S* | head -5你会看到类似lrwxrwxrwx 1 root root 18 Jun 10 10:02 S10sysklogd - ../init.d/sysklogd lrwxrwxrwx 1 root root 15 Jun 10 10:02 S20rsyslog - ../init.d/rsyslog ...目录存在且已有其他Sxx链接说明系统确实在这个目录下加载启动脚本。3.2 创建软链接重点命名规则顺序逻辑执行sudo ln -s /etc/init.d/mytest.sh /etc/rc5.d/S99mytest解析这个名字S表示这是启动脚本不是停止99最大序号确保它在绝大多数服务之后执行比如数据库、网络服务都启动完了你的脚本才跑mytest纯标识名和脚本原始名一致便于识别。3.3 验证链接是否创建成功ls -l /etc/rc5.d/S99mytest应输出lrwxrwxrwx 1 root root 22 Jun 15 14:30 /etc/rc5.d/S99mytest - /etc/init.d/mytest.sh软链接指向正确名字合规权限正常。4. 测试方法不用重启也能快速验证重启太慢而且有风险。我们用更安全、更快捷的两种方式验证4.1 方式一模拟开机启动流程推荐SysV init提供invoke-rc.d命令Ubuntu或直接调用/etc/init.d/脚本CentOS模拟系统启动时的调用行为# Ubuntu系含Debian sudo invoke-rc.d mytest start # CentOS/RHEL系或通用方式 sudo /etc/init.d/mytest.sh start然后检查日志sudo tail -1 /var/log/mytest.log如果看到新时间戳说明脚本能被rc机制正确调用4.2 方式二手动触发rc5.d所有S脚本深度验证这条命令会按顺序执行/etc/rc5.d/下所有以S开头的脚本跳过已执行过的sudo run-parts --test /etc/rc5.d/ | grep mytest输出应为/etc/rc5.d/S99mytest再真正执行一次加--no-sep避免警告sudo run-parts --no-sep /etc/rc5.d/ | grep mytest提示run-parts是系统内部真正用来遍历执行rcX.d脚本的命令用它测等于测了系统真实行为。5. 常见失败原因与排查清单照着检查90%问题当场解决即使步骤全对也可能失败。以下是真实环境中最高频的5个卡点附带一句命令定位问题现象快速排查命令原因与修复日志文件没生成sudo ls -l /var/log/mytest.log文件不存在说明脚本根本没运行。先执行sudo /etc/init.d/mytest.sh start看是否报错。脚本有语法错误sudo bash -n /etc/init.d/mytest.sh报错则说明脚本语法不合法如少fi、引号不匹配修正后再试。软链接指向错误ls -l /etc/rc5.d/S99mytest如果显示broken说明/etc/init.d/mytest.sh路径不对或已被删除。运行级别不匹配runlevel ls -l /etc/rc*.d/S99mytest如果runlevel是3但链接只在rc5.d那就无效。删掉错的链到rc3.d。脚本没加LSB头或权限不足sudo chkconfig --list mytestCentOSsudo service mytest statusUbuntu若提示“unrecognized service”说明系统未识别该脚本。确认LSB头完整、权限为x、文件名不含特殊字符。记住所有问题都优先用sudo /etc/init.d/mytest.sh start手动执行来定位。能手动跑通才能开机跑通。6. 进阶技巧让脚本更可靠、更省心上面是“能用”下面这三条让你的脚本真正“好用”6.1 加入启动依赖声明防服务未就绪你的脚本如果要访问MySQL或Redis必须等它们先启动。在LSB头里声明# Required-Start: $local_fs $network mysql redis-server然后系统会自动确保这些服务先于你的脚本启动需对应服务本身也注册了LSB头。6.2 使用update-rc.dUbuntu或chkconfigCentOS自动化管理避免手写ln命令出错# Ubuntu sudo update-rc.d mytest defaults # CentOS sudo chkconfig --add mytest sudo chkconfig mytest on这两条命令会自动根据LSB头里的Default-Start为你在所有对应rcX.d目录下创建正确链接。6.3 日志轮转与错误捕获生产必备在脚本start分支末尾加上# 捕获执行错误并记录 if ! /path/to/your/real/command; then echo [$(date)] ERROR: real command failed! /var/log/mytest.log fi同时用logrotate管理/var/log/mytest.log防止日志撑爆磁盘。7. 总结开机启动这件事其实就四步回顾一下从零到验证成功你只做了四件确定的事1. 写一个带时间戳的日志脚本并手动验证它能跑2. 用runlevel命令查清系统真实启动级别不凭经验猜测3. 在对应的/etc/rcX.d/目录下用ln -s创建S##name格式的软链接4. 用invoke-rc.d或run-parts模拟启动流程确认日志写入成功。没有玄学没有隐藏配置不依赖发行版特有工具。这套方法在CentOS 6/7SysV兼容模式、Ubuntu 14.04–18.04上100%有效。即使你明天换了一台新服务器只要系统还支持SysV init就照着做准没错。现在你可以关掉这篇博客了——因为接下来要做的就是打开终端敲下那几行命令亲眼看着自己的脚本在系统启动的那一刻安静而坚定地写下第一行日志。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。