Shell脚本
Linux 系统中的 Shell 是一个特殊的应用程序,它介于操作系统内核与用户之间,充当了一个“命令解释器”的角色,负责接收用户输入的操作指令(命令)并进行解释,将需要执 行的操作传递给内核执行,并输出执行结果。
常见的 Shell 解释器程序有很多种,使用不同的 Shell 时,其内部指令、命令行提示符等方面会存在一些区别。通过/etc/shells 文件可以了解当前系统所支持的 Shell 脚本种类
在一些复杂的 Linux 维护工作中,大量重复性的输入和交互操作不仅费时费力,而且容易出错,而编写一个恰到好处的 Shell 脚本程序,可以批量处理、自动化地完成一系列维护任务,大大减轻管理员的负担
什么是Shell
Shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行。
实际上Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核。不仅如此,Shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的程序
Shell的运行过程
Shell作用
Linux 系统中的 Shell 是一个特殊的应用程序,它介于操作系统内核与用户之间,充当了一个“命令解释器”的角色,负责接收用户输入的操作指令(命令)并进行解释,将需要执行的操作传递给内核执行,并输出执行结果
Shell脚本的概念
- 将要执行的命令按顺序保存到一个文本文件
- 给该文件可执行权限
- 可结合各种Shell控制语句以完成更复杂的操作
Shell脚本应用场景
- 重复性操作
- 交互性任务
- 批量事务处理
- 服务运行状态监控
- 定时任务执行
- ......
执行脚本
- sh 脚本文件
- bash 脚本文件
路径执行脚本
在脚本文件第一行加入默认命令解释器
#!/bin/bash (解释器绝对路径 )声明默认命令解释器,在不指定命令解释器执行脚本时,默认使用声明的默认解释器执行
绝对路径执行
/root/kgc.sh
相对路径执行(脚本所在目录)
./kgc.sh // ./表示当前路径
. kgc.sh
source kgc.sh
重定向
由于 Shell 脚本“批量处理”的特殊性,其大部分操作过程以静默方式运行,不需要用户进行干预。因此学会提取、过滤执行信息变得十分重要。本小节主要介绍 Shell 环境中的两个 I/O 操作:重定向和管道
交互式硬件设备
- 标准输入:从该设备接收用户输入的数据
- 标准输出:通过该设备向用户输出数据
- 标准错误:通过该设备报告执行出错信息
类型 | 设备文件 | 文件描述编号 | 默认设备 |
标准输入 | /dev/stdin | 0 | 键盘 |
标准输出 | /dev/stdout | 1 | 显示器 |
标准错误输出 | /dev/stder | 2 | 显示器 |
重定向操作
类型 | 操作符 | 用途 |
重定向输入 | 从指定的文件读取数据,而不是从键盘输入 | |
重定向输出 | > | 将输出结果保存到指定文件(覆盖原有内容) |
>> | 将输出结果追加到指定的文件尾部 | |
标准错误输出 | 2> | 将错误信息保存到指定的文件(覆盖原有内容) |
2>> | 将错误信息追加到指定文件中 | |
混合输出 | &> | 将标准输出、标准错误的内容保存到同一个文件中 |
Shell变量
各种 Shell 环境中都使用到了“变量”的概念。Shell 变量用来存放系统和用户需要使用的特定参数(值),而且这些参数可以根据用户的设定或系统环境的变化而相应变化。通过使用变量,Shell 程序能够提供更加灵活的功能,适应性更强。
常见 Shell 变量的类型包括自定义变量、环境变量、只读变量、位置变量、预定义变量
变量的作用
- 用于存放系统和用户需要使用的特定参数(值)
- 变量名:使用固定的名称,由系统预设或用户定义
- 变量值:能够根据用户设置,系统环境的变化而变化
变量的类型
- 自定义变量:由用户自己定义、修改和使用
- 特殊变量:环境变量、只读变量、位置变量、预定义变量
变量的命名规范
变量名称只能包括大小写字母数字、下划线,不能以数字开头,区分大小写,建议全大写
自定义变量
自定义变量是由系统用户自己定义的变量,只在用户自己的 Shell 环境中有效,因此又称为本地变量。在编写 Shell 脚本程序时,通常会设置一些特定的自定义变量,以适应程序执行过程中的各种变化
变量名=变量值 //变量的值不能使用空格,如果非要使用空格需要使用引号引起来
name=join
变量名=`命令` //反引号将命令的结果当成变量的值,命令替换
num=`expr 1 + 1`
变量名=$(命令) //将命令的结果当成变量的值,命令替换
num=$(expr 1 + 1)
read命令
除了上述赋值操作以外,还可以使用 Bash 的内置命令 read 来给变量赋值。read 命令用来提示用户输入信息,从而实现简单的交互过程。执行时将从标准输入设备(键盘)读入 一行内容,并以空格为分隔符,将读入的各字段依次赋值给指定的变量(多余的内容赋值给最后一个变量)。若指定的变量只有一个,则将整行内容赋值给此变量
[root@localhost ~]# read ToDir1
/opt/backup/ //输入变量ToDir1 的值为/opt/backup/ [root@localhost ~]# echo $ToDir1
/opt/backup/
[root@localhost ~]# read -p "请指定备份存放目录:" ToDir2
请指定备份存放目录:/opt/backup
[root@localhost ~]# echo $ToDir2
/opt/backup
删除变量
unset 变量 //删除变量
查看变量值
echo $变量 //查看变量值,可以查看多个变量值可以使用空格隔开,
echo ${变量} //查看变量值,可以查看多个变量值可以使用空格隔开
echo "${变量}" //查看变量值,可以查看多个变量值可以使用空格隔开(在引号内)不可以使用单引号,单引号会被当做字符串输出
算数运算符
#空格不能少,只显示整数位
expr 1 + 1 //输出1+1的结果
expr 1 - 1 //输出1-1的结果
expr 1 / 1 //输出1除以1的结果
expr 1 % 2 //输出1取余2的结果
expr 1 \* 2 //输出1乘以2的结果 \将具有特殊意义的字符恢复为普通字符
expr 1 "*" 2 //输出1乘以2的结果
expr 1 '*' 2 //输出1乘以2的结果
echo $[算数运算] //算数运算+-*/%
echo $((算数运算)) //+,-,*,/,%
特殊的Shell变量
环境变量
由系统提前创建,用来设置用户的工作环境
配置文件:/etc/profile(全局)、~/.bash_profile(用户)
变量 USER 表示用户名称,HOME 表示用户的宿主目录,LANG 表示语言和字符集,PWD 表示当前所在的工作目录,PATH 表示命令搜索路径
只读变量
readonly name //设置name变量为只读
预定义变量
执行脚本 [参数] //执行脚本时传入参数,多个参数使用空格隔开
$[数字] //在脚本内接收参数,数字0表示脚本本身的名称,1表示第一个参数,2表示第二个参数,以此类推
$*或者$@ //接收所有参数
$# //计算参数的数量
$?:表示上一条命令执行后的返回状态,返回值为 0 表示执行正确,返回任何非 0值均表示执行出现异常
条件控制语句
test命令
测试表达式是否成立,若成立返回0,否则返回其他数值
- 格式1:test 条件表达式
- 格式2:[ 条件表达式 ] //两边一定要有空格
文件测试
常用测试操作符
- -d:测试是否是目录(Directory)
- -e:测试目录或文件是否存在(Exist)
- -f:测试是否为文件(File)
- -r:测试当前用户是否有权限读取(Read)
- -w:测试当前用户是否由权限写入(Write)
- -x:测试当前用户是否有权限执行(eXcute)
整数值比较
[ 整数1 操作符 整数2]
常用测试操作符
- -eq:等于(Equal)
- -ne:不等于(Not Equal)
- -gt:大于(Greater THan)
- -lt:小于(Less than)
- -le:小于或等于(Less than or equal to)
- -ge:大于或等于(Greater than or equal to)
字符串比较
格式1:[ 字符串1 == 字符串2 ]
:[ 字符串1 != 字符串2 ]
格式2:[ -z 字符串 ]
- =:字符串内容相同
- !=:字符串内容不同,!表示相反的意思
- -z:字符串内容为空
逻辑测试
格式1:[ 表达式1 ] 操作符 [ 表达式2 ] ...
格式2:命令1 操作符 命令2 ...
常用的测试操作符
-a或&&:逻辑与,而且的意思
-o或||:逻辑或
!:逻辑否
if条件判断
if 条件表达式 (等价于Java的ifelse)
then //条件成立
elif 条件表达式
then //elif条件成立
else //条件不成立
fi //if结束语
exit [错误代码]:退出脚本
示例1
[root@localhost ~]# vim gradediv.sh
#!/bin/bash
read -p "请输入您的分数(0-100): " GRADE if [ $GRADE -ge 85 ] && [ $GRADE -le 100 ] then
echo "$GRADE 分,优秀!"
elif [ $GRADE -ge 70 ] && [ $GRADE -le 84 ] then
echo "$GRADE 分,合格!
else
echo "$GRADE 分,不合格!"
fi
[root@localhost ~]# chmod +x gradediv.sh
#执行 gradediv.sh 脚本的效果如下所示。
[root@localhost ~]# ./gradediv.sh
请输入您的分数(0-100): 67
67 分 , 不 合 格 !
[root@localhost ~]# ./gradediv.sh
请输入您的分数(0-100): 78
78 分,合格!
[root@localhost ~]# ./gradediv.sh
请输入您的分数(0-100): 89
89 分,优秀!
示例2
#!/bin/bash
if [ -z "$1" ];then //判断传递的参数是否为空
echo "Please pass the IP address parameter."
exit 1
elif ! [[ $1 =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]];then //IP地址是否可用
echo "The IP address is invalid." //可用
exit 1
elif ! [ $(whoami) == "root" ];then //是否为root用户登录
echo "The script is executed by the root user." //条件成立
exit 1
fi
if ping -c 2 "$1" >> /dev/null;then //尝试测试IP地址是否可用
echo "$1 is survival"
else echo "$1 is death"
fi
exit 0 //退出脚本,返回值0
[root@localhost ~]# chmod u+x test2.sh
#示例2测试
[root@localhost ~]# ./test2.sh 192.168.78.129
192.168.78.129 is survival
case条件判断
case "$1" in
start) //条件1
echo "服务正在启动..."
sleep 3
;; //条件1结束语符合条件退出条件判断,如果不写会一直判断
stop) //条件2
echo "服务停止"
;; //条件2结束语
restart)
echo "服务重启中..."
sleep 5
;;
*) //*除了以上条件以外的所有
echo "Usage: " 最后可以不写结束语
esac
[root@localhost ~]# chmod u+x test.sh
#结果测试
[root@localhost ~]# ./test.sh stop
服务停止
[root@localhost ~]# ./test.sh start
服务启动中...