Linux系统基础13:Shell 脚本入门 新手超详细教程

📅 2026/7/14 10:26:52
Linux系统基础13:Shell 脚本入门 新手超详细教程
Shell 脚本入门 新手超详细教程目录Shell 脚本入门 新手超详细教程一、先搞懂基础概念1. Shell 和 Shell 脚本是什么2. 脚本有什么用3. 我们用哪种 Shell二、第一个 Shell 脚本从创建到运行步骤 1创建脚本文件步骤 2写入脚本内容逐行拆解说明第 1 行#!/bin/bash —— 脚本声明Shebang第 2 行# 我的第一个Shell脚本... —— 注释第 3 行echo 你好Shell脚本 —— 执行的命令步骤 3给脚本加执行权限步骤 4运行脚本方式 1./脚本名 —— 最标准的运行方式推荐方式 2bash 脚本名 —— 不需要执行权限方式 3source 脚本名 / . 脚本名 —— 在当前 Shell 执行三、Shell 变量存数据的容器1. 自定义变量语法规则正确与错误对比引用变量完整例子定义变量并输出2. 变量的其他操作只读变量 readonly删除变量 unset3. 系统内置变量重点脚本传参$1 $2 非常常用例子写一个接收两个参数的脚本 arg_test.sh4. 命令替换把命令的结果存进变量例子把当前时间存进变量四、输入与输出1. echo输出内容2. read接收用户输入交互式脚本基础用法更优雅的写法-p 直接带提示语五、条件判断if 语句1. 条件测试的写法2. 三类常用判断条件① 文件 / 目录判断最常用② 数值比较③ 字符串比较3. if 语句的三种结构结构 1单分支 if实战例子判断目录不存在就创建结构 2双分支 if-else实战例子判断用户是不是 root结构 3多分支 if-elif-else实战例子分数评级六、循环结构重复执行代码1. for 循环按列表循环基础语法例子 1遍历数字打印 1 到 5例子 2批量创建 10 个带序号的文件例子 3遍历当前目录下所有 .txt 文件2. while 循环满足条件就循环基础语法例子从 1 数到 53. break 和 continue七、Shell 函数封装重复的代码1. 函数的定义和调用语法例子写一个打招呼的函数2. 函数传参例子加法函数接收两个参数输出和3. 函数返回值八、完整实战写一个自动备份脚本脚本功能完整脚本 backup.sh逐段拆解运行测试九、新手必踩坑总结十、新手练习建议Shell 脚本是 Linux 自动化的核心技能本质就是把一系列 Linux 命令按逻辑写进一个文本文件里让系统批量自动执行不用你手动一条一条敲命令。小到批量创建文件大到定时备份、自动化部署都可以用 Shell 脚本实现。我们从「什么是脚本」→「第一个脚本怎么写怎么跑」→「变量→判断→循环→函数」逐层递进每个知识点都配可直接运行的例子 逐行拆解 新手踩坑提醒零基础也能跟着学会。一、先搞懂基础概念1. Shell 和 Shell 脚本是什么Shell就是我们一直在用的「命令解释器」比如 bash它负责把你输入的 Linux 命令翻译给内核执行相当于人和系统的翻译官。Shell 脚本把一堆 Linux 命令、逻辑判断、循环按执行顺序写进一个文本文件里交给 Shell 批量执行相当于「命令的批处理文件」。2. 脚本有什么用自动化重复工作比如每天自动备份日志、批量创建 100 个用户、批量修改文件名。定时任务配合 crontab 定时执行比如凌晨自动清理临时文件。降低出错率手动敲命令容易输错写好的脚本一次写对每次运行都一致。3. 我们用哪种 ShellLinux 有很多种 Shell 解释器最主流、所有发行版都默认带的是BashBourne Again Shell我们全程以 Bash 脚本为例讲解脚本后缀一般约定为.sh。二、第一个 Shell 脚本从创建到运行我们写一个最简单的「Hello World」脚本完整走一遍「创建→编写→加权限→运行」的全流程。步骤 1创建脚本文件用 nano 编辑器创建一个叫hello.sh的文件nano hello.sh步骤 2写入脚本内容把下面三行内容复制进去我们逐行解释每一行的作用#!/bin/bash # 我的第一个Shell脚本输出问候语 echo 你好Shell脚本逐行拆解说明第 1 行#!/bin/bash—— 脚本声明Shebang这是脚本的灵魂第一行必须写在文件最开头格式固定#! 解释器的绝对路径。作用告诉系统这个脚本要用/bin/bash这个解释器来执行而不是默认的其他 Shell。新手坑不写这一行也可能能跑但系统会用默认 Shell 解释可能出现兼容问题规范写法必须加。第 2 行# 我的第一个Shell脚本...—— 注释#开头的行都是注释解释器会直接跳过不会执行。作用给人看的说明这段代码是干嘛的写多了自己也忘注释是好习惯。第 3 行echo 你好Shell脚本—— 执行的命令就是我们学过的echo命令作用是在终端打印一段文字。脚本里的命令和你在终端里直接敲的效果完全一样。步骤 3给脚本加执行权限刚创建的脚本默认没有执行权限直接运行会报错这是新手最高频的坑。chmod x hello.sh拆解x就是加上执行execute权限对应我们之前学的文件权限知识。为什么要加Linux 里文件默认不能直接运行必须有 x 权限才能作为程序执行。步骤 4运行脚本有三种运行方式场景不同用法不同新手先记住第一种。方式 1./脚本名—— 最标准的运行方式推荐./hello.sh输出你好Shell脚本为什么要加./代表「当前目录下的」。Linux 不会自动在当前目录找程序必须明确指定路径不然会报错「找不到命令」。方式 2bash 脚本名—— 不需要执行权限bash hello.sh作用直接调用 bash 解释器去读这个脚本文件所以脚本本身不需要 x 权限。场景调试脚本、脚本没加执行权限的时候用。方式 3source 脚本名/. 脚本名—— 在当前 Shell 执行source hello.sh # 或者简写 . hello.sh区别前两种方式会开一个子 Shell 运行脚本脚本里的变量不会影响当前终端这种方式是在当前终端里直接执行脚本里定义的变量、修改的环境退出脚本后还生效。场景修改环境变量、加载配置文件的时候用。三、Shell 变量存数据的容器变量就是给一段数据起个名字后面可以反复用、修改是脚本的基础。1. 自定义变量语法规则变量名变量值⚠️新手第一大坑等号两边绝对不能有空格有空格就会报错这是 Shell 语法最反直觉的地方一定要记住。正确与错误对比✅ 正确写法❌ 错误写法name张三name 张三等号有空格age20age 20引用变量用$变量名或者${变量名}来获取变量的值推荐用大括号边界更清晰。完整例子定义变量并输出#!/bin/bash # 定义变量 nameLinux学习者 age1 # 引用变量输出内容 echo 你好我是$name echo 我已经学习Shell ${age}天了运行输出plaintext你好我是Linux学习者 我已经学习Shell 1天了为什么${age}要加大括号如果后面紧跟其他字符比如${age}天不加括号系统会以为变量名叫age天就会取值失败加括号明确变量名的边界。2. 变量的其他操作只读变量readonly定义后不能修改相当于常量#!/bin/bash pi3.14159 readonly pi pi3 # 这行会报错因为pi是只读的删除变量unset删除后变量就不存在了#!/bin/bash temp临时数据 echo $temp unset temp echo $temp # 输出空因为变量被删了3. 系统内置变量Shell 自带了很多已经定义好的变量直接就能用常用的有变量含义举例输出$HOME当前用户的家目录/home/linuxlearn$PWD当前所在的目录/home/linuxlearn/script$USER当前用户名linuxlearn$HOSTNAME主机名ubuntu$0当前脚本的文件名./test.sh$1、$2、$3...传给脚本的第 1、2、3 个参数脚本后接的参数$#传给脚本的参数总个数传了 2 个参数就输出 2$?上一条命令的执行结果0 代表成功非 0 代表失败0重点脚本传参$1 $2 非常常用运行脚本的时候可以在后面跟参数脚本里用$1$2接收非常灵活。例子写一个接收两个参数的脚本arg_test.sh#!/bin/bash # 演示脚本传参 echo 脚本名字$0 echo 第1个参数$1 echo 第2个参数$2 echo 总共有 $# 个参数运行方式在脚本名后面空格加参数./arg_test.sh 苹果 香蕉输出结果脚本名字./arg_test.sh 第1个参数苹果 第2个参数香蕉 总共有 2 个参数4. 命令替换把命令的结果存进变量可以把一条 Linux 命令的执行结果赋值给变量有两种写法写法 1$(命令)推荐更清晰支持嵌套写法 2命令反引号老写法容易和单引号搞混例子把当前时间存进变量#!/bin/bash # 把date命令的结果赋值给now变量 now$(date %Y-%m-%d %H:%M:%S) echo 当前系统时间是$now运行输出当前系统时间是2024-07-14 15:30:00场景备份文件按时间命名、日志打时间戳都用这个方法。四、输入与输出1.echo输出内容我们一直在用补充两个常用技巧-n输出后不换行默认会自动换行-e支持转义字符比如\n换行、\t制表符例子#!/bin/bash echo -n 不换行输出 echo 第一行 echo -e 换行\n第二行\t制表符2.read接收用户输入交互式脚本让脚本停下来等用户输入内容把输入存进变量里实现人机交互。基础用法#!/bin/bash echo 请输入你的名字 read username echo 你好$username更优雅的写法-p直接带提示语#!/bin/bash read -p 请输入你的名字 username echo 欢迎你$username-pprompt后面跟提示文字不用单独写 echo 提问了更简洁。五、条件判断if 语句脚本不能只会从上到下执行还要能根据条件做不同的操作这就需要 if 判断。1. 条件测试的写法Shell 里判断条件有两种常用写法效果完全一样推荐用第二种test 条件[ 条件 ]方括号写法更常用⚠️新手第二大坑方括号内部两边必须有空格✅ 正确[ $age -gt 18 ]❌ 错误[$age -gt 18]没空格直接报错2. 三类常用判断条件① 文件 / 目录判断最常用用来判断文件是否存在、是文件还是目录、有没有权限写自动化脚本经常用。条件含义-e 文件名exists文件 / 目录是否存在-f 文件名file是否是普通文件-d 文件名directory是否是目录-r 文件名读权限是否可读-w 文件名写权限是否可写-x 文件名执行权限是否可执行例子判断目录是否存在[ -d /data/backup ]② 数值比较注意Shell 里数值比较不能用 必须用专门的参数。条件含义对应数学符号-eqequal 等于-nenot equal 不等于!-gtgreater than 大于-ltless than 小于-gegreater equal 大于等于-leless equal 小于等于例子判断年龄是否大于等于 18[ $age -ge 18 ]③ 字符串比较条件含义str1 str2两个字符串相等str1 ! str2两个字符串不相等-z strzero字符串长度为 0空字符串例子判断用户输入的是不是 yes[ $answer yes ]3. if 语句的三种结构结构 1单分支 if满足条件就执行不满足就跳过。if [ 条件 ] then # 条件成立时执行的命令 fi实战例子判断目录不存在就创建这是最常用的脚本片段比如备份前先建备份目录#!/bin/bash backup_dir/data/backup # 如果目录不存在就创建 if [ ! -d $backup_dir ] then echo 备份目录不存在正在创建... mkdir -p $backup_dir echo 创建完成 fi说明!代表「取反」! -d就是「不是目录 / 不存在」。fi是 if 的结束标志有 if 就必须有 fi成对出现。结构 2双分支 if-else条件成立执行 A不成立执行 B。if [ 条件 ] then # 条件成立执行 else # 条件不成立执行 fi实战例子判断用户是不是 root#!/bin/bash if [ $USER root ] then echo 当前是管理员root用户 else echo 当前是普通用户$USER fi结构 3多分支 if-elif-else多个条件依次判断匹配哪个就执行哪个。if [ 条件1 ] then # 条件1成立 elif [ 条件2 ] then # 条件2成立 else # 都不成立 fi实战例子分数评级#!/bin/bash read -p 请输入考试分数 score if [ $score -ge 90 ] then echo 优秀 elif [ $score -ge 60 ] then echo 及格 else echo 不及格 fi六、循环结构重复执行代码需要重复做一件事的时候用循环不用写 N 遍代码。1. for 循环按列表循环适合已知循环次数、遍历一组内容的场景。基础语法for 变量 in 值1 值2 值3... do # 循环体每次循环执行的代码 done例子 1遍历数字打印 1 到 5#!/bin/bash for i in 1 2 3 4 5 do echo 当前数字$i done例子 2批量创建 10 个带序号的文件#!/bin/bash for i in $(seq 1 10) do touch file_$i.txt echo 创建了 file_$i.txt done说明seq 1 10生成 1 到 10 的连续数字。运行后当前目录会生成 file_1.txt 到 file_10.txt 共 10 个文件。例子 3遍历当前目录下所有 .txt 文件#!/bin/bash for file in *.txt do echo 找到txt文件$file done2. while 循环满足条件就循环适合不知道循环多少次满足条件就一直跑的场景。基础语法while [ 条件 ] do # 循环体 done例子从 1 数到 5#!/bin/bash i1 while [ $i -le 5 ] do echo 当前$i i$((i1)) # 变量自增$((运算式)) 是Shell的整数运算写法 done3. break 和 continuebreak立刻跳出整个循环不再执行后面的循环。continue跳过本次循环直接进入下一次循环。七、Shell 函数封装重复的代码把一段常用的代码封装成函数后面想用直接调用函数名就行不用重复写让脚本更整洁。1. 函数的定义和调用语法# 定义函数 函数名(){ # 函数体代码 } # 调用函数直接写函数名 函数名例子写一个打招呼的函数#!/bin/bash # 定义函数 say_hello(){ echo Hello欢迎学习Shell脚本 echo 今天也要加油哦 } # 调用函数 say_hello2. 函数传参和脚本传参一样函数里用$1$2接收调用时传的参数。例子加法函数接收两个参数输出和#!/bin/bash add(){ sum$(( $1 $2 )) echo $1 $2 $sum } # 调用函数传两个参数 add 3 5 add 10 20运行输出3 5 8 10 20 303. 函数返回值用return返回状态码0-255 的整数调用后用$?获取返回值。一般 0 代表成功非 0 代表失败和命令的退出码一致。如果要返回字符串、数字结果直接用 echo 输出用变量接收就行。八、完整实战写一个自动备份脚本我们把上面的知识点整合起来写一个实用的目录备份脚本巩固所有内容。脚本功能接收一个参数要备份的目录路径判断目录是否存在不存在就报错退出备份目录不存在就自动创建用 tar 打包压缩按当前时间命名备份完成后提示成功显示备份文件大小完整脚本backup.sh#!/bin/bash # 功能自动备份指定目录按时间命名压缩包 # 用法./backup.sh 要备份的目录路径 # 1. 判断有没有传参数 if [ $# -ne 1 ] then echo 用法错误正确用法./backup.sh 要备份的目录路径 exit 1 # 退出脚本状态码1代表错误 fi # 2. 定义变量 source_dir$1 # 要备份的源目录 backup_dir/data/backup # 备份文件存放目录 time_str$(date %Y%m%d_%H%M%S) # 时间字符串用来命名 backup_filebackup_$time_str.tar.gz # 备份文件名 # 3. 判断源目录是否存在 if [ ! -d $source_dir ] then echo 错误源目录 $source_dir 不存在 exit 1 fi # 4. 判断备份目录是否存在不存在就创建 if [ ! -d $backup_dir ] then echo 备份目录不存在正在创建... mkdir -p $backup_dir fi # 5. 执行备份 echo 开始备份 $source_dir ... tar -zcf $backup_dir/$backup_file $source_dir # 6. 判断备份是否成功 if [ $? -eq 0 ] then echo 备份成功备份文件$backup_dir/$backup_file echo 文件大小$(du -h $backup_dir/$backup_file | awk {print $1}) else echo 备份失败 exit 1 fi逐段拆解开头先校验参数用户用错了就提示用法友好健壮。所有配置都用变量定义后面要改路径、命名格式只改变量就行。所有路径变量都加了双引号防止目录名有空格的时候报错。用$?判断上一条 tar 命令是否执行成功给出对应提示。运行测试# 给脚本加权限 chmod x backup.sh # 备份你的 learn_linux 目录 ./backup.sh ~/learn_linux九、新手必踩坑总结空格问题变量定义等号两边不能有空格条件判断[ ]内部两边必须有空格条件和符号之间也要有空格变量引用加双引号尤其是文件路径、用户输入内容可能有空格不加引号会被拆成多个参数导致报错。好习惯引用变量就加双引号比如$filename。严格区分大小写Shell 变量、命令、文件名全部分大小写Name和name是两个变量。多写注释脚本过一周自己都忘了干嘛的注释能帮你快速回忆。小步调试不要一口气写一大段写一点跑一下验证出错了容易找原因。脚本用 .sh 后缀不是必须的但约定俗成别人一看就知道是 Shell 脚本。十、新手练习建议先把上面的例子都亲手敲一遍运行不要复制粘贴敲的过程中才能发现坑。试着改例子比如把备份脚本改成备份后自动删除 7 天前的旧备份。把你平时重复做的操作试着写成脚本比如批量重命名文件、一键更新系统 清理缓存。