31-Linux学习之旅之Shell 脚本(一)
·
Linux学习之旅之Shell 脚本(一)
一、认识Shell
1、什么是Shell
Shell 是用户和操作系统内核之间的「命令解释器」,相当于一层外壳,把人类输入的命令翻译给内核执行,再把内核结果返回给用户。
2、常见Shell
| Shell | 说明 |
|---|---|
| bash (/bin/bash) | 现在 Linux 默认 Shell,功能最强,日常写.sh脚本绝大多数用 bash |
| sh (/bin/sh) | POSIX 标准 shell,语法精简,功能受限;很多系统 sh 是 bash 的软链接 |
| zsh | 交互体验好,运维终端常用(oh‑my‑zsh) |
| csh/tcsh | C 语言风格语法,很少写脚本用 |
二、Shell基础规则
1、解释器声明
#! 叫做 shebang,必须写在文件第一行,告诉系统用 bash 解释执行脚本。
#!/bin/bash
2、文件权限与执行方式
#新建脚本 data.sh
root@ubuntu2404ser:~# vim date.sh
root@ubuntu2404ser:~# cat date.sh
#!/bin/bash
date
# 方式1:推荐,使用脚本内shebang指定解释器
root@ubuntu2404ser:~# ll date.sh
-rw-r--r-- 1 root root 17 Aug 24 02:46 date.sh
root@ubuntu2404ser:~# ./date.sh
-bash: ./date.sh: Permission denied
# 赋予可执行权限
root@ubuntu2404ser:~# chmod +x date.sh
root@ubuntu2404ser:~# ll date.sh
-rwxr-xr-x 1 root root 17 Aug 24 02:46 date.sh*
root@ubuntu2404ser:~# ./date.sh
Mon Aug 24 02:49:07 AM UTC 2026
# 方式2:直接指定解释器执行,不需要x权限
root@ubuntu2404ser:~# /bin/bash date.sh
Mon Aug 24 02:47:19 AM UTC 2026
# 方式3:在当前shell执行(会改变当前shell环境变量)
root@ubuntu2404ser:~# chmod -x date.sh
root@ubuntu2404ser:~# ll date.sh
-rw-r--r-- 1 root root 17 Aug 24 02:46 date.sh
root@ubuntu2404ser:~# source date.sh
Mon Aug 24 02:49:54 AM UTC 2026
3、本地变量
本地变量:只在当前 Shell 环境内生效,不会传给子 Shell,脚本结束就销毁,其它终端没有办法使用
root@ubuntu2404ser:~# tty
/dev/pts/0
root@ubuntu2404ser:~# name=xyx
root@ubuntu2404ser:~# echo $name
xyx
root@ubuntu2404ser:~# tty
/dev/pts/1
root@ubuntu2404ser:~# echo $name
root@ubuntu2404ser:~#
4、全局变量
通告所有终端
root@ubuntu2404ser:~# tty
/dev/pts/0
root@ubuntu2404ser:~# echo 'export myvar="hello123"' >> /root/.bashrc
root@ubuntu2404ser:~# echo $myvar
hello123
root@ubuntu2404ser:~# tty
/dev/pts/1
root@ubuntu2404ser:~# source .bashrc
root@ubuntu2404ser:~# echo $myvar
hello123
5、变量命名规则
1. 只能由字母、数字、下划线组成
root@ubuntu2404ser:~# n_b=123
root@ubuntu2404ser:~# echo $n_b
123
root@ubuntu2404ser:~# n-n=1234
n-n=1234: command not found
2. 不能以数字开头
root@ubuntu2404ser:~# 1mmm=yyy
1mmm=yyy: command not found
3. 区分大小写:A 和 a 是两个完全不同变量
root@ubuntu2404ser:~# ncs=hhh
root@ubuntu2404ser:~# echo $ncs
hhh
root@ubuntu2404ser:~# NCS=yyy
root@ubuntu2404ser:~# echo $NCS
yyy
4. 等号 = 两边绝对不能加空格
root@ubuntu2404ser:~# aaa = bbb
Command 'aaa' not found, did you mean:
.................
Try: apt install <deb name>
5. 字符串,无空格可以不加引号
root@ubuntu2404ser:~# var=abc
root@ubuntu2404ser:~# echo $var
abc
6. 值包含空格、特殊符号,必须加双引号 ""
root@ubuntu2404ser:~# var="hello world"
root@ubuntu2404ser:~# echo $var
hello world
7. 单引号 '':原样输出,不解析$变量
root@ubuntu2404ser:~# var='echo $HOME'
root@ubuntu2404ser:~# echo $var
echo $HOME
8. 双引号“” :解析$变量
root@ubuntu2404ser:~# var="echo $HOME"
root@ubuntu2404ser:~# echo $var
echo /root
8. $() 命令执行结果赋值
root@ubuntu2404ser:~# res=$(ls /root)
root@ubuntu2404ser:~# echo $res
date.sh xyy.sh
9. 反引号 `` 等价 $(),旧写法
root@ubuntu2404ser:~# res=`pwd`
root@ubuntu2404ser:~# echo $res
/root
6、{}使用方式
$变量名 简单使用
${变量名} 推荐,用于拼接,避免边界混淆
root@ubuntu2404ser:~# a=10
root@ubuntu2404ser:~# echo $a
10
root@ubuntu2404ser:~# echo ${a}
10
root@ubuntu2404ser:~# prefix="test"
root@ubuntu2404ser:~# file="${prefix}_log.txt"
root@ubuntu2404ser:~# echo $file
test_log.txt
三、环境变量
1、$0
#显示脚本 / 程序名字
root@ubuntu2404ser:~# cat > "test.sh" << 'EOF'
> #!/bin/bash
echo "脚本名 $0"
> EOF
root@ubuntu2404ser:~# bash test.sh
脚本名 test.sh
2、$1~n
# $1 ~ $9 :脚本第 1 至第 9 个传入参数,超过 9 个参数需使用 ${10} 、 ${11} 大括号写法读取
root@ubuntu2404ser:~# vim test.sh
root@ubuntu2404ser:~# cat test.sh
#!/bin/bash
echo "脚本名称:$0"
echo "第1个参数:$1"
echo "第2个参数:$2"
echo "第10个参数:${10}"
echo "参数总个数: $#""
root@ubuntu2404ser:~# bash test.sh sshd 22
脚本名称:test.sh
第1个参数:sshd
第2个参数:22
第10个参数:
参数总个数: 2
root@ubuntu2404ser:~# bash test.sh a b c d e f g h i j k l m n
脚本名称:test.sh
第1个参数:a
第2个参数:b
第10个参数:j
参数总个数: 14
3、$#
$# :统计脚本传入参数总个数,常用于前置校验参数数量是否符合要求。
root@ubuntu2404ser:~# bash test.sh a b c d e f g h i j k l m n
参数总个数: 14
4、$*
$* :把所有参数合并为单个完整字符串,参数之间以 IFS 分隔符(默认空格)拼接。
root@ubuntu2404ser:~# vim test.sh
root@ubuntu2404ser:~# cat test.sh
#!/bin/bash
echo '==== "$*" 输出 ===='
for arg in "$*"; do
echo "参数项:$arg"
done
root@ubuntu2404ser:~#
root@ubuntu2404ser:~# bash test.sh a b c d
==== "$*" 输出 ====
参数项:a b c d e f
5、$@
$@ :保留参数原始独立数组结构,每个参数单独隔离,带空格的参数不会被拆分。
root@ubuntu2404ser:~# vim test.sh
root@ubuntu2404ser:~# cat test.sh
#!/bin/bash
echo '==== "$@" 输出 ===='
for arg in "$@"; do
echo "参数项:$arg"
done
root@ubuntu2404ser:~# bash test.sh a b c d e f
==== "$@" 输出 ====
参数项:a
参数项:b
参数项:c
参数项:d
参数项:e
参数项:f
root@ubuntu2404ser:~#
6、$?
$? :上一条执行命令的退出返回码,0 代表执行成功,非 0 代表异常失败。
root@ubuntu2404ser:~# ls ./
date.sh test.sh xyy.sh
root@ubuntu2404ser:~# echo $?
0
root@ubuntu2404ser:~# sklab
sklab: command not found
root@ubuntu2404ser:~# echo $?
127
7、$$
$$ :当前脚本运行进程 PID,常用于临时文件命名、进程唯一标识。
root@ubuntu2404ser:~# echo $$
2629
root@ubuntu2404ser:~# tty
/dev/pts/1
root@ubuntu2404ser:~# ps aux |grep 2629
root 2629 0.0 0.3 8780 5872 pts/1 Ss 03:15 0:00 -bash
8、$!
$! :上一个后台异步执行命令(&)的进程 PID,用于后台进程监控、等待后台任务。
root@ubuntu2404ser:~# sleep 200 &
[1] 2922
root@ubuntu2404ser:~# echo $!
2922
root@ubuntu2404ser:~# ps aux | grep "sleep"
root 2922 0.0 0.1 5684 2104 pts/1 S 05:00 0:00 sleep 200
四、输入输出
1、echo输出
-n:不换行输出
-e:开启转义字符解析(\n换行、\t制表符、\\反斜杠)
root@ubuntu2404ser:~# echo "hello word"
hello word
root@ubuntu2404ser:~# echo -n "请输入开机密码: "
请输入开机密码: root@ubuntu2404ser:~#
root@ubuntu2404ser:~# echo -e "第一行\n第二行\n第三行\n "
第一行
第二行
第三行
#-e颜色解析
root@ubuntu2404ser:~# echo -e "\033[31m红色\033[0m"
红色
root@ubuntu2404ser:~# echo -e "\033[32m绿色\033[0m"
绿色
root@ubuntu2404ser:~# echo -e "\033[33m黄色\033[0m"
黄色
字体颜色
| 代码 | 颜色 |
|---|---|
| 30 | 黑色 |
| 31 | 红色(错误) |
| 32 | 绿色(成功) |
| 33 | 黄色(警告) |
| 34 | 蓝色 |
| 35 | 紫色 |
| 36 | 青色 |
| 37 | 白色 |
背景颜色
| 代码 | 颜色 |
|---|---|
| 40 | 黑背景 |
| 41 | 红背景 |
| 42 | 绿背景 |
| 43 | 黄背景 |
| 44 | 蓝背景 |
2、read 读取用户输入(接收键盘输入)
-p "提示文字":打印提示,不用额外写 echo
-t 5:超时 5 秒,没有输入自动结束
-s:静默输入,输入不回显(密码输入)
-n 3:只读取 3 个字符,输完直接结束,不用回车root@ubuntu2404ser:~# read -p "请输入新的主机名:" hostname
请输入新的主机名:xyx
root@ubuntu2404ser:~# read -s -p "请输入密码:" passwd
请输入密码:root@ubuntu2404ser:~#
#等待三秒
root@ubuntu2404ser:~# read -t 3 -p "请输入密码:" passwd
请输入密码:root@ubuntu2404ser:~#
3、printf 格式化
%s :字符串占位,输出文本、路径、服务名称;
%d :十进制整数占位,输出端口、进程号、使用率整数;
%6.2f :浮点数格式化,总宽度 6 位,保留 2 位小数,自动空格补齐实现右对齐。
#不支持自动换行
root@ubuntu2404ser:~# printf "你的名字是: %s\n" "XYX"
你的名字是: XYX
root@ubuntu2404ser:~# printf "你的名字是: %s" "XYX"
你的名字是: XYXroot@ubuntu2404ser:~#
#问就是永远18
root@ubuntu2404ser:~# printf "你的年龄: %d\n" "18"
你的年龄: 18
root@ubuntu2404ser:~#
#%A.Bf 浮点数格式规则:
#A:总字段宽度(整个数字占多少字符,包含小数点)
#B:小数点后面保留多少位小数
root@ubuntu2404ser:~# printf "你的存款多少: %6.3f元\n" "58.62"
你的存款多少: 58.620元
五、条件判断体系
| 判断 | 含义 |
|---|---|
-eq | 等于 |
-ne | 不等于 |
-gt | 大于 |
-ge | 大于等于 |
-lt | 小于 |
-le | 小于等于 |
1、test
#明显不对,因为=是字符串比较运算符,运算符两边必须是独立参数,要有空格隔开!
root@ubuntu2404ser:~# test 1=2
root@ubuntu2404ser:~# echo $?
0
root@ubuntu2404ser:~# test 1 = 2
root@ubuntu2404ser:~# echo $?
1
#判断文件是否存在
root@ubuntu2404ser:~# test -f test.sh
root@ubuntu2404ser:~# echo $?
0
root@ubuntu2404ser:~# ls
date.sh test.sh xyy.sh
#判断相等
root@ubuntu2404ser:~# test "a" = "b"
root@ubuntu2404ser:~# echo $?
1
2、[ ]
#[ ] 等价于 test
#[ b ]括号内侧必须有空格
root@ubuntu2404ser:~# [a = b]
[a: command not found
root@ubuntu2404ser:~# [ a = b ]
root@ubuntu2404ser:~# echo $?
1
root@ubuntu2404ser:~# [ -f /etc/passwd ]
root@ubuntu2404ser:~# echo $?
0
| 表达式 | 含义 |
|---|---|
-f file | 普通文件存在 |
-d file | 目录存在 |
-e file | 文件 / 目录存在 |
-r file | 可读 |
-w file | 可写 |
-x file | 可执行 |
3、[[ ]]
[[ ]] 是 bash 专属扩展判断语法,不属于 POSIX 标准,仅 bash 环境可用,运维脚本首选。
支持:&&、||、>、<、=~正则匹配
| 写法 | 逻辑与 | 逻辑或 |
|---|---|---|
[ ] / test | -a | -o |
[[ ]] | && |
root@ubuntu2404ser:~# [[ 1 -eq 1 && 1 -ne 2 ]]
root@ubuntu2404ser:~# echo $?
0
root@ubuntu2404ser:~# [[ "a" -ne "b" || "a" -eq "b" ]]
root@ubuntu2404ser:~# echo $?
0
root@ubuntu2404ser:~# port="4399"
root@ubuntu2404ser:~# [[ ${port} =~ ^[0-9]*$ ]]
root@ubuntu2404ser:~# echo $?
0
root@ubuntu2404ser:~#
4、== != -n -e
| 运算符 | 含义 | 适用场景 |
|---|---|---|
= | 字符串相等 | [ ]、[[ ]] |
== | 字符串相等 | 仅[[ ]],[ ]不标准 |
!= | 字符串不相等 | [ ]、[[ ]] |
-z | 字符串长度为 0(空) | [ ]、[[ ]] |
-n | 字符串长度不为 0(非空) | [ ]、[[ ]] |
root@ubuntu2404ser:~# [[ "hello" == "hello" ]]
root@ubuntu2404ser:~# echo $?
0
root@ubuntu2404ser:~# [[ "hello" != "hello" ]]
root@ubuntu2404ser:~# echo $?
1
root@ubuntu2404ser:~# [ -z "$NAME" ]
root@ubuntu2404ser:~# echo $?
0
root@ubuntu2404ser:~# [ -n "$HOME" ]
root@ubuntu2404ser:~# echo $?
0
六、流程控制
1、if 分支
#单分支 if 语法结构: if 判断条件; then 条件成立执行代码; fi , fi 是 if 的反向结束标记,必须成对出现。
#; 分号作用:将 if 与 then 写在同一行,分隔两条独立语句;也可换行省略分号。
#缩进规范:then 内部执行代码统一缩进 n 空格,企业脚本标准化排版,提升可读性。
#适用场景:前置参数校验、文件目录存在性判断、资源阈值告警单次判断。
#标准用法,增加可读性
if 条件;then
命令
elif 条件2;then
命令
else
命令
fi
#单分支
root@ubuntu2404ser:~# vim test.sh
#!/bin/bash
read -p "输入数字:" num
if [[ $num -gt 100 ]];then
echo "大于100"
fi
root@ubuntu2404ser:~# bash test.sh
请输入数字: 111
数字大于100
#多分支
root@ubuntu2404ser:~# vim test.sh
#!/bin/bash
read -p "输入数字:" num
if [[ $num -gt 100 ]];then
echo "大于100"
else
echo "小于100"
fi
root@ubuntu2404ser:~# bash test.sh
请输入数字: 11
数字小于100
#多条件分支
root@ubuntu2404ser:~# vim test.sh
#!/bin/bash
read -p "请输入您的分数: " num
if [[ $num -gt 90 ]];then
echo "优秀"
elif [[ $num -gt 70 ]];then
echo "很好"
elif [[ $num -gt 60 ]];then
echo "合格"
elif [[ $num -eq 60 ]];then
echo "你是不是在控分"
else
echo "不及格"
fi
root@ubuntu2404ser:~# bash test.sh
请输入您的分数: 67
合格
root@ubuntu2404ser:~# bash test.sh
请输入您的分数: 91
优秀
2、case 多分支
# case 语法结构: case 变量 in 匹配模式) 执行逻辑 ;; esac , esac 是 case 反向结束标记。
# ;; 双分号:匹配分支结束分隔符,缺少会穿透执行下一个匹配分支。
# 核心优势:针对单一变量多固定值匹配,代码比多层 if-elif 更简洁,常用于菜单工具、脚本传参功能分发。
# 业务场景:运维工具箱菜单、启停脚本(start/stop/restart/status)、参数功能分发。
#标准语句
case 变量 in
模式1)
命令
;;
模式2)
命令
;;
*)
#默认分支,相当于else
命令
;;
esac
root@ubuntu2404ser:~# vim test.sh
root@ubuntu2404ser:~# cat test.sh
#!/bin/bash
read -p "请输入操作(start/stop/restart):" op
case $op in
start)
echo "运行中"
;;
stop)
echo "已停止"
;;
reatart)
echo "正在重启"
;;
*)
echo "请输入正确的参数: start/stop/restart"
;;
esac
root@ubuntu2404ser:~# bash test.sh
请输入操作(start/stop/restart):stop
已停止
root@ubuntu2404ser:~# bash test.sh
请输入操作(start/stop/restart):start
运行中
root@ubuntu2404ser:~# bash test.sh
请输入操作(start/stop/restart):reload
请输入正确的参数: start/stop/restart
root@ubuntu2404ser:~# cat > 'dxx.sh' << 'EOF'
#!/bin/bash
read -p "输入字母(A/B/C):" char
case $char in
a|A)
echo "输入A"
;;
b|B)
echo "输入B"
;;
c|C)
echo "输入C"
;;
*)
echo "其他字符"
;;
esac
EOF
root@ubuntu2404ser:~# bash dxx.sh
输入字母(A/B/C):a
输入A
root@ubuntu2404ser:~# bash dxx.sh
输入字母(A/B/C):c
输入C
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐



所有评论(0)