shell脚本编程
目录
前言
Shell 脚本编程是 Linux 运维和开发人员必备的核心技能之一。作为用户与操作系统内核之间的桥梁,Shell 不仅是一系列命令的简单堆砌,更是一门功能完备的编程语言。它能够将繁琐的手动操作转化为高效的自动化流程,让重复性工作变得简单可靠。
一、shell基础入门
1.1 编程语言概述
编程语言是人与计算机沟通的桥梁,根据设计思想和应用场景,主要分为两大类:
面向过程语言 —— 像做菜谱
强调“按步骤执行”,把问题拆解成一系列有序的步骤或函数。
-
代表语言:C语言、Shell脚本
-
适用场景:系统底层开发、自动化运维、任务编排
面向对象语言 —— 像搭积木
强调“以对象为中心”,将数据和行为封装成“类”,通过对象间的交互来构建系统。
-
代表语言:Java、Python
-
适用场景:大型企业级应用、复杂业务逻辑开发
1.2 什么是shell
Shell 能做什么?(定位与能力)
Shell 是用户与内核之间的翻译官,是 Linux 系统中的“万能瑞士军刀”,既是命令解释器,也是一种编程语言。它的核心价值体现在三个层面:
| 能力 | 说明 |
|---|---|
| 命令翻译 | 将用户输入的命令解释并传递给内核,是用户与操作系统内核之间的“翻译官”。 |
| 输入输出管理 | 控制数据的流向(标准输入/输出/错误),并支持重定向和管道,实现命令间的协同。 |
| 编程能力 | 支持变量、条件判断、循环、函数等编程要素,可将多条命令编写成脚本,实现复杂任务的自动化。 |
典型应用场景:
-
软件安装与配置自动化(如一键部署LNMP环境)
-
批量用户管理与权限设置
-
系统日志分析与定时备份
-
服务器资源监控与告警
常见的shell类型:
-
/bin/bash 默认shell
-
/bin/sh 是指向 /bin/bash 的软链接
-
/bin/tcsh 是 csh(C Shell)的增强版。它的语法更接近 C 语言
查看 shell
1. 查看当前所使用的 shell
echo $SHELL
2. 查看系统支持的所有 shell
cat /etc/shells
1.3 shell脚本的概念
Shell脚本,简单说就是把一堆要在终端敲的Linux命令,按顺序写到一个文本文件里,然后一次性交给Shell解释器去执行。它是一种解释型、面向过程的脚本编程语言,功能是把“手动操作”变成“自动执行”。
#!/bin/bash 脚本声明
# 这是一个最简单的脚本 注释
echo "当前时间:" 命令
date
二、shell脚本的编写与执行
2.1 shell脚本的构成
shell 由三部分构成
| 结构元素 | 写法示例 | 作用 |
|---|---|---|
| 1. 解释器声明(Shebang) | #!/bin/bash | 必须放在第一行。告诉操作系统用哪个解释器来执行这个脚本。没有这行,系统会猜,容易出错。 |
| 2. 注释说明 |
# 作者:张三 # 功能:备份日志 |
以 # 开头,给人看的信息。脚本的名称、作者、功能、用法最好都写在开头,方便维护。 |
| 3. 可执行命令 |
echo "ni hao" pwd |
脚本的正文,按从上到下的顺序依次执行。你在终端能敲的命令,都可以写在这里。 |
2.2 创建脚本的流程
创建文件 → 添加权限 → 检查语法 → 执行脚本
vim xxx.sh chmod +x bash -n ./xxx.sh
创建 shell 脚本
2.3 执行方法
| 执行方式 | 命令示例 | 需要执行权限 | 开子进程 | 变量保留 |
|---|---|---|---|---|
| 指定解释器 |
./xxx.sh /xxx.sh |
❌ | ✅ | ❌ |
| 直接执行 |
bash xxx.sh sh xxx.sh |
✅ | ✅ | ❌ |
| source 执行 | source xxx.sh | ❌ | ❌ | ✅ |
| 重定向执行 | sh < xxx.sh | ❌ | ✅ | ❌ |
三、变量基础
3.1 什么是变量
变量是一个用来存放数据的“容器”,并且这个容器有一个名字,方便你随时存取里面的数据。
书写方式为:变量名=变量值(“=” 两边不能有空格)
定义变量 name 和 age
name="张三"
age=18
当 = 号两边有空格时,会当作命令来执行。
规则:
1. 只能包含字母,数字,下划线
2. 不能以数字开头
3. 区分大小写
3.2 变量的引用和输出
引用方法:在变量前加 $ 符号
name="张三"
age=18
echo $name
echo $age
{}符号使用
3.3 echo的高级用法
常用选项:
| 选项 | 作用 | 示例 | 输出效果 |
|---|---|---|---|
-n |
不换行(输出末尾不加换行符) | echo -n "内容:" | 光标停在 : 后面,等待输入,不会换到下一行。 |
-e |
识别转义字符(如 \n 换行、\t 制表符) |
echo -e "a\nb" | 输出两行:ab |
常用转义字符:
| 转义字符 | 实际效果 |
|---|---|
\n → 换行 |
echo -e "a\nb" 输出两行 |
\t → 制表符 |
echo -e "a\tb" 输出 a b(中间有 Tab 空格) |
\c → 不换行 |
echo -e "a\cb" 输出 a(b 被忽略) |
\b → 退格 |
echo -e "123\b456" 输出 12456(删除了 3) |
\\ → 输出 \ |
echo -e "路径\\home" 输出 路径\home |
\$ → 输出 $ |
echo -e "价格\$100" 输出 价格$100 |
四、特殊变量赋值
4.1 单引号和双引号
| 特性 | 双引号 "" | 单引号 ' ' |
|---|---|---|
解析变量($var) |
会解析,输出变量的值 | 不会解析,输出 $var 这个字符 |
解析转义符(\n \t) |
会解析(部分生效) | 不会解析,原样输出反斜杠 |
解析命令替换(`cmd` 或 $(cmd)) |
会执行命令并替换结果 | 不会执行,原样输出 |
| 内部是否还能用引号 | 可以用转义的双引号或单引号 | 内部不能再出现单引号(即使转义也不行) |
name="张三"
单引号:
双引号:
单引号会把内容原样输出,双引号会输出变量值
4.2 反撇号与命令替换
`` 的作用是把命令输出到变量里
用法:
1. ``
time=`date +%T`
echo "当前时间:$time"
2. $()
time=$(date +%T)
echo "当前时间:$time"
4.3 read命令
read 命令输入交互式输入命令。
read -p "请输入姓名:" name
echo "你好,$name"
常用选项
选项 作用 典型示例 补充说明 -p显示提示信息 read -p "请输入姓名:" name替代 echo+read,更简洁,推荐优先使用-n限制输入字符数 read -n 11 phone输入满 N 个字符后自动结束,无需按回车;少于 N 个则需手动回车确认 -s静默模式(输入不可见) read -s -p "请输入密码:" pwd常用于密码输入;注意:结束后需手动 echo换行,否则后续输出会紧贴光标-t设置超时时间(秒) read -t 5 input超时后 read自动退出,可通过$?判断是否超时(非0即为超时)
五、变量运算
5.1 expr命令
expr 是 Linux/Unix 中一个非常古老的表达式计算命令,用于在 Shell 中进行整数运算、字符串操作和逻辑判断。
1. expr 10 + 55 (运算符两边必须有空格)
2. 乘法需要转义
5.2 变量运算
expr 同样支持变量运算:
x=10 y=20
expr $X + $Y # 输出:30
expr $X - $Y # 输出:-10
expr $X \* $Y # 输出:200
expr $X / $Y # 输出:0
expr $X % $Y #输出:10
5.3 $[]和$(())
比expr更简洁:乘法不用转义!
1. $[]
echo $[5 * 6]
2. $(())
echo $((5 * 6))
三种方法对比:
| 方式 | 乘法需转义 | 变量前 $ 是否必须 |
推荐指数 | 说明 |
|---|---|---|---|---|
expr |
✅ 必须(\*) |
✅ 必须($var) |
★★☆ | 老式外部命令,性能较差,仅维护旧脚本时使用 |
$[] |
✗ 不需要 | ⚠️ 可省略,但建议保留 | ★★★ | 已废弃,但某些老版本 Shell 仍支持;不推荐新脚本使用 |
$(( )) |
✗ 不需要 | ⚠️ 可省略,但建议保留 | ★★★★★ | 现代脚本首选,POSIX 标准,性能好,语法清晰 |
5.4 let命令
let 命令会直接修改变量本身。
num=20
let num=num+10
echo $num
简写方式
num=10
let num+=5 # num = num + 5 = 15
let num-=3 # num = num - 3 = 12
let num*=2 # num = num * 2 = 24自增自减:
num=10
let num++ # num变成11
let num-- # num变成10幂运算(let特有):
let num=num**10 # 2的10次方,num变成1024
5.5 bc命令
bc 命令可以计算小数,而 expr 只能计算整数。
echo "scale=2; 10/3" | bc
其中:scale=2 表示保留2位小数
基本用法:
echo "scale=3; 10/3" | bc
echo "5^2" | bc
echo "sqrt(16)" | bc
逻辑运算:
echo "3 > 5" | bc # 输出:0(假)
echo "3 < 5" | bc # 输出:1(真)
echo "10 == 10" | bc # 输出:1(真)
六、变量类型与作用范围
6.1 自定义变量和环境变量
在 Linux Shell 中,自定义变量和环境变量的本质区别在于:能否被子进程继承。
| 对比项 | 自定义变量(本地变量) | 环境变量(全局变量) |
|---|---|---|
| 作用范围 | 仅当前 Shell 进程有效 | 当前 Shell 及其所有子进程均有效 |
| 能否被子进程继承 | ❌ 不能 | ✅ 能 |
| 定义方式 | var=value |
export var=value 或 declare -x var=value |
| 查看所有 | set(含所有变量和函数) |
env 或 export |
| 删除 | unset var |
unset var |
| 生命周期 | Shell 进程结束时销毁 |
同左,但子进程会复制一份副本 |
常见环境变量:
| 环境变量 | 含义 | 示例值 |
|---|---|---|
PATH |
命令搜索路径 | /usr/local/bin:/usr/bin:/bin |
HOME |
用户家目录 | /home/zhangsan |
SHELL |
当前使用的 Shell | /bin/bash |
USER |
当前用户名 | zhangsan |
PWD |
当前工作目录 | /home/zhangsan/project |
OLDPWD |
上一个工作目录 | /home/zhangsan |
LANG |
系统语言编码 | zh_CN.UTF-8 |
TERM |
终端类型 | xterm-256color |
HOSTNAME |
主机名 | my-server |
6.2 只读变量
readonly 是 Shell 中用于将变量或函数设为只读的内置命令。一旦设置为只读,变量的值不能再被修改,也不能被 unset 删除,直到当前 Shell 进程结束。
n=zdw 设置变量
echo $n 查看变量
readonly n 设置只读变量
n=zdw123 修改变量
6.3 位置变量
位置变量是 Shell 脚本中用于接收命令行传入参数的特殊变量。当你执行脚本时跟在脚本名后面的那些参数,就是通过位置变量来获取的。
$0 |
脚本名称(或当前 Shell 名称) | ./test.sh |
$1 |
第 1 个参数 | ./test.sh hello → $1 = hello |
$2 |
第 2 个参数 | ./test.sh hello world → $2 = world |
$3 ~ $9 |
第 3~9 个参数 | $3、$4…… |
${10} |
第 10 个参数(必须加花括号) | ${10}、${11}…… |
$# |
参数个数(不含 $0) |
./test.sh a b c → $# = 3 |
$* |
所有参数视为一个整体字符串 | "$*" → "a b c" |
$@ |
所有参数视为独立的多个字符串 | "$@" → "a" "b" "c" |
sh first.sh zdw 123 456
6.4 预定义变量
预定义变量是 Shell 内置的特殊变量,用于获取脚本运行时的环境信息、进程状态、命令执行结果等。它们由 Shell 自动维护,无需定义即可直接使用。
| 变量 | 含义 | 示例值 | 常用场景 |
|---|---|---|---|
$$ |
当前 Shell 进程 PID | 12345 |
创建唯一临时文件 |
$! |
最后一个后台进程的 PID | 12346 |
后台任务管理 / wait |
$? |
上一条命令的退出状态码 | 0(成功)或 1~255(失败) |
判断命令执行结果 |
ls /etc/passwd
echo $? (输出 0 表示正确)
ls /etcpasswd
echo $? (输出 非0 表示错误)
6.5 export命令
export 是 Shell 中用于将变量或函数标记为环境变量(即导出到子进程)的内置命令。它是 Shell 变量作用域管理的核心工具。
基本用法:
七、重定向与管道
7.1 标准输入输出和错误输出
| 名称 | 文件描述符 | 符号 | 默认指向 | 用途 |
|---|---|---|---|---|
| 标准输入 | 0 |
< 或 << |
键盘 | 读取数据(命令的输入来源) |
| 标准输出 | 1 |
> 或 >> |
终端屏幕 | 输出命令的正常结果 |
| 标准错误输出 | 2 |
2> 或 2>> |
终端屏幕 | 输出命令的错误信息 |
7.2 输出重定向
输出重定向 就是将命令的标准输出(stdout) 和/或 标准错误输出(stderr) 从默认的屏幕改道到文件、设备或另一个命令。
1. 覆盖写入(危险:会清空原文件)
echo "第一行" > file.txt
cat file.txt # 输出:第一行echo "第二行" > file.txt
cat file.txt # 输出:第二行(第一行被覆盖了!)
2. 追加写入(安全:保留原内容)
echo "第三行" >> file.txt
cat file.txt # 输出:第二行\n第三行
3. 分离正确和错误输出:
ls /etc/passwd xxx > ok.txt 2> err.txt
7.3 输入重定向
输入重定向 就是改变命令的输入来源——从默认的键盘改道为文件、字符串或另一个命令的输出。
# 统计文件行数(从文件读取)
wc -l < /etc/passwd 输出:30(/etc/passwd 的行数)
# 对比:不加 < 会把文件名显示出来
wc -l /etc/passwd 输出:30 /etc/passwd(包含文件名)
多行输入:
cat << EOF > config.txt
app_name=MyApp
version=1.0
EOF
7.4 管道操作
管道符 = 把多个命令串联起来
| 命令 | 功能 | 常见示例 | 补充说明 |
|---|---|---|---|
grep |
过滤匹配的行 | cat file | grep "error" |
支持正则;-v 反选,-i 忽略大小写,-c 只计次数 |
sort |
对行进行排序 | cat file | sort |
-r 倒序,-n 按数字排序,-k 指定列,-t 指定分隔符 |
uniq |
去重或统计重复次数 | cat file | uniq -c |
必须搭配 sort 使用(去重相邻行);-c 统计次数,-d 只显示重复行 |
wc |
统计行数、字数、字符数 | cat file | wc -l |
-l 行数,-w 单词数,-c 字节数,-m 字符数 |
cut |
按列提取文本 | cat file | cut -d: -f1 |
-d 指定分隔符,-f 指定列(支持 -f1,3 或 -f1-3),-c 按字符位置 |
1. 查找httpd包
rpm -qa | grep httpd
2. 统计访问量最高的10个IP
cat /var/log/httpd/access_log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
7.5 综合应用实例
自动化备份脚本
#!/bin/bash
BACKUP_DIR="/backup"
DATE=$(date +%Y%m%d)# 创建备份目录(如果不存在)
mkdir -p "$BACKUP_DIR"# 执行备份,将错误输出重定向到 error.log
tar -czf "${BACKUP_DIR}/backup_${DATE}.tar.gz" /home 2> "${BACKUP_DIR}/error.log"# 判断备份是否成功
if [ $? -eq 0 ]; then
echo "备份成功!"
else
echo "备份失败,请查看错误日志!"
fi
执行脚本
sh file01.sh
总结
本文章系统梳理了 Shell 编程的核心知识体系,涵盖以下四个主要方面:
一、Shell 基础与脚本编写
明确了 Shell 作为命令解释器和编程语言的双重身份,掌握了脚本的三要素构成(Shebang 声明、注释说明、可执行命令),以及四种执行方式(直接执行、指定解释器、source 执行、重定向执行)的区别,其中 source 执行会在当前 Shell 中运行,变量得以保留。
二、变量体系
-
变量基础:定义了变量的命名规则与引用方式(
$变量名),掌握了echo的-n(不换行)和-e(识别转义)选项。 -
变量类型:区分了自定义变量(仅当前 Shell 有效)与环境变量(可通过
export传递给子进程),了解了只读变量(readonly)的不可修改特性。 -
特殊变量:掌握了位置变量(
$0~$9、$#、$@、$*)用于接收脚本参数,以及预定义变量($$、$!、$?)用于获取进程信息和命令执行状态。 -
引号规则:单引号原样输出不解析变量,双引号会解析变量和转义符。
三、运算与交互
-
变量运算:对比了
expr(老式,需转义)、$(( ))(现代推荐,整数运算)和bc(支持浮点数)三种方式,明确日常开发优先使用$(( ))和bc。 -
交互输入:通过
read命令配合-p(提示)、-s(静默)、-t(超时)、-n(限制字符数)实现灵活的交互式输入。
四、输入输出与数据处理
-
标准流与重定向:理解了标准输入/输出/错误(文件描述符 0/1/2)的分离设计,掌握了输出重定向(
>、>>、2>、&>)和输入重定向(<、<<、<<<)的用法。 -
管道与文本处理:通过管道符
|串联多个命令,结合grep(过滤)、sort(排序)、uniq(去重统计)、wc(统计)、cut(提取列)等工具,实现强大的数据处理流水线。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐










































所有评论(0)