ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Shell脚本示例免费下载:7个实战Bash脚本搞定Linux运维高频场景

Shell脚本示例免费下载:7个实战Bash脚本搞定Linux运维高频场景 Shell脚本这东西入门之后真就离不开。不管是做运维、搞开发还是自己折腾服务器几个基础的bash脚本能帮你把重复劳动压缩到一条命令。标题里的Basic Shell Script Examples [Free Downloads]听起来很直白但它背后其实是运维日常里最高频的一批场景文件批量处理、日志清理、服务器探测、配置备份。我拿到这套示例后第一反应是终于有一套不用自己从零摸爬滚打的脚本集合了下载下来改改路径就能跑。对刚接触Shell的新手来说这些示例能帮你建立脚本到底长什么样、该按什么套路写的直观认知对已经写过一阵脚本但习惯比较随意的朋友来说里面关于参数校验、退出码处理和日志输出的风格也很值得对照参考。这套示例的设计思路很典型每个脚本都尽量保持单文件、少依赖用最基础的bash命令组合完成任务这也正是我平时给新人推荐的风格。1. 基础Shell脚本示例解决的痛点与适用人群1.1 Shell脚本到底能解决什么问题很多刚接触命令行的朋友会觉得Shell脚本不就是把几条命令堆在一起吗这个理解方向没错但实际用起来差别很大。Shell脚本的真正价值在于把你平时在终端里反复敲的命令序列固化下来变成可重复、可传参、能自动执行的小工具。举个例子你每天上班第一件事是登录服务器检查磁盘、看服务状态、拉取最新日志。这一步如果手敲至少五六分钟还得记住一堆命令参数。写成脚本后一条./check_env.sh就全搞定输出结果还比你肉眼看得清晰。再比如需要批量重命名上百个文件、定期清理过期日志、临时探测几十台服务器的连通性这些场景靠手动操作不仅效率低还容易出错。脚本能把操作步骤固定下来配合cron定时执行很多日常维护基本就不用再人工盯了。生活里最贴切的类比是做饭你不会每次炒菜都去翻菜谱、现切葱姜蒜、临时调火候而是把一套成熟的做法记在脑子里按固定流程走中间还能根据食材情况灵活调整参数。Shell脚本就是把你那套成熟做法写成菜谱笔记下次直接照做省时又稳。1.2 这套免费示例资源适合谁来用我用了这套Basic Shell Script Examples之后发现它的定位非常精准主要是三类人。第一类是刚入门的新手。很多人学Shell卡在语法都认识但不知道怎么写一个完整的脚本。这套示例的价值是给了你一个可以对照的样板每个脚本都不长注释清晰变量命名规整读完就明白一个生产环境可用的脚本该具备哪些基本要素。第二类是日常需要和Linux服务器打交道的开发者、测试人员。你可能不需要天天写复杂脚本但经常要做文件操作、日志排查、环境检查这类事情。从这套示例里直接改一个适合自己场景的版本比从零写要快得多。第三类是运维和系统管理员。虽然这类人群通常已经具备一定的脚本能力但基础示例这件事很容易被忽视。越是基础的东西越需要一套规范来兜底。这套示例里的参数校验、退出码处理、日志输出格式正好可以当作团队内部脚本规范的参考模板。2. 示例脚本的整体设计思路与通用约定2.1 示例脚本的选取逻辑这套示例里的脚本数量不算多但每个都是高频场景。我仔细过了一遍发现它的选取逻辑很清晰覆盖Shell日常使用的四个核心方向——文件操作、信息收集、批量处理和备份清理。文件操作方向选了批量重命名和文件类型统计这两个场景几乎每个用Linux的人都遇到过。信息收集方向有系统环境检查和服务端口探测属于排查故障时最常用的手段。批量处理方向是批量探测多台服务器连通性这个在有几十台机器的小规模环境里特别实用。备份清理方向则是日志清理和配置备份这两件事都是crond任务里出现频率最高的。为什么选这些而不是更花哨的东西因为基础脚本的定位是拿过来就能用而不是演示某个炫酷技巧。过于复杂的脚本会引入太多环境依赖和调试成本反而不利于新手理解。这套示例还有一个特点脚本全部使用POSIX风格兼容的写法尽量避免GNU扩展特性。这样在Ubuntu、CentOS、macOS自带的bash环境下都能跑。作者没有刻意追求一行流的写法而是选择清晰、可读的常规写法这个取舍我很赞同。脚本是给人读的其次才是让机器执行。追求代码精简到极致往往会给后续维护埋坑。2.2 脚本命名与参数设计的通用约定看完这套示例可以总结出几条通用的脚本编写约定这些约定也应该是你写任何Shell脚本时默认遵守的。命名规则方面脚本文件名用英文小写加下划线例如rename_files.sh、clean_logs.sh。文件名就能说明用途不要用test1.sh这类毫无信息量的名字。脚本内部变量名要见名知意$file_count比$n好得多$backup_dir比$d清楚得多。这套示例在命名上很规范直接当作标准来用就行。参数处理方面每个脚本都支持命令行传参并且有参数个数校验。比如日志清理脚本要求至少传入一个目录路径脚本启动时会检查参数个数不够就打印用法提示然后退出。这样设计的好处是双重的一方面防止误操作另一方面也方便接入cron时检查参数是否写全。退出码约定这是很多入门教程忽略但生产环境极其重要的点。脚本正常执行完返回0任何错误情况返回非0。这套示例里常见做法是遇到错误时执行exit 1这样上层调度程序比如cron或者jenkins可以通过退出码判断任务是否成功出问题能第一时间报警。我在实际工作中就遇到过因为脚本没有正确退出码导致监控系统判断失误的情况排查半天才发现是脚本里exit 0放错了位置。2.3 免费下载资源的组织方式这套示例在资源组织上也花了不少心思。每个脚本独立成一个文件配套一个简短的说明文档写明适用场景、依赖命令、使用示例。没有搞成一个大杂烩压缩包而是保持一个脚本一个文件的结构这样你只需要下载自己需要的那一个拿到就能放进对应的工具目录里。下载解压后的目录结构和内容大致是这样的shell-script-examples/ ├── README.md ├── scripts/ │ ├── rename_files.sh │ ├── count_file_types.sh │ ├── check_system_info.sh │ ├── check_server_port.sh │ ├── batch_ping_check.sh │ ├── clean_old_logs.sh │ └── backup_config.sh └── docs/ ├── rename_files_usage.md ├── clean_logs_usage.md └── ...说明文档里标注了每个脚本的适用环境比如需要bash 4.0依赖gzip命令之类。我建议你拿到手后先花十分钟把README通读一遍了解每个脚本是什么再根据自己的需求逐个试用。磨刀不误砍柴工这个习惯能省掉很多后面踩坑的调试时间。3. 核心示例脚本逐一拆解这里的拆解不会把每个脚本从头到尾念一遍而是挑最有代表性的四个讲清楚它们的设计思路、关键语法和使用方式。你拿到完整代码后对照这部分学习效率会高很多。3.1 文件批量重命名脚本文件批量重命名这个脚本解决的场景非常具体某个目录下有大量文件名带前缀或后缀不统一的情况需要批量改造。手工用mv逐个操作容易漏写个循环又容易在空格文件名上翻车这个示例就用了稳妥的方式处理。以下是该示例的核心逻辑#!/bin/bash # 批量重命名示例将目录下所有 .txt 文件统一加上日期前缀 if [ $# -ne 1 ]; then echo Usage: $0 target_directory exit 1 fi target_dir$1 date_prefix$(date %Y%m%d) if [ ! -d $target_dir ]; then echo Error: $target_dir is not a valid directory exit 1 fi count0 for file in $target_dir/*.txt; do if [ -f $file ]; then filename$(basename $file) new_filename${date_prefix}_${filename} mv $file $target_dir/$new_filename count$((count 1)) echo Renamed: $filename - $new_filename fi done echo Done. $count files renamed.这段脚本有几个细节值得特别注意。if [ $# -ne 1 ]是参数个数检查确保调用时给出了目标目录。这个脚本少传参数就直接退出不打日志不误操作。$target_dir/*.txt中的双引号是关键路径含空格时不会出问题。basename提取文件名date %Y%m%d生成日期前缀。整个脚本没有使用复杂的find命令只用最基础的循环和字符串拼接在任何Unix环境下都能稳跑。我自己试跑的时候发现一个小问题如果目标目录下原本没有.txt文件for循环里$file会直接等于/path/*.txt这个字面量导致误判。示例脚本里用[ -f $file ]做了文件存在性判断这样既能把这种情况兜住也不会因为目录存在但无匹配文件而报错。这个细节非常实用很多新手写循环时会踩这个坑。3.2 定时日志清理脚本日志清理是所有运维场景里最刚需的一个。系统日志、应用日志、nginx访问日志日积月累能撑爆磁盘。这个示例实现的是清理指定目录下N天前的日志文件整体逻辑干净利落。#!/bin/bash # 清理旧日志示例删除指定目录下超过 N 天的 .log 文件 if [ $# -ne 2 ]; then echo Usage: $0 log_directory days_threshold exit 1 fi log_dir$1 days$2 if [ ! -d $log_dir ]; then echo Error: $log_dir is not a valid directory exit 1 fi # 用 find 找出指定天数前修改过的日志文件 find $log_dir -name *.log -type f -mtime $days -exec rm {} \; echo Log cleanup completed. Removed logs older than ${days} days from ${log_dir}这个脚本最核心的是find命令的-mtime $days参数。-mtime N表示查找修改时间超过N天的文件N是大于N天N是正好N天-N是N天以内。示例里用的是超过N天也就是删除N天前的日志这是日志清理最常见的需求。-exec rm {} \;是find常用的执行删除方式花括号{}会被替换为找到的每个文件名末尾的分号需要转义成\;。这条命令写起来看着怪但它是find执行操作的标准姿势。除了rm你还可以换成-exec ls -lh {} \;能先把要删的文件列表打出来看看防止误删。实际用的时候我建议先加-print参数把匹配的文件打出来确认一次再真正删除。这个习惯能避免不少事故。等确认无误后再配合cron实现定时清理。cron配置我后面会讲到。3.3 多服务器连通性检查脚本涉及多台机器的场景手工一台台ping太蠢这个脚本就是为了解决批量探测问题。#!/bin/bash # 批量探测多台服务器连通性示例 if [ ! -f $1 ]; then echo Usage: $0 server_list_file echo server_list_file: 每行一个IP或域名 exit 1 fi server_file$1 while IFS read -r server; do # 跳过空行和注释行 [ -z $server ] continue [[ $server \#* ]] continue if ping -c 1 -W 2 $server /dev/null 21; then echo [OK] $server is reachable else echo [FAIL] $server is not reachable fi done $server_file这个脚本的输入是一个服务器列表文件每行一个IP或域名。while IFS read -r server这种写法是逐行读取文件的标准姿势IFS确保行首行尾空格不被吃掉-r防止反斜杠被转义。这两处细节如果省略处理某些格式的文件时会静默出错。脚本里对空行和注释行的处理也是有心了。[ -z $server ] continue跳过空行[[ $server \#* ]] continue跳过以#开头的注释行。你可以在列表文件里写一些说明注释脚本会智能跳过不会把它们当真IP去ping。ping参数-c 1 -W 2的意思是只发一个包等待超时2秒。这样每台机器最多2秒内能出结果20台机器撑死40秒就全探测完了。输出结果用了[OK]和[FAIL]的标记方便后面接grep过滤只看到失败的那几台。我拿这个脚本跑了机房里的30台机器整个流程大概40秒输出一目了然。相比自己手动一台台ping效率提升是实打实的。3.4 配置备份归档脚本最后一个核心示例是配置备份。服务器配置文件改动前最好备份一份防止改坏了没法恢复。这个脚本的思路是把指定目录打包成一个带时间戳的压缩包存到备份目录。#!/bin/bash # 配置备份示例将 /etc/nginx 打包为带时间戳的 tar.gz 备份 if [ $# -ne 2 ]; then echo Usage: $0 source_dir backup_base_dir exit 1 fi source_dir$1 backup_base$2 if [ ! -d $source_dir ]; then echo Error: source directory $source_dir does not exist exit 1 fi # 生成备份目录按月份组织 month_dir${backup_base}/$(date %Y%m) mkdir -p $month_dir # 生成带时间戳的备份文件名 stamp$(date %Y%m%d_%H%M%S) backup_file${month_dir}/$(basename $source_dir)_${stamp}.tar.gz # 打包压缩 tar -czf $backup_file -C $(dirname $source_dir) $(basename $source_dir) echo Backup created: $backup_file这个脚本在细节上很讲究。-C参数先切换到上级目录再打包指定的子目录名这样压缩包解压出来不会带一大串绝对路径而是直接就是目录名恢复的时候方便。时间戳精确到秒同一分钟多次备份也不会重名覆盖。备份目录按月份组织mkdir -p自动创建后续找历史版本有清晰的路径。备份这件事最怕的就是备份文件本身把磁盘占满了。建议配合定时任务的同时也定期清理一下超过一定时间的备份。比如只保留最近三个月的备份这个可以用前面日志清理的思路扩展出来。实测中我用它备份了nginx配置生成的tar.gz文件只有几十KB恢复时一条tar -xzf就搞定。虽然小但关键时刻能救命。配置备份这个习惯越早养成越好。4. 实操过程与关键环节实现前面拆解了核心脚本的设计思路这一部分我完整走一遍从下载到实际部署运行的全流程让没用过这些脚本的朋友能快速上手。4.1 下载后的第一步赋予执行权限与试运行从免费下载页面拿到压缩包后解压到本地目录。在Linux上脚本文件默认可能没有执行权限所以第一件事是给全部脚本加上执行权限tar -xzf shell-script-examples.tar.gz cd shell-script-examples/scripts chmod x *.shchmod x是给脚本文件添加可执行权限。如果没有这一步直接运行会报Permission denied。这也是新手最常见的第一个坑。加完权限后先别急着正式使用。我建议对每个脚本执行一次无参运行看它是否会正确输出用法说明。正常设计的脚本在没有参数时应该打印Usage信息并退出而不是报一堆看不懂的错。这套示例在这方面做得比较规范逐个运行无参命令就能确认脚本基本健康。4.2 用真实场景验证脚本参数我准备了一个测试目录来验证批量重命名脚本。先创建测试文件mkdir /tmp/test_rename cd /tmp/test_rename touch report1.txt report2.txt summary.txt然后运行脚本./rename_files.sh /tmp/test_rename执行后目录下的.txt文件都会加上当天的日期前缀例如20250312_report1.txt。运行过程的输出会显示每个文件的改名情况方便确认。验证日志清理脚本时同样制造一些测试数据mkdir -p /tmp/test_logs touch -d 10 days ago /tmp/test_logs/old.log touch -d 1 day ago /tmp/test_logs/new.log ./clean_old_logs.sh /tmp/test_logs 7第一条touch -d 10 days ago把old.log的修改时间设为10天前第二条设为1天前。运行脚本指定7天阈值结果只有old.log被删除new.log保留。这种验证方法很重要看到实际效果才会对脚本行为有信心。4.3 接入cron实现定时任务这些脚本的价值在手动执行之上更体现在定时执行上。以日志清理为例每天凌晨2点自动清理一次用crontab -e编辑当前用户的cron表添加一行0 2 * * * /path/to/shell-script-examples/scripts/clean_old_logs.sh /var/log/myapp 7 /var/log/clean_logs_cron.log 21这一行cron表达式的含义是每天凌晨2点0分执行一次日志清理。把脚本输出追加到日志文件这样第二天可以检查清理是否正常执行。cron环境变量和终端不一样脚本里用到的命令如果是自定义安装路径建议写绝对路径或者把PATH变量在脚本里显式声明。我刚开始用cron时犯过一个低级错误脚本里用了某个自定义路径的工具直接跑脚本一切正常放到cron后每次都报command not found。原因就是cron的最小化环境里PATH不包含那个工具的目录。解决办法很简单脚本开头加上export PATH/usr/local/bin:$PATH或者直接调用全路径。4.4 参数选择与调整思路这套示例里的参数选择不是拍脑袋决定的每个参数背后都有值得说道的逻辑。以日志清理脚本的days参数为例N应该设多大答案是取决于你的磁盘容量、日志增长速度和保留需求。磁盘大、日志增长慢可以保留30天甚至更多磁盘紧张、日志服务又特别啰嗦那就只保留3到7天。我一般先观察一周内日志占用的磁盘空间增速再反推一个合理保留天数。公式很简单可用磁盘空间 ÷ 日均日志增长量 可以保留的天数再打个八折留点余量。批量重命名脚本的日期前缀格式也是如此。date %Y%m%d生成的是纯数字日期适合排序和回溯。如果你想在文件名里看到的日期更友好可以把格式改成date %Y-%m-%d这个看团队习惯没有标准答案但最好统一。备份脚本的备份目录按年月组织也是我从实践里摸索出来的。如果备份文件全堆在一个目录时间久了文件数量上千列出目录都卡。按月分目录后找某个月的备份非常直观清理过期备份时也只需rm -rf对应月份目录。5. 常见问题与排查技巧实录任何脚本在实际使用中都可能遇到问题这里我把在试用和部署这套示例过程中遇到的典型问题整理成速查表再补几条独家避坑经验。5.1 常见问题速查表现象可能原因解决方案Permission denied脚本文件没有执行权限chmod x script.shbad interpreter: No such file or directory脚本第一行的shebang路径错误脚本在Windows上编辑过导致换行符变成\r检查#!/bin/bash是否正确执行sed -i s/\r$// script.sh清理换行符传参后脚本毫无反应参数校验不通过Usage信息未打印检查调用的参数个数是否匹配用bash -x script.sh追踪执行过程脚本能跑但结果不对for循环处理时没有对文件存在性做判断循环体内加[ -f $file ]判断find命令报错参数太多待删除文件数量特别巨大时参数溢出改用find ... -delete或find ... -exec rm {} cron执行不生效但手动运行正常cron最小化环境缺少必要的PATH配置脚本内显式声明PATH或者使用命令绝对路径5.2 用bash -x追踪执行过程排查脚本问题最有效的工具就是bash -x。这个参数会让bash打印出每条命令的执行过程变量展开后的实际值一目了然。bash -x clean_old_logs.sh /tmp/test_logs 7输出会显示类似这样的过程 [ 2 -ne 2 ] log_dir/tmp/test_logs days7 [ ! -d /tmp/test_logs ] find /tmp/test_logs -name *.log -type f -mtime 7 -exec rm {} ; echo Log cleanup completed....每一个号开头的是展开后实际执行的命令方便你核对变量是否赋值正确、逻辑分支走进的是哪条路径。遇到脚本行为和预期不符时第一反应就开bash -x基本能定位八成问题。还有bash -n可以做语法检查不执行脚本只检查语法错误。上线前跑一遍bash -n script.sh能拦住大部分低级语法笔误。5.3 实战中必须注意的脚本安全事项脚本写出来是给人用的如果负责删文件就得格外小心。这里分享几条我在实战中踩过坑后总结出的安全事项。永远先用echo代替rm。删除类脚本跑正式环境之前先把rm临时改成echo执行一遍看看会删除哪些文件。确认列表没错再改回来。我在这上面栽过一次一条find命令把错误目录下的文件全删了恢复数据折腾了一下午。路径变量一定要用双引号包裹。$log_dir和$log_dir在路径含空格时结果完全不同。Shell对引号的解析机制导致未加引号的变量会被按空格切分成多个词。这条规则适用于所有路径操作和文件操作场景。脚本开头声明set -euo pipefail。set -e让脚本在命令出错时立即退出防止错误继续累积set -u让未定义变量的引用直接报错能发现拼写错误的变量名set -o pipefail让管道中任何一个环节的失败都能被感知。这三个选项组合起来是现代Shell脚本的安全气囊能拦截大量潜在错误。我之前线上跑过一个数据备份脚本某个环节命令失败但脚本继续往下执行最后产出了一个残缺备份haplans的恢复全部失败。后来在所有脚本统一加上set -euo pipefail这类静默失败直接变成显式报错问题就好查多了。对位置参数做好默认值。一些非关键参数可以在脚本里提供默认值这样调用时不必每次都传全。比如日志清理的默认天数可以是7天用户不传时自动使用7。写法是days${2:-7}这种参数展开语法很实用。6. 进阶延伸把示例脚本改造成自己的生产力工具基础示例用顺手之后很自然的想法是基于这些模板扩展成更适合自己工作流的工具。这里简单说几个可以改的方向都是我实际做过的。给脚本加上彩色输出。配合tput setaf或ANSI转义码让OK显示绿色、FAIL显示红色、警告显示黄色。一眼扫过去就能定位问题再也不用逐行读输出文字。把批量重命名的功能扩展成支持正则表达式替换。基础的日期前缀只是入门实际使用中经常需要把report_2023.txt改成report-2023-final.txt之类的复杂规则这就需要在脚本里引入sed或rename命令做模式匹配替换。把服务器连通性检查扩展成端口探测。ping只能确认主机在不在线确认服务正常需要探测端口。用nc -z -w 2 server port可以检测TCP端口是否开放这样就能批量检查线上几十台机器的Web服务是否正常响应。这些扩展方向并不难它们都是基础语法的组合应用。能力是一步步长出来的先掌握基础示例理解每个语法点的作用后面就能根据实际需求拼出更强大的工具。在我自己写的脚本库里大量的代码结构都脱胎于这些基础示例。每次写新脚本时我依然会翻回去看看这套Basic Shell Script Examples确认自己有没有遗漏参数校验或者退出码处理的细节。基础的扎实程度决定了上层工具的可靠性。脚本这东西写一次是够用写扎实才是真正省心。
返回列表