news 2026/7/26 9:17:43

Linux操作系统-shell编程之认识shell脚本

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux操作系统-shell编程之认识shell脚本

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

在开始之前,我们先写一个最简单的脚本,感受一下流程。

第一步:创建脚本文件

vimhello.sh

第二步:写入内容

#!/bin/bash# 这是我的第一个 Shell 脚本echo"Hello, World!"
  • #!/bin/bashshebang,告诉系统用哪个解释器来执行这个脚本
  • #开头的行是注释,不会被执行
  • echo是输出命令

第三步:赋予执行权限并运行

chmod+x hello.sh ./hello.sh

输出:

Hello, World!

💡小贴士:脚本也可以用bash hello.shsh hello.sh直接运行,无需执行权限。

三、变量:脚本的“记忆单元”

变量是编程语言的基石。Shell 中的变量无需声明类型,直接赋值即可使用

3.1 变量定义与引用

# 定义变量(等号两侧不能有空格!)name="Linux Shell"# 字符串count=100# 数字(Shell 中默认也是字符串)pi=3.14# 浮点数# 引用变量(加 $ 符号)echo$nameecho${name}# 推荐用花括号,避免歧义

关键规则

  • 等号两侧不能有空格
  • 变量名不能以数字开头
  • 可以使用下划线,不能使用破折号或标点符号
  • 变量引用需加$符号
  • 推荐使用${var}而非$var,避免歧义

3.2 单引号 vs 双引号

字符串可以用单引号或双引号,区别很大:

name="Alice"echo'Hello, $name'# 输出:Hello, $name(原样输出,变量不解析)echo"Hello,$name"# 输出:Hello, Alice(变量被解析)

规则

  • 单引号:原样输出,里面的变量和转义字符都不生效
  • 双引号:变量会被解析,转义字符生效

3.3 特殊变量(非常重要!)

Shell 提供了一些内置的特殊变量:

变量含义
$0当前脚本的名称
$1~$9脚本的第 1~9 个参数
$#传递的参数个数
$*所有参数(作为一个整体字符串)
$@所有参数(每个作为独立字符串)
$?上一条命令的退出状态码(0=成功,非0=失败)
$$当前 Shell 的进程 ID

示例

#!/bin/bashecho"脚本名:$0"echo"第一个参数:$1"echo"参数个数:$#"echo"所有参数:$@"

运行:

./test.sh hello world# 输出:# 脚本名: ./test.sh# 第一个参数: hello# 参数个数: 2# 所有参数: hello world

3.4 数组

Shell 支持数组,下标从 0 开始:

# 定义数组fruits=("apple""banana""orange")# 访问单个元素echo${fruits[0]}# 输出:apple# 访问所有元素echo${fruits[@]}# 输出:apple banana orange# 获取数组长度echo${#fruits[@]}# 输出:3# 遍历数组forfruitin"${fruits[@]}";doecho"I like$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-gt5];thenecho"$a大于 5"fi# 文件存在性检查if[-f"/etc/passwd"];thenecho"passwd 文件存在"elseecho"passwd 文件不存在"fi# 字符串匹配(推荐使用 [[ ]])if[["$name"==*"error"*]];thenecho"包含错误信息"fi

💡推荐:使用[[ ]]替代[ ],前者支持更丰富的模式匹配(如通配符*)。

4.2 case 多分支选择

当有多个分支时,case比多个if-elif更清晰:

#!/bin/bashcase$1instart)echo"启动服务...";;stop)echo"停止服务...";;restart)echo"重启服务...";;*)echo"用法:$0{start|stop|restart}";;esac

4.3 for 循环

for 循环用于遍历列表或范围:

# 遍历列表forfileinlog1.txt log2.txt log3.txt;doecho"处理文件:$file"done# 遍历数组files=("log1.txt""log2.txt""log3.txt")forfilein"${files[@]}";doecho"处理文件:$file"done# 数字序列循环foriin{1..5};doecho"第$i次循环"done# C 语言风格for((i=1;i<=5;i++));doecho"第$i次循环"done

实战:批量重命名文件

# 将所有 .txt 文件重命名为 .backupforfilein*.txt;domv"$file""${file%.txt}.backup"done

4.4 while 循环

while 循环适合不确定次数的场景,条件为真时持续执行:

#!/bin/bashcount=5while[$count-gt0];doecho"剩余次数:$count"count=$((count-1))done

4.5 until 循环

until 和 while 相反,条件为假时执行,直到条件变为真:

count=1until[$count-gt5];doecho"计数:$count"count=$((count+1))done

4.6 循环控制:break 和 continue

# break:跳出整个循环foriin{1..10};doif[$i-eq5];thenbreakfiecho$idone# 输出:1 2 3 4# continue:跳过本次循环foriin{1..5};doif[$i-eq3];thencontinuefiecho$idone# 输出:1 2 4 5

五、函数:让代码可复用

函数是模块化编程的核心。把重复的逻辑封装成函数,脚本更清晰、更易维护。

5.1 定义与调用

# 定义函数(两种写法等价)functiongreet(){echo"Hello,$1!"}# 或者greet(){echo"Hello,$1!"}# 调用函数(不加括号)greet"World"# 输出:Hello, World!

5.2 函数参数与返回值

函数通过$1$2等位置变量接收参数。返回值用return指定(0-255),$?获取:

#!/bin/bash# 带参数的函数backup_file(){localsrc=$1localdest=$2cp"$src""$dest"&&echo"备份成功:$dest"||echo"备份失败"}# 带返回值的函数check_number(){if[$1-gt0];thenreturn0# 表示成功/真elsereturn1# 表示失败/假fi}# 调用backup_file"/var/log/syslog""/backup/syslog.log"check_number5if[$?-eq0];thenecho"是正数"fi

5.3 局部变量

local关键字声明的变量只在函数内部有效,不会污染全局:

#!/bin/bashmy_func(){localvar="我是局部变量"echo"函数内:$var"}my_funcecho"函数外:$var"# 输出为空,因为 var 是局部变量

六、调试技巧:让 Bug 无处遁形

Shell 脚本的调试是新手最容易卡住的地方。下面介绍几种实用的调试方法。

6.1 echo 大法(最基础)

在关键位置打印变量值,是最简单直接的调试方式:

#!/bin/bashname="Alice"echo"DEBUG: name=$name"# 打印变量值

6.2 set -x:跟踪执行(最推荐)

set -x会让 Shell 在执行每条命令前,把命令打印出来:

#!/bin/bashset-x# 开启调试模式name="Alice"echo"Hello,$name"set+x# 关闭调试模式

输出会显示每一条命令及其展开后的结果,非常适合定位逻辑错误。

6.3 set -e:遇错即停

默认情况下,脚本中某条命令失败后会继续执行,可能导致更严重的连锁问题。set -e让脚本在遇到任何错误时立即退出:

#!/bin/bashset-e# 任何命令失败就退出rm/nonexistent/file# 这行会报错,脚本立即退出echo"这行不会执行"

6.4 组合技:set -euxo pipefail

这是生产环境脚本的黄金组合

#!/bin/bashset-euxopipefail

各选项含义:

  • -e:命令失败立即退出
  • -u:使用未定义变量时报错
  • -x:打印执行的每条命令
  • -o pipefail:管道中任何命令失败都算失败

6.5 trap:捕获错误与信号

trap可以在脚本被中断或出错时执行清理操作:

#!/bin/bashcleanup(){echo"脚本被终止,执行清理..."rm-f/tmp/temp_file}# 捕获 Ctrl+C 和脚本错误trapcleanup SIGINT SIGTERM ERR# 正常逻辑...

6.6 语法检查:bash -n

不执行脚本,仅检查语法错误:

bash-nscript.sh

七、实战案例:拿来就能用

案例一:批量检查服务器存活

#!/bin/bash# check_servers.sh - 批量 Ping 检测服务器存活servers=("192.168.1.1""192.168.1.2""192.168.1.3")foripin"${servers[@]}";doifping-c1-W1$ip>/dev/null2>&1;thenecho"✅$ip存活"elseecho"❌$ip不可达"fidone

案例二:Nginx 服务管理脚本

#!/bin/bash# nginx_ctl.sh - Nginx 服务管理NGINX_HOME="/usr/local/nginx"NGINX_PID="$NGINX_HOME/logs/nginx.pid"start(){if[-f$NGINX_PID]&&kill-0$(cat$NGINX_PID)2>/dev/null;thenecho"Nginx 已经在运行"else$NGINX_HOME/sbin/nginxecho"Nginx 启动成功"fi}stop(){if[-f$NGINX_PID];thenkill-QUIT$(cat$NGINX_PID)echo"Nginx 已停止"elseecho"Nginx 未运行"fi}reload(){if[-f$NGINX_PID];thenkill-HUP$(cat$NGINX_PID)echo"Nginx 配置已重载"elseecho"Nginx 未运行"fi}case$1instart)start;;stop)stop;;reload)reload;;restart)stop&&sleep1&&start;;*)echo"用法:$0{start|stop|restart|reload}";;esac

案例三:磁盘使用率监控告警

#!/bin/bash# disk_monitor.sh - 磁盘使用率监控THRESHOLD=80EMAIL="admin@example.com"df-h|grep-vE'^Filesystem|tmpfs|devtmpfs'|whilereadline;dousage=$(echo$line|awk'{print $5}'|sed's/%//')mount=$(echo$line|awk'{print $6}')if[$usage-gt$THRESHOLD];thenecho"警告:$mount使用率已达$usage%"|mail-s"磁盘告警"$EMAILfidone

八、生产环境最佳实践

8.1 脚本头部模板

#!/bin/bash#-------------------------------------------------------------------# 脚本名称: xxx.sh# 功能描述: xxx# 作者: xxx# 版本: 1.0# 创建日期: $(date +%Y-%m-%d)#-------------------------------------------------------------------set-euopipefail

8.2 使用绝对路径

在脚本中尽量使用绝对路径,避免因 PATH 环境变量不同导致命令找不到。

8.3 变量加引号

变量引用时始终加双引号,避免空格或特殊字符导致意外解析:

# ❌ 不推荐file=$1rm$file# ✅ 推荐file="$1"rm"$file"

8.4 检查命令是否存在

if!command-vnginx&>/dev/null;thenecho"nginx 命令不存在,请先安装"exit1fi

8.5 函数封装,避免重复

重复的逻辑封装成函数,提高可维护性。

8.6 日志记录

log(){echo"[$(date'+%Y-%m-%d %H:%M:%S')]$*">>/var/log/my_script.log}log"脚本开始执行"

总结

Shell 编程是 Linux 运维和自动化领域的核心技能。从基础语法到流程控制,从函数封装到调试技巧,掌握这些知识,你就能把日常的重复劳动交给脚本去完成。

记住三句话

  1. Shell 是人与系统交互的桥梁:掌握它,你就掌握了 Linux 的“遥控器”。
  2. 脚本的本质是命令的自动化组合:把重复的事写成脚本,让机器替你“搬砖”。
  3. 先能跑,再优化:不要追求一开始就写出完美的脚本,先写出能用的,再逐步完善。

Shell 脚本的威力在于——一次编写,永久复用;一处编写,处处运行。希望这篇文章能帮你迈出 Shell 编程的第一步,写出属于你自己的自动化工具!

本篇文章主要是让读者对shell编程有一个大致的认识和了解,后续将带您更加深入的学习shell编程的相关知识,如果你有任何问题或经验分享,欢迎在评论区留言讨论!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/26 9:15:15

C++模板元编程:从SFINAE到Concepts的编译期条件编程实战

1. 项目概述&#xff1a;当C模板遇上“编译时侦探”如果你写过一段时间的C模板代码&#xff0c;尤其是尝试过写一些通用的库函数或者容器&#xff0c;大概率会遇到一种让人挠头的编译错误&#xff1a;编译器告诉你某个类型没有某个成员函数&#xff0c;或者两个类型无法进行某种…

作者头像 李华
网站建设 2026/7/26 9:12:15

AI情感调谐系统:多模态识别与动态策略生成

1. 项目概述&#xff1a;当AI遇见情感疗愈去年冬天&#xff0c;我接待了一位特殊的来访者——某互联网大厂的中层管理者张女士。在第三次咨询时&#xff0c;她突然崩溃大哭&#xff1a;"医生&#xff0c;我每天给团队做心理疏导&#xff0c;却没人知道我自己已经三个月没睡…

作者头像 李华
网站建设 2026/7/26 9:10:04

视频硬字幕提取终极指南:三步解放被“锁死“的视频内容

视频硬字幕提取终极指南&#xff1a;三步解放被"锁死"的视频内容 【免费下载链接】video-subtitle-extractor 视频硬字幕提取&#xff0c;生成srt文件。无需申请第三方API&#xff0c;本地实现文本识别。基于深度学习的视频字幕提取框架&#xff0c;包含字幕区域检测…

作者头像 李华
网站建设 2026/7/26 9:08:04

Linux命令行JSON处理神器jq详解与应用

1. 为什么每个Linux用户都应该掌握jq在终端处理JSON数据就像试图用剪刀裁切钢板——原始工具完全不对口。我第一次面对数百行的JSON响应时&#xff0c;用grep和awk折腾了整整下午&#xff0c;直到发现jq这个"JSON瑞士军刀"。这个轻量级的命令行处理器不仅能漂亮地格式…

作者头像 李华
网站建设 2026/7/26 9:07:48

Ralph模式:AI编程的自动化迭代革命

1. Ralph现象&#xff1a;当AI编程遇上"放羊哲学"2025年5月&#xff0c;一个名为Ralph的AI编程方法在技术圈掀起了一场静默革命。这个由澳洲前软件工程师、现职业牧羊人Geoffrey Huntley创造的方案&#xff0c;用最简单的技术逻辑颠覆了传统软件开发流程。它的核心思…

作者头像 李华