Linux Shell 编程实战:让自动化替你“搬砖”
引言
如果你是一个运维工程师,每天可能要重复执行几十次同样的命令——登录服务器、查日志、清缓存、重启服务……这些重复劳动不仅枯燥,而且容易出错。
如果你是一个开发人员,每次部署都要手动敲一串命令,环境稍微有点差异就报错,排错半天。
如果你是一个刚接触 Linux 的新手,面对黑乎乎的终端,不知道从哪里下手。
其实,这些问题都有一个共同的解决方案——Shell 脚本。
Shell 脚本本质上是 Linux 命令的“批处理”文件。把你平时手动敲的那些命令按顺序写到一个文件里,加上一点逻辑判断和循环,它就变成了一个自动化工具。一次编写,永久复用。可以说Shell脚本是Linux操作系统的精华,不懂Shell那就没掌握Linux操作系统运维的精髓。
今天这篇文章,我们就来系统学习 Linux Shell 编程:从基础语法到流程控制,从函数封装到调试技巧,再到几个拿来就能用的实战案例。读完这篇,你就能写出自己的第一个生产级脚本。
一、Shell 是什么?为什么值得学?
Shell 是用户与 Linux 内核之间的桥梁。你在终端里敲的每一个命令,都是 Shell 在帮你解释并调用内核执行。
Shell 不仅仅是一个命令解释器,它本身也是一门功能相当强大的编程语言,易编写、易调试、灵活性强。
Shell 脚本的核心价值在于自动化:
常见的 Shell 类型包括 Bash(最主流,Linux 默认)、Zsh、Ksh 等。Bash 凭借强大的脚本功能和广泛的社区支持,成为生产环境的首选。
💡 一个真实的效率对比:手动操作,每小时仅能处理 5-10 台服务器;而通过 Shell 脚本,单台服务器操作时间可压缩至秒级,配合循环结构可同时管理数百台设备,效率提升数十倍。
二、第一个 Shell 脚本:Hello World
在开始之前,我们先写一个最简单的脚本,感受一下流程。
第一步:创建脚本文件
第二步:写入内容
#!/bin/bash# 这是我的第一个 Shell 脚本echo "Hello, World!"
#!/bin/bash 是 shebang,告诉系统用哪个解释器来执行这个脚本#echo
第三步:赋予执行权限并运行
chmod +x hello.sh./hello.sh
输出:
💡 小贴士:脚本也可以用 bash hello.sh 或 sh hello.sh 直接运行,无需执行权限。
三、变量:脚本的“记忆单元”
变量是编程语言的基石。Shell 中的变量无需声明类型,直接赋值即可使用。
3.1 变量定义与引用
# 定义变量(等号两侧不能有空格!)name="Linux Shell" # 字符串count=100 # 数字(Shell 中默认也是字符串)pi=3.14 # 浮点数# 引用变量(加 nameecho 符号推荐使用 var,避免歧义3.2 单引号 vs 双引号字符串可以用单引号或双引号,区别很大:name="Alice"echo 'Hello, name(原样输出,变量不解析)echo "Hello, 0当前脚本的名称$1~$9脚本的第 1~9 个参数$#传递的参数个数$*所有参数(作为一个整体字符串)$@所有参数(每个作为独立字符串)$?上一条命令的退出状态码(0=成功,非0=失败)$0"echo "第一个参数: #"echo "所有参数: {fruits[0]}# 输出:apple# 访问所有元素echo {#fruits[@]} # 输出:3# 遍历数组for fruit in "fruit"done四、流程控制:让脚本有“脑子”有了变量只能存数据,有了流程控制,脚本才能做判断、走分支、循环执行——这才是编程语言的灵魂。4.1 if 条件判断if 语句支持数值、字符串、文件状态等多种判断。基本语法:if [ 条件 ]; then # 条件成立时执行elif [ 另一个条件 ]; then # 另一个条件成立时执行else # 所有条件都不成立时执行fi常见条件测试:测试类型运算符含义数值比较-eq等于-ne不等于-gt大于-lt小于-ge大于等于-le小于等于文件测试-f存在且为普通文件-d存在且为目录-e文件存在-x文件可执行字符串=相等!=不等-z为空实战示例:#!/bin/bash# 数值比较a=10if [ a 大于 5"fi# 文件存在性检查if [ -f "/etc/passwd" ]; then echo "passwd 文件存在"else echo "passwd 文件不存在"fi# 字符串匹配(推荐使用 [[ ]])if [[ "1in start) echo "启动服务..." ;; stop) echo "停止服务..." ;; restart) echo "重启服务..." ;; *) echo "用法: file"done# 遍历数组files=("log1.txt" "log2.txt" "log3.txt")for file in "file"done# 数字序列循环for i in {1..5}; do echo "第 i 次循环"done实战:批量重命名文件:# 将所有 .txt 文件重命名为 .backupfor file in *.txt; do mv "{file%.txt}.backup"done4.4 while 循环while 循环适合不确定次数的场景,条件为真时持续执行:#!/bin/bashcount=5while [ count" count=count-gt5 ]; do echo "计数: ((count +1))done4.6 循环控制:break 和 continue# break:跳出整个循环for i in {1..10}; do if [ idone# 输出:1 2 3 4# continue:跳过本次循环for i in {1..5}; do if [ idone# 输出:1 2 4 5五、函数:让代码可复用函数是模块化编程的核心。把重复的逻辑封装成函数,脚本更清晰、更易维护。5.1 定义与调用# 定义函数(两种写法等价)function greet() { echo "Hello, 1!"}# 调用函数(不加括号)greet "World" # 输出:Hello, World!5.2 函数参数与返回值函数通过 $1、$2 等位置变量接收参数。返回值用 return 指定(0-255),1 local dest=src" "dest" || echo "备份失败"}# 带返回值的函数check_number() { if [ ? -eq 0 ]; then echo "是正数"fi
5.3 局部变量
用 local 关键字声明的变量只在函数内部有效,不会污染全局:
#!/bin/bashmy_func() { local var="我是局部变量" echo "函数内: var" # 输出为空,因为 var 是局部变量
六、调试技巧:让 Bug 无处遁形
Shell 脚本的调试是新手最容易卡住的地方。下面介绍几种实用的调试方法。
6.1 echo 大法(最基础)
在关键位置打印变量值,是最简单直接的调试方式:
#!/bin/bashname="Alice"echo "DEBUG: name=name"set +x # 关闭调试模式
输出会显示每一条命令及其展开后的结果,非常适合定位逻辑错误。
6.3 set -e:遇错即停
默认情况下,脚本中某条命令失败后会继续执行,可能导致更严重的连锁问题。set -e 让脚本在遇到任何错误时立即退出:
#!/bin/bashset -e # 任何命令失败就退出rm /nonexistent/file # 这行会报错,脚本立即退出echo "这行不会执行"
6.4 组合技:set -euxo pipefail
这是生产环境脚本的黄金组合:
#!/bin/bashset -euxo pipefail
各选项含义:
6.5 trap:捕获错误与信号
trap 可以在脚本被中断或出错时执行清理操作:
#!/bin/bashcleanup() { echo "脚本被终止,执行清理..." rm -f /tmp/temp_file}# 捕获 Ctrl+C 和脚本错误trap cleanup SIGINT SIGTERM ERR# 正常逻辑...
6.6 语法检查:bash -n
不执行脚本,仅检查语法错误:
七、实战案例:拿来就能用
案例一:批量检查服务器存活
#!/bin/bash# check_servers.sh - 批量 Ping 检测服务器存活servers=("192.168.1.1" "192.168.1.2" "192.168.1.3")for ip in "ip> /dev/null 2>&1; then echo "✅ ip 不可达" fidone
案例二:Nginx 服务管理脚本
#!/bin/bash# nginx_ctl.sh - Nginx 服务管理NGINX_HOME="/usr/local/nginx"NGINX_PID="NGINX_PID ] &&kill-0NGINX_PID)2>/dev/null; then echo "Nginx 已经在运行" else NGINX_PID ]; then kill -QUIT NGINX_PID) echo "Nginx 已停止" else echo "Nginx 未运行" fi}reload() { if [ -f (cat 1 in start) start ;; stop) stop ;; reload) reload ;; restart) stop && sleep 1 && start ;; *) echo "用法: (echo 5}' | sed 's/%//') mount=line |awk'{print usage-gtmount 使用率已达 EMAIL fidone
八、生产环境最佳实践
8.1 脚本头部模板
#!/bin/bash#-------------------------------------------------------------------# 脚本名称: xxx.sh# 功能描述: xxx# 作者: xxx# 版本: 1.0# 创建日期: 1rm 1"rm "(date'+%Y-%m-%d %H:%M:%S')] $*" >> /var/log/my_script.log}log "脚本开始执行"
总结
Shell 编程是 Linux 运维和自动化领域的核心技能。从基础语法到流程控制,从函数封装到调试技巧,掌握这些知识,你就能把日常的重复劳动交给脚本去完成。
记住三句话:
- Shell 是人与系统交互的桥梁
- 脚本的本质是命令的自动化组合
- 先能跑,再优化:不要追求一开始就写出完美的脚本,先写出能用的,再逐步完善。
Shell 脚本的威力在于——一次编写,永久复用;一处编写,处处运行。希望这篇文章能帮你迈出 Shell 编程的第一步,写出属于你自己的自动化工具!
本篇文章主要是让读者对shell编程有一个大致的认识和了解,后续将带您更加深入的学习shell编程的相关知识,如果你有任何问题或经验分享,欢迎在评论区留言讨论!