279个Shell脚本合集实战:从环境准备到排错与沙箱验证全记录

发布时间:2026/10/16 16:47:49
279个Shell脚本合集实战:从环境准备到排错与沙箱验证全记录 简介这是一份以 PDF 形式整理的 2024 年新版 Shell 脚本速查合集面向 Linux/Unix 运维、后端开发及对自动化感兴趣的入门到进阶读者。合集收录 279 个开箱即用脚本覆盖 DDoS 攻击 IP 自动屏蔽、Linux 系统邮件告警、MySQL 数据库单循环与多循环备份、Nginx 访问日志按天切割、日志深度分析、HTTP 状态码统计、网卡实时流量查看等高频运维场景每个脚本均配有功能说明、关键命令拆解与运行提示并给出可直接套用的代码与排错思路便于直接复用或二次改造。压缩包仅 1 个 pdf 文件整体 4.69MB适合离线查阅和随手速查。已有 154 人学习下载。无论用于学习还是生产环境参考都适用对希望快速积累 Shell 实战脚本、提升服务器管理与自动化排障效率的读者而言这份集合可提供现成思路与可落地代码节省从零整理命令的时间。1. 开箱即用的 Shell 脚本与其每次重写不如把这 279 个场景直接拿来改我最早接触这套 279 个 shell 脚本合集是在一次给某公司做服务器初始化的时候。新机器到手又要配时区、关防火墙、调内核参数、设 SSH 超时一套流程敲下来少说半小时还容易漏项。后来我把这些操作整理成初始化脚本跑一遍只要十几秒这才意识到Shell 脚本最大的价值不是“写”而是“复用”。这套合集里收集了大量能直接拿来改的业务场景脚本从 Dos 攻击 IP 自动封禁、MySQL 多表备份到 Nginx 日志按天切割、网卡流量实时监控基本覆盖了运维日常会遇到的重复性工作。但它不是一键安装包而是一份需要你按自己环境去调整参数的资料。如果你正在搭建 Linux 服务器监控体系、或者想规范备份和日志处理流程这套脚本能帮你省掉大量搜索和调试时间如果只是刚接触 Shell也可以从里面挑几个简单的入手边改边理解变量、循环和管道是怎么配合的。下面我从环境准备、脚本拆解、排错到验证把这套脚本真正落地跑通的全过程记录下来。2. 环境准备跑这套脚本前先看清 Bash 版本和依赖工具2.1 检查系统默认 ShellBash 3.x 和 4.x 的差异会直接影响脚本结果这套合集里的脚本绝大多数是给 Bash 写的。系统默认的 Shell 可能是 bash、dash 或 sh如果默认解释器是 dash有些数组语法和[[ ]]条件判断会直接报错。所以第一步是先确认默认 Shell 和版本echo $SHELL bash --version | head -1 ls -l /bin/shecho $SHELL输出的是当前登录 Shell 的路径ls -l /bin/sh能看出 /bin/sh 实际指向谁。Debian/Ubuntu 系列里 /bin/sh 往往指向 dashCentOS 上则指向 bash。处理方式很简单所有脚本统一用#!/bin/bash作为 shebang执行时也用bash xxx.sh而不是sh xxx.sh。Bash 版本也值得注意。合集里个别脚本用到了数组和关联数组比如并发获取多台机器 hostname 那段逻辑Bash 4.x 才能完整支持。CentOS 6 自带的 Bash 4.1CentOS 7 是 4.2一般够用如果哪台机器还是 Bash 3.2macOS 自带版本跑数组相关脚本会间歇性出问题。这种差异排查起来最耗时间我一般先统一环境再跑批量脚本。2.2 按脚本用途准备依赖命令mailx、mysql、sysstat 这些一个都不能少这套合集本来就是在联网且装了基础软件包的机器上收集来的换到新环境依赖基本都要自己补。不同的脚本依赖不同的外部命令其中几个常见的类别如下脚本场景常用命令安装方式CentOS/RHEL邮件告警mailx, sendmail/postfixyum install mailxMySQL 备份mysql, mysqldumpyum install mysql mysql-client或装完整版性能监控sar, iostat, topyum install sysstat流量查看netstatyum install net-tools网络分析iptables系统自带确认服务未禁用判依赖是否齐全有个笨办法直接bash script.sh跑一遍哪个命令缺失就装哪个。但批量处理时我更推荐先把所有脚本里出现过的关键命令列出来统一检查写个循环判断for cmd in mailx mysql mysqldump sar iostat netstat iptables awk grep crontab; do if command -v $cmd /dev/null 21; then echo $cmd OK else echo $cmd MISSING fi donecommand -v只做存在性检查不执行命令本身比which更稳在精简容器里也能用。检查完哪几个 MISSING就集中yum install -y补齐。像 sysstat 这种包装了之后还要等几秒才会生成 /etc/cron.d/sysstat如果脚本马上要采集 sar 数据偶尔会抽风等一分钟再跑更保险。2.3 获取脚本合集并做语法体检bash -n 和 shellcheck 过一遍再上线资源到手后先解压然后别急着跑先做一个批量语法检查。这一步能提前筛掉因为复制粘贴导致的半角全角符号混用、括号不匹配这类问题unzip shell_scripts_2024.zip -d /opt/shell-scripts cd /opt/shell-scripts for f in $(find . -name *.sh); do bash -n $f || echo 语法错误: $f donebash -n只解析语法不执行比直接运行安全得多。初次接触这套合集的人最容易栽在从网页复制代码时引号被转成中文引号bash -n一跑就现形。如果机器上装了 shellcheck我还会补跑一遍shellcheck -f gcc重点看 SC2086变量未加双引号这类问题——这类问题在文件路径含空格时会引发翻车。3. 核心脚本拆解Dos 防御、MySQL 备份、Nginx 日志切割的配置方法3.1 Dos 攻击防范脚本看懂 tail、grep、awk 的组合再把阈值改成你的业务值这套合集的第一个脚本是 Dos 攻击防范。它做的是从 Nginx 日志里找同一分钟内请求数超过阈值的 IP然后调用 iptables 直接 DROP。脚本不长但信息密度很高#!/bin/bash DATE$(date %d/%b/%Y:%H:%M) LOG_FILE/usr/local/nginx/logs/demo2.access.log ABNORMAL_IP$(tail -n5000 $LOG_FILE | grep $DATE | awk {a[$1]}END{for(i in a)if(a[i]10)print i}) for IP in $ABNORMAL_IP; do if [ $(iptables -vnL | grep -c $IP) -eq 0 ]; then iptables -I INPUT -s $IP -j DROP echo $(date %F_%T) $IP /tmp/drop_ip.log fi doneDATE变量取的是当前分钟格式要和 Nginx 默认日志里的时间格式完全对齐tail -n5000只扫最后 5000 行避免全文件扫描拖慢性能。awk {a[$1]}END{for(i in a)if(a[i]10)print i}是统计去重 IP 访问次数这里a[$1]以 IP 为 key 做计数a[i]10就是触发封禁的阈值。实际部署时几个参数要按业务改tail -n5000在高并发站点上可能只覆盖几十秒的日志建议改成tail -n20000阈值 10 次/分钟对于被 CDN 穿透的源站来说太敏感正常业务 5 秒刷一次页面都可能触发我一般调到 60 再观察。还有一点容易踩坑脚本封的是 Nginx 日志里的$remote_addr如果你前面挂了 CDN 或 SLB日志里看到的是 CDN 节点 IP封了等于白封这种情况下要先在 Nginx 配置里打开$http_x_forwarded_for并用真实客户端 IP 做统计否则这个脚本的封禁效果会大打折扣。另外脚本里的 iptables 规则是-I INPUT即插入到规则链最前面生效最快但重启后丢失。想持久化CentOS 6 用service iptables saveCentOS 7 用iptables-save /etc/sysconfig/iptables。我自己更多是把它和 fail2ban 结合用fail2ban 负责常见端口扫描这个脚本只处理 Nginx 层的突发请求两条线不冲突。3.2 MySQL 备份脚本从单循环到多循环搞懂什么时候用 -B 什么时候要逐表导出合集里给了两个 MySQL 备份脚本一个单循环一个多循环。单循环逻辑是枚举所有业务库逐个mysqldump -BDATE$(date %F_%H-%M-%S) HOSTlocalhost USERbackup PASS123.com BACKUP_DIR/data/db_backup DB_LIST$(mysql -h$HOST -u$USER -p$PASS -s -e show databases; 2/dev/null | egrep -v Database|information_schema|mysql|performance_schema|sys) for DB in $DB_LIST; do BACKUP_NAME$BACKUP_DIR/${DB}_${DATE}.sql if ! mysqldump -h$HOST -u$USER -p$PASS -B $DB $BACKUP_NAME 2/dev/null; then echo $BACKUP_NAME 备份失败! fi done这里的egrep -v过滤掉系统库-B参数让 mysqldump 在导出文件里带上 CREATE DATABASE 和 USE 语句恢复时不用手动建库。备份账号密码直接写在脚本里如果服务器有其他人登录这点会有安全隐患——更稳妥的做法是把凭证放在 /etc/my.cnf 的 [client] 段或者用 mysql_config_editor 生成登录路径脚本里只写--login-pathbackup。多循环版本是在数据库之外再套一层表循环每个表单独导出一个文件for DB in $DB_LIST; do BACKUP_DB_DIR$BACKUP_DIR/${DB}_${DATE} [ ! -d $BACKUP_DB_DIR ] mkdir -p $BACKUP_DB_DIR /dev/null TABLE_LIST$(mysql -h$HOST -u$USER -p$PASS -s -e use $DB;show tables; 2/dev/null) for TABLE in $TABLE_LIST; do BACKUP_NAME$BACKUP_DB_DIR/${TABLE}.sql if ! mysqldump -h$HOST -u$USER -p$PASS $DB $TABLE $BACKUP_NAME 2/dev/null; then echo $BACKUP_NAME 备份失败! fi done done多循环的优势是单表损坏时只需要恢复一张表不用整个库回滚劣势是表多的时候备份时间和文件数都成倍增长1000 张表会产生 1000 个小文件后期清理压力很大。我的取舍标准是核心交易库用多循环逐表备份普通业务库用单循环整库备份。另外两个脚本都有同一个隐患——没有清理过期备份的策略跑一个月磁盘就会被撑爆。我会在备份脚本末尾加一段find $BACKUP_DIR -type f -name *.sql -mtime 15 -delete把 15 天前的备份清掉。这个教训是当年某台数据库服务器磁盘被备份文件占满得来的从此之后凡涉及备份的脚本一定会配清理逻辑。3.3 Nginx 日志切割脚本mv 加 USR1 信号重开日志别再用 kill -9 硬怼Nginx 日志切割脚本看起来只有几行但知识点都在最后一行LOG_DIR/usr/local/nginx/logs YESTERDAY_TIME$(date -d yesterday %F) LOG_MONTH_DIR$LOG_DIR/$(date %Y-%m) LOG_FILE_LISTdefault.access.log for LOG_FILE in $LOG_FILE_LIST; do [ ! -d $LOG_MONTH_DIR ] mkdir -p $LOG_MONTH_DIR mv $LOG_DIR/$LOG_FILE $LOG_MONTH_DIR/${LOG_FILE}_${YESTERDAY_TIME} done kill -USR1 $(cat /var/run/nginx.pid)关键动作是mv把正在写入的 access.log 改名然后kill -USR1让 Nginx 重新打开日志文件句柄。很多新手会漏掉最后一行结果发现切完之后的 access.log 文件还在不断变大——因为 Nginx 的 fd 还指向旧文件mv 只改了文件名但没断开文件描述符。USR1 信号是 Nginx 专门用来做日志轮转的网上有些教程用kill -9重启 Nginx 来触发但生产环境这样会中断连接属于血泪教训。执行权限方面如果脚本是用 cron 跑的要注意 cron 环境里的 PATH 可能不包含 /usr/sbin直接执行 kill 或 nginx -s 有可能提示找不到命令。在脚本头部加export PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin是最省心的处理方案。3.4 服务器初始化脚本时区、SELinux、防火墙、内核参数一次搞定初始化脚本是我拿到新服务器第一个跑的。它做的事包括把时区改成 Asia/Shanghai、写入 ntpdate 定时同步、禁用 SELinux、关闭 firewalld、给历史命令加时间戳、SSH 超时设为 600 秒、禁止 root 远程登录、内核参数追加到 sysctl.conf 等。其中两个细节值得展开if egrep 7.[0-9] /etc/redhat-release /dev/null; then systemctl stop firewalld systemctl disable firewalld elif egrep 6.[0-9] /etc/redhat-release /dev/null; then service iptables stop chkconfig iptables off fi这段是在区分 CentOS 6 和 CentOS 7 的防火墙管理方式。CentOS 6 用 service/chkconfigCentOS 7 用 systemctl同一个动作两套命令。如果你的机器是 CentOS 8 以上egrep 7.[0-9]不会匹配所以我一般会把判断条件改成rpm -q systemd /dev/null 21用 systemd 是否存在来判断兼容性更好。另一个要注意的是 SELinux 禁用。脚本改的是/etc/selinux/config把permissive替换成disabled但这个改动要重启才能完全生效。getenforce如果不输出 Disabled说明当前还是在 enforcing 或 permissive 状态用setenforce 0可以临时切到 permissive免重启。新装机器可以先跑脚本再重启存量机器则需要额外处理。内核参数那段往 /etc/sysctl.conf 里追加 tcp_syncookies、tcp_max_tw_buckets 等改完后要sysctl -p让配置生效脚本里没做这一步需要手动补。4. 排查这套脚本最容易翻车的几个地方和对应解决办法4.1 现象脚本里 mysqldump 报错但错误信息被吞了备份失败却不知道为什么原因在第 41 行2/dev/null。脚本作者把标准错误重定向到了空设备好处是执行过程不会有报错刷屏坏处是出了问题你完全看不到原因。备份失败可能是账号密码错、磁盘满、表被锁但日志里只有一句“备份失败”信息量太少。解决调试阶段删掉2/dev/null改成2/tmp/mysql_backup_error.log把错误留痕。也可以保留重定向但把if ! mysqldump ...的条件改成if mysqldump ... 2$ERR_LOG; then这样的正向写法错误日志单独存放不影响脚本判断逻辑。4.2 现象Nginx 日志切割后 access.log 还在变大旧文件也不再写入原因只 mv 了文件没有发kill -USR1或者 /var/run/nginx.pid 不存在信号没送出去。还有种情况是 Nginx 进程监听着多个 worker信号只给了 master 但日志缓存还没写尽看起来像没切成功。解决先检查 pid 文件是否真实存在不存在就从ps -ef | grep nginx里找 master 进程 PID。发完 USR1 后用lsof -p $(cat /var/run/nginx.pid) | grep access.log确认文件句柄是否已经指向新文件。如果脚本是在 cron 里跑还可能是 PATH 问题导致找不到 kill 命令在脚本头部强制 export PATH 最省心。4.3 现象iptables 封禁 IP 后过几分钟又失效被封的 IP 重新出现在日志里原因DDOS 脚本用iptables -I INPUT添加的规则没有持久化。iptables 规则默认只存在内存中重启即丢服务重启后恶意 IP 又恢复了正常访问。解决写完规则后执行iptables-save /etc/sysconfig/iptables。CentOS 7 的 firewalld 和 iptables 服务共存时会互相干扰如果用的是 firewalld建议iptables-save后再用firewall-cmd --reload验证规则是否还在。另外有些云服务器厂商的安全组是在虚拟化层拦截服务器内部的 iptables 规则对某些攻击流量根本不生效这种模式下调 iptables 是心态问题只能靠安全组或高防接口来封。4.4 现象同一个脚本在 CentOS 7 上跑得好好的搬到 Ubuntu 上报错一堆原因这两套系统的命令默认路径和包管理机制差异很大。CentOS 的yum install mailxUbuntu 上要apt install mailutilsservice iptables stop这种写法在 Ubuntu 上可能提示不存在。另外 Ubuntu 默认的/bin/sh指向 dash脚本里如果用了[[ ]]或数组直接sh script.sh跑会各种诡异报错。解决明确用bash script.sh或检查 shebang 是否为#!/bin/bash。涉及 iptables、firewalld 的脚本尽量只在 RHEL 系机器上跑涉及 SSH 批量执行的脚本则要小心目标机器是否支持同样的ssh -p参数写法参数细节建议打开ssh -V确认版本后再批量操作。4.5 现象定时任务里跑监控脚本总是不输出手工执行却一切正常原因cron 的最小环境变量集只有 PATH/usr/bin:/bin脚本里用到的命令可能装在 /usr/local/bin 或 /usr/sbin直接不被识别。另一个坑是脚本依赖的相对路径./conf.ini这种写法在 cron 的工作目录下根本找不到文件。解决脚本开头固定cd $(dirname $0)切到脚本所在目录再 export PATH 补全常用命令路径。如果要调脚本里的绝对路径建议把所有路径写成全局变量比如LOG_DIR/var/log/nginx集中维护比散落在各处改起来方便得多。排查时先看 cron 的邮件输出或/var/log/cron日志能少走很多弯路。5. 验证沙箱环境跑通这三个脚本再上生产拿到这套脚本后别直接在核心生产服务器上第一次执行。我的做法是先在本地用虚拟机或容器搭一个模拟环境把最容易改出问题的三个脚本线上验证一遍。先建一个测试用的 Nginx 访问日志模拟某种攻击特征手动往 access.log 里写入 20 条来自同一 IP 的记录然后执行 Dos 防御脚本再检查 iptables 规则和 drop_ip.logecho 192.168.1.88 - - [01/Dec/2024:10:15:00 0800] GET / HTTP/1.1 200 1024 /usr/local/nginx/logs/demo2.access.log bash ddos.sh iptables -vnL INPUT | grep 192.168.1.88 cat /tmp/drop_ip.log如果iptables -vnL输出里能看到源地址为 192.168.1.88 的 DROP 规则同时 drop_ip.log 有对应记录说明整个链路走通了。这里注意测试日志的时间戳要跟date %d/%b/%Y:%H:%M在同一个分钟段内否则脚本会因为匹配不到当前分钟而跳过处理——这一步是最容易自测失败的。接着验证 MySQL 备份脚本。先造两个测试库和几张表跑多循环备份脚本然后随机挑一张表模拟损坏再恢复mysql -e create database testdb1; create table testdb1.t1(id int); insert into testdb1.t1 values(1); bash mysql_backup_multi.sh mysql -e drop table testdb1.t1; mysql testdb1 /data/db_backup/testdb1_$(date %F_%H-%M-%S)/t1.sql mysql -e select * from testdb1.t1;恢复后能查到id1就证明备份文件有效。这类验证建议纳入每次备份脚本调整后的例行步骤不要只看备份文件生成了就以为万事大吉——曾经遇到过一次 mysqldump 因为字符集问题导出文件全程报错但返回码是 0恢复阶段才发现数据全是乱码从那以后我每次调整备份脚本都会强制走一遍“备份 → 删表 → 恢复 → 校验数据”的完整流程校验脚本也一并写进了 crontab。最后验证 Nginx 日志切割。先往 access.log 里随便写几行执行切割脚本确认旧文件带日期后缀出现在月份目录里再等一下确认新的 access.log 文件已重新生成并且写入生效echo test /usr/local/nginx/logs/default.access.log bash cut_nginx_log.sh ls -l /usr/local/nginx/logs/$(date %Y-%m)/ echo test2 /usr/local/nginx/logs/default.access.log sleep 1 tail -1 /usr/local/nginx/logs/default.access.logls能看到default.access.log_前一天日期这个文件同时tail能看到最新的 test2 写入了新 access.log切割流程才算闭环。这三个脚本验证完整套合集的其余脚本依葫芦画瓢按场景从易到难慢慢加。脚本这种工具验证过一次就有底了关键是养出习惯——从那以后我每次把新脚本接入 crontab 前都会强制在沙箱里走一遍全流程而不是直接拉去生产环境赌运气。这套方法帮你省下的排查时间远比你想象中多希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询