Linux一键修复与安装脚本:从发行版兼容到LNMP实战

发布时间:2026/8/31 23:04:54
Linux一键修复与安装脚本:从发行版兼容到LNMP实战 简介这是一套面向Linux系统管理员、运维工程师及自学进阶者的自动化运维工具集聚焦解决服务器环境部署低效、系统故障修复繁琐等高频痛点。资源包含19个文件以14个Shell脚本为核心覆盖磁盘检查、网络配置、服务安装、日志清理等场景辅以2份Markdown文档含conda与Ubuntu环境配置指南、2个发行版适配说明文本Debian/Ubuntu及1份LICENSE协议总大小仅35KB轻量易用且结构清晰。已有175人学习下载适合快速搭建Web、数据库、Python/Rust/Julia等开发环境或一键诊断修复GRUB异常、时间同步错误、journal日志膨胀、软件包依赖冲突等典型问题。所有脚本均基于bash编写兼顾Ubuntu、Debian、CentOS等主流发行版兼容性并内置sudo权限校验、错误提示与基础日志记录机制兼顾实用性与安全性。1. 一键脚本治什么病从三类用户的实际场景说起干运维这些年我收藏过各种一键修复和安装脚本有修引导的、有清理系统的、有装LNMP的、有给新机器做初始化配置的。见得多了就会发现一个一键脚本能不能长期有用关键不在它写得多炫而在于作者有没有吃透Linux发行版之间的差异、有没有考虑过执行环境的各种意外。最近整理这个一键修复与安装脚本项目的时候我把这类脚本的适用场景、设计思路和踩坑记录重新梳理了一遍这里分享出来希望对刚接触脚本化运维、或者想自己写一套服务器环境安装工具箱的人有参考价值。先明确这个项目解决什么问题它把系统修复和服务器环境安装两条线合并到同一个脚本包用户拿到压缩包后按菜单选择要执行的修复项或安装项脚本自动完成发行版识别、依赖处理、源配置、软件安装、服务启动这些动作。本质上是把运维经验固化成了可重复执行的代码。这非常实用但也有一个容易被忽视的问题脚本越是一键越要清楚自己的边界否则出了问题用户会把锅扣在脚本头上。1.1 三类最典型的用户从我的实际使用经验看这类脚本的用户大致分三类。第一类是刚买了一台云服务器的个人站长。系统是厂商提供的最小化Linux镜像什么都没有要装Nginx、PHP、MySQL或者Python运行环境。手动做一遍算上配置源、解决依赖、调参数一上午就没了用脚本十分钟能跑完剩下时间可以用来配置业务本身。第二类是公司里负责几十台机器的运维或者身兼多职的半个运维开发人员。机器出问题的时候时间比什么都金贵。比如某台机器磁盘满了、服务起不来了、包管理器依赖坏了。有脚本可以先做一轮标准化排查和修复人工再进去处理真正需要判断的问题效率高很多。第三类是想在测试环境反复搭建相同软件栈的人。脚本能保证两次安装之间的版本、配置、目录结构尽量一致降低开发环境能跑、测试环境跑不起来的概率。1.2 脚本不是银弹先认清适用边界一键脚本能做的事有一个大前提系统还能启动、网络基本可用、关键数据没有被破坏。如果机器直接断电起不来、磁盘物理损坏、数据库文件损坏那就别指望脚本兜底那属于备份和容灾的范畴。另外脚本适合处理的是有标准答案的操作。改源、装包、写配置、启服务这些动作的结果可以预期适合自动化。而像这个服务为什么响应慢这段SQL为什么走错索引这类需要分析的问题脚本没法替你判断它只能帮你收集信息、做初步排查。我把手动安装、一键脚本、配置管理工具比如Ansible放在一起做过对比适合自己项目的选型可以参考这张表维度手动操作一键脚本配置管理工具上手门槛低低高一些需要懂语法重复执行稳定性差手一抖就漏较好但要处理幂等最好天然幂等规模化管理不现实单机或小批量适合大规模排查问题时透明性全程可见中需要日志中需要考虑配置漂移适用典型场景偶尔装台机器日常装机、应急修复持续配置管理、版本化交付我的观点是脚本适合做能标准化的一次性动作配置管理工具适合做长期保持某台机器处于期望状态的事。两者不冲突脚本完全可以作为配置管理工具里的一个执行单元。别指望一份脚本包解决所有问题想清楚边界脚本反而更可靠。2. 脚本骨架怎么搭兼容多发行版的底层设计如果只在一台机器上跑脚本怎么写都无所谓但要在各种Linux系统上跑第一个要解决的问题就是发行版差异。很多一键脚本换个系统就白屏不是因为功能写得不对而是第一步就卡在了包管理器识别上。2.1 发行版差异到底差在哪Debian系Ubuntu、Debian、Kali用aptRedHat系CentOS、RHEL、Rocky、AlmaLinux、Fedora用yum/dnfArch系用pacmanSUSE系用zypper。这些系统的软件包格式不同、源配置不同、服务管理工具也经历了从SysVinit到systemd的迁移老一点的CentOS 6还在用chkconfig和服务脚本。一个具备通用性的脚本必须在执行任何操作之前先搞清楚三件事系统是什么发行版、什么版本架构是什么x86_64、aarch64用什么包管理器、用什么初始化系统这些信息决定后面所有命令的写法。如果直接写死一个apt-get install或者yum install那这套脚本的适用范围就锁死在某个生态里了。2.2 检测发行版的标准方式最稳妥的方式是读取/etc/os-release文件这个文件在几乎所有现代Linux发行版上都存在包含ID、VERSION_ID、PRETTY_NAME等字段。下面是我常用的一段检测函数detect_distro() { if [ -r /etc/os-release ]; then . /etc/os-release DISTRO_ID${ID:-unknown} DISTRO_VERSION${VERSION_ID:-unknown} else echo 未找到 /etc/os-release无法确认发行版。 2 exit 1 fi case $DISTRO_ID in ubuntu|debian|kali|linuxmint) PKG_MANAGERapt INSTALL_CMDapt-get install -y UPDATE_CMDapt-get update ;; centos|rhel|rocky|almalinux|fedora) if command -v dnf /dev/null 21; then PKG_MANAGERdnf INSTALL_CMDdnf install -y else PKG_MANAGERyum INSTALL_CMDyum install -y fi UPDATE_CMD$PKG_MANAGER makecache ;; *) echo 暂未适配的发行版$DISTRO_ID 2 exit 1 ;; esac }这里有个细节CentOS 7及更早版本只有yumCentOS 8之后才默认有dnf。直接写死dnf在CentOS 7上就会报错直接写死yum在Fedora新版本上虽然能用但体验不佳。用command -v判断一下是成本最低的兼容写法。检测架构用uname -m得到x86_64、aarch64之类的结果。这在下载二进制包时非常关键。比如下载某些预编译的tar包时需要根据架构拼接URL错了就白下载。2.3 执行环境的细节环境变量、非交互、临时目录很多脚本在用户执行时报一堆乱码或卡在交互确认上原因常常是没处理非交互环境。写一键脚本时要注意几点。一是定义DEBIAN_FRONTENDnoninteractive这样apt在安装软件时不会弹出时区、配置文件覆盖之类的交互式问题否则脚本挂在一个看似不起眼的询问上一挂就是几十分钟。二是脚本开头最好用set -euo pipefail让脚本在遇到错误时及时退出而不是带着错继续跑把系统改得更乱。但这里要小心set -e在某些命令返回非零但不是错误的情况比如grep没匹配也会中断所以要根据模块灵活处理我在下面的修复模块里会再展开。三是临时目录要放在明确的位置比如/var/tmp/repair_tool并且做好权限控制结束后清理。不要把中间文件随手写到服务器上一堆地方最后自己都找不到。2.4 日志、锁和执行幂等一个认真的一键脚本必须记录日志。每个操作、每个命令的返回值、每段耗时写进日志文件用户遇到问题直接看日志不用猜。还需要考虑并发问题。如果用户手滑连点两次执行两个脚本同时改源、同时装包后果很麻烦。在脚本开头用简单的PID锁可以避免这种情况LOCK_FILE/var/run/repair_tool.lock if [ -e $LOCK_FILE ]; then PID$(cat $LOCK_FILE) if kill -0 $PID 2/dev/null; then echo 检测到已有脚本实例在运行请等待或手动清理 $LOCK_FILE exit 1 fi fi echo $$ $LOCK_FILE trap rm -f $LOCK_FILE EXIT关于幂等我的原则是可以重复执行的步骤尽量做到重复执行不产生副作用。比如创建目录前检查目录是否存在修改配置前先备份原文件安装软件前先判断软件是否已安装。这样脚本即使执行到一半失败修复问题后重新运行也不会把事情搞得更糟。3. 系统修复模块最常翻车的三类故障与排查思路系统修复是这类脚本里最有技术含量的部分。我在设计修复模块的时候把常见的故障分成了三类引导与内核类、包管理器类、服务与资源类。修复的思路不是一上来就改而是先收集信息判断故障层级再动手。3.1 引导与内核问题进不了系统的处理链路故障表现一般是重启后卡在GRUB界面、报error: file not found、或者内核启动阶段直接panic。造成原因常见的有/boot分区写满导致新内核装不上、grub配置被误改、内核升级后驱动不兼容。如果系统还能进单用户模式或救援模式修复的思路是这样的确认当前磁盘和分区情况df -h /boot看看是不是已经100%占用。如果是先清理旧内核包把空间腾出来。CentOS系可以用package-cleanup --oldkernels --count2Ubuntu/Debian系用apt-get autoremove --purge配合检查/boot下的旧vmlinuz文件。重新生成grub配置。Ubuntu系用update-grubCentOS系用grub2-mkconfig -o /boot/grub2/grub.cfg。注意UEFI和BIOS的引导路径不同UEFI通常是/boot/efi/EFI/...别搞混。如果grub.cfg损坏但GRUB壳还能进就在GRUB命令行里手工指定root和kernel启动。我在脚本里会建议先进入救援模式再执行这些修复动作。有一个经验救援模式下很多目录是空的需要通过chroot把原系统根目录挂载进去才能真正操作原系统的包管理器和配置。这个步骤如果没有做过建议先在测试机演练别等生产环境出问题再第一次见。3.2 包管理器损坏与依赖断裂的恢复方法这类问题是一键修复脚本的高频场景。现象通常是执行apt-get或yum时报依赖错误、提示broken packages、unmet dependencies、或者源不可达。恢复的顺序很重要不要一上来就重装系统。第一步确认源是否可达。很多时候不是依赖坏了是服务器换了内网环境、DNS失效或者软件源服务器响应过慢。可以先执行ping仓库域名或者curl -I测试一下。如果源有问题考虑切换到可用的镜像源。切换前一定备份原源文件这是最容易被忽略的一步。第二步修复本地依赖状态。Debian系执行dpkg --configure -a把未配置完的包配置完然后apt-get -f install修复依赖关系RedHat系执行yum/dnf clean all再makecache配合yum/dnf --setopttsflagsnoscripts等参数处理脚本碎片。第三步如果个别包已经损坏定位到具体包名重新安装。比如libssl.so.1.1缺失导致一堆命令打不开用包管理器查找所属包重新安装对应版本。这一步很容易翻车因为同一个文件可能被多个包包含需要谨慎确认。我在脚本里给包管理器修复单独做了一块只读检查模式也就是先打印出当前发现的问题让用户确认再进入自动修复。毕竟包管理器是全系统的根基自动瞎改可能比不修还麻烦。3.3 服务起不来、端口被占、磁盘满日常故障的自检顺序服务类故障占了服务器日常问题的大头。我的排查顺序固定为磁盘、内存、端口、系统日志、服务日志。先看磁盘df -h看看哪个分区满了。经验中/var分区被journal日志灌满是最常见的。systemd日志默认占用的空间可能到几个G长期不清理会把磁盘撑爆。修复手段是用journalctl --vacuum-size200M把日志压缩到合理大小。还要注意清理后最好把SystemMaxUse配置写到/etc/systemd/journald.conf里设定上限防止下次再满。再看内存free -h确认内存和swap状态。如果内存耗尽OOM killer会把进程随机杀掉表现就是服务莫名其妙挂了。可以先查看dmesg -T | grep -i oom确认是不是这个原因。然后看端口ss -lntp查看端口监听情况。端口被占导致服务起不来的情况一般是改配置换端口或者先处理占用进程。最后才是看服务日志systemctl status xxx、journalctl -u xxx -n 100 --no-pager。很多人一上来就改配置重启服务结果压根没确认服务为什么起不来浪费时间。脚本在这里能做的事是把这些检查项一次性跑完输出一份报告再把常见问题的修复动作列出来。让用户先看清现状再决定操作。我发现这个先报告后修复的设计比脚本直接自动改配置更能赢得用户信任也减少了很多误操作。4. 服务器环境安装LNMP这类组合为什么难一键装环境看起来是安装几个软件实际操作里隐藏着很多坑。为什么LNMPLinux Nginx MySQL PHP这类组合很难做到真一键因为每个组件都有版本、依赖、配置、和周边生态的兼容性问题。4.1 安装方式的选型源码编译还是软件源一键装环境首先要选安装方式。用发行版自带源依赖稳定、升级方便、包管理可控但版本通常偏旧。用第三方源如Nginx官方源、MySQL APT源、PHP PPA版本新但增加了对第三方仓库的依赖。源码编译定制化最强但耗时长、依赖链复杂升级维护比较麻烦。安装方式优点缺点适用场景发行版源稳定、依赖自动解决、升级方便版本可能偏旧绝大多数生产环境第三方官方源版本新、兼容性好需要信任第三方仓库对版本有硬要求的业务源码编译定制化强、版本任意编译慢、依赖难、升级痛苦特殊模块、特殊参数优化我在脚本里默认走发行版源优先必要组件用官方源补充的路子。比如Ubuntu自带的Nginx版本通常满足多数场景但PHP的版本可能偏老这时考虑用ondrej/php PPA获取新版本。CentOS系的EPELExtra Packages for Enterprise Linux源在很多场景是必装的它提供了很多基础源里没有的包。4.2 安装顺序的编排逻辑安装顺序看起来无所谓其实直接影响效率和排错难度。我的一般顺序是系统基础依赖curl、wget、git、vim、unzip、tar、编译工具链build-essential / gcc gcc-c make。这一步不装好后面哪一步都可能报缺少XXX。数据库MySQL或MariaDB。先装数据库因为它需要初始化数据目录、设置密码、绑定监听地址这些动作相对独立先做好可以避免后面被其他组件的配置干扰。Web服务器Nginx或Apache。配置相对简单放在数据库后面。运行语言环境PHP-FPM、Python、Node等。语言环境经常需要按业务调整版本和扩展放后面装如果前一步有问题影响面更小。安全与开机自启设置服务开机自启、配置防火墙放行端口、禁用不需要的系统服务。一个容易忽略的细节装完MySQL后立刻给root设置密码不允许空密码远程登录。不要等服务跑起来几天后再想起这个数据库裸奔在公网上的教训太多了。脚本里可以用mysql_secure_installation的思路做成一个个检查项但要注意非交互自动化时用SQL语句直接修改root密码和删除匿名用户更可控。4.3 默认配置怎么给以2核4G服务器为例很多一键脚本装完环境就算完事但真正跑起来性能不理想问题出在默认配置。我的经验是脚本至少要按服务器规格给出一套能跑的初始配置并同时打印出推荐修改的参数。以一台2核4G的云服务器为例Nginx的nginx.conf里worker_processes设为2worker_connections建议1024开启gzip。PHP-FPM的php-fpm.d/www.conf里pm dynamicpm.max_children设为20左右pm.start_servers设为5pm.min_spare_servers设为5pm.max_spare_servers设为10。这个数值和PHP程序的内存占用强相关如果你运行的是WordPress这类比较吃内存的应用max_children还要往下调。MySQL的my.cnf里innodb_buffer_pool_size建议1G到1.5G约为物理内存的25%-40%query_cache_type可以关掉MySQL 8.0已经移除查询缓存max_connections设为200左右。这些值不是银弹但比装完默认值能明显改善页面响应速度。脚本的职责是生成一份参考配置加一份说明文档而不是替用户做最终调优因为我永远不知道业务具体是重CPU还是重内存。4.4 服务注册与开机自启安装完软件一定要把服务设置为开机自启。systemd已经是大量发行版的默认init系统脚本里可以统一执行这些动作systemctl enable nginx systemctl enable php-fpm systemctl enable mysql systemctl start nginx systemctl start php-fpm systemctl start mysql但注意CentOS 7及之前的系统不一定有php-fpm这个unit名字有的版本叫php-fpm.service有的发行版需要单独装php-fpm包才有这个服务。老一点的服务还要用service命令或者chkconfig管理。所以脚本里不能把systemctl写死要先判断systemd是否存在再决定用systemctl、service还是chkconfig这套老命令。5. 实测中踩过的兼容性、安全和自作聪明的坑脚本写多了踩过的坑比功能代码还多。这一节是纯经验每一条都是真实翻过车的。5.1 永远不要乱动系统自带Python/OpenSSL版本我见过不少一键安装脚本为了装某个新软件直接把系统的Python从3.6升级到3.11或者把OpenSSL替换成新版本。结果就是yum、dnf、apt这些依赖系统Python的命令全部瘫痪因为它们的模块可能import不了新Python的库。OpenSSL更是牵一发动全身很多系统库依赖特定版本。正确做法是在需要新版本Python的场合用pyenv或conda这类独立环境工具把版本装到/usr/local或者用户目录下不要动/usr/bin/python*。需要新版本OpenSSL时优先考虑用发行版源或第三方源提供的版本尽量避免源码安装覆盖系统路径如果非要源码编译装到/usr/local/ssl再通过LD_LIBRARY_PATH让具体应用使用。5.2 防火墙和SELinux会让装好了却连不上变得司空见惯环境装完浏览器访问不了第一反应一般是脚本没配好。但我排查过很多案例问题其实是防火墙没放行80/3306端口或者SELinux处于enforcing模式Nginx无法读取home目录下的站点文件。脚本里应该主动做两件事一是检测firewalld、ufw是否启用启用了就放行常用端口但放行前打印一条消息让用户知道二是检测SELinux状态如果是enforcing至少提示用户注意事项不要擅自执行setenforce 0因为重启后会失效而且直接关闭SELinux在很多公司安全规范里是不允许的。我在脚本里会建议用户根据自己的安全策略决定是否调整脚本只负责把服务和端口准备好。5.3 高危操作前的备份时间戳目录是最低成本的后悔药修改源、替换配置文件、重建GRUB配置这些都是高危操作。脚本在做这些动作之前先创建一个带时间戳的备份目录把原文件复制进去是成本最低的后悔药。BACKUP_DIR/var/backups/repair_tool/$(date %Y%m%d_%H%M%S) mkdir -p $BACKUP_DIR cp -a /etc/apt/sources.list $BACKUP_DIR/ 2/dev/null || true cp -a /etc/yum.repos.d $BACKUP_DIR/ 2/dev/null || true别看这操作简单真到出问题的时候能省下大量时间。很多时候用户不是不想修复而是改之前没备份改坏了就彻底回不去了只能重装系统。5.4 一个真实案例在CentOS 7.9最小化上跑通LNMP有一次我拿这套脚本在新开的CentOS 7.9最小化云主机上装LNMP过程很能说明问题。第一步执行基础依赖安装发现系统里没有gcc和高版本make脚本检测到这些缺失后自动用yum groupinstall Development Tools补齐。第二步装EPEL源的时候源服务器连接很慢脚本设置了超时重试三个源镜像轮询才通过。第三步装Nginx用官方源装1.24版本本来一切顺利结果到启动Nginx时发现80端口被某个遗留进程占用了我手动排查后释放端口Nginx才正常起来。第四步MySQL初始化完成后脚本自动设置了强密码并把bind-address改成了127.0.0.1这一步我特意做了防止数据库暴露在公网。整个过程里最花时间的不是安装本身而是处理预检时没发现、执行时才暴露的个别问题。所以我在脚本里特意强化了预检步骤系统版本、磁盘空间、内存、端口占用、防火墙、SELinux这些信息先收集完整再动手。预检做得越充分后面翻车的概率越低。6. 脚本的长期维护从一次性工具到团队基建一个脚本写完能跑一次、两次不算成功。真正好用的一键脚本要能长期维护、快速排查问题、持续适配新系统。这一节分享我自己的维护思路。6.1 日志和退出码要规范脚本里每个功能模块执行完都要有一个明确的退出结果。我常用的约定是0表示成功1表示参数或环境错误2表示功能未适配3表示依赖缺失。脚本最后汇总打印出哪些模块成功、哪些失败让用户一眼看完整体情况。日志里至少要记录执行时间、运行用户、系统发行版版本、内核版本、每个关键命令的返回值。这样用户把日志甩过来我可以快速定位问题而不用反复让他执行一堆检查命令。6.2 测试矩阵适配不等于试过写各种Linux系统的脚本最怕的就是没有测试矩阵。我在脚本仓库里维护了一个表格记录每个版本在哪些系统上验证过系统版本架构包管理器验证状态Ubuntu20.04x86_64apt已验证Ubuntu22.04x86_64apt已验证Debian11x86_64apt已验证CentOS7.9x86_64yum已验证Rocky Linux9x86_64dnf已验证国产Linux发行版10.xx86_64yum/dnf部分验证某些国产信创系统有些是基于Debian生态、有些基于CentOS生态脚本里对发行版ID的识别要单独处理不能想当然地认为带个特定ID就属于某个生态。我测试时的经验是先看/etc/os-release再实际跑一遍包管理命令确认包管理器类型脚本再走对应分支。6.3 用户反馈脚本没效果时先排查这三件事用户说脚本没效果不要急着改功能先问三个问题执行环境是全新服务器还是已经跑了很多服务的老机器老机器上经常有历史配置和脚本预期冲突。执行前有没有切换到root或者使用sudo很多脚本安装服务时没有权限却报个莫名其妙的错。有没有完整看执行日志日志往往已经把问题说得明明白白只是用户没看或者日志被脚本自身清理掉了。我后来在脚本里强制把日志路径在结束的时候打印一遍提示用户保留日志有问随查。这个改动虽然小却让售后排查成本降了不少。最后一句话维护这类脚本最深的体会脚本越往下写越觉得可控比自动化更重要。宁可多留几个检查点、多打几行日志、多让用户确认一次也不要自作主张替用户改掉系统关键配置。一键脚本的价值是让重复工作变得可预期而不是让风险在不可见的地方悄悄放大。写到这里我停一下其实后面还可以扩展的方向很多比如给脚本加交互菜单界面、打包成容器镜像、结合CI/CD做上线前的环境预检。但如果是一开始起步的话先把发行版检测、日志、备份、预检这四件事做好脚本的可用性就能超过市面上大半同类工具了。这就是我这次整理的全部心得希望能给你自己动手写一键脚本的时候提供点参考。本文还有配套的精品资源点击获取