一、表达式
1.1 测试表达式
样式1: test 条件表达式
样式2: [ 条件表达式 ]
注意:以上两种方法的作用完全一样,后者为常用。但后者需要注意方括号[、]与条件表达式之间至少有一个空格。test跟 [] 的意思一样条件成立,状态返回值是0条件不成立,状态返回值是1
简单示例
test语法示例
[root@localhost ~]# test 1 == 1
[root@localhost ~]# echo $?
0
[root@localhost ~]# test 1 == 2
[root@localhost ~]# echo $?
1
[] 语法示例
[root@localhost ~]# [ 1 == 1 ]
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ 1 == 12 ]
[root@localhost ~]# echo $?
1
1.2 逻辑表达式
语法解读
&& 示例:命令1 && 命令2如果命令1执行成功,那么我才执行命令2 -- 夫唱妇随如果命令1执行失败,那么命令2也不执行
|| 示例:命令1 || 命令2如果命令1执行成功,那么命令2不执行 -- 对着干如果命令1执行失败,那么命令2执行
!示例:! 命令如果命令执行成功,则整体取反状态
实践1:
&& 语法实践
[root@localhost ~]# [ 1 = 1 ] && echo "条件成立"
条件成立
[root@localhost ~]# [ 1 = 2 ] && echo "条件成立"|| 语法实践
[root@localhost ~]# [ 1 = 2 ] || echo "条件不成立"
条件不成立
[root@localhost ~]# [ 1 = 1 ] || echo "条件不成立"
[root@localhost ~]#
实践2-案例实践
执行文件前保证具备执行权限
[root@localhost ~]# cat test_argnum.sh
#!/bin/bash
# && 和 || 演示# 设定普通变量
arg_num=$#[ $# == 1 ] && echo "脚本参数为1,允许执行脚本"
[ $# == 1 ] || echo "脚本参数不为1,不允许执行脚本"
实践3-取反
查看正常的字符串判断
[root@localhost ~]# [ aaa == aaa ]
[root@localhost ~]# echo $?
0查看取反的效果判断
[root@localhost ~]# [ ! aaa == aaa ]
[root@localhost ~]# echo $?
1
[root@localhost ~]# [ ! aaa == bbb ]
[root@localhost ~]# echo $?
0
实践4 - 组合使用
[root@localhost ~]# [ -d /etc ] && echo "目录存在" || echo "目录不存在"
目录存在
[root@localhost ~]# [ -d /etc1 ] && echo "目录存在" || echo "目录不存在"
目录不存在
1.3 字符串表达式
内容比较判断str1 == str2 str1和str2字符串内容一致str1 != str2 str1和str2字符串内容不一致,!表示相反的意思内容空值判断-z str 空值判断,获取字符串长度,长度为0,返回True-n "str" 非空值判断,获取字符串长度,长度不为0,返回True注意:str外侧必须携带"",否则无法判断
简单实践
实践1-内容比较判断
判断字符串内容是否一致
[root@localhost ~]# test aaa == bbb
[root@localhost ~]# echo $?
1
[root@localhost ~]# test aaa != bbb
[root@localhost ~]# echo $?
0判断数字内容是否一致
[root@localhost ~]# num1=234 num2=456
[root@localhost ~]# test $num1 == $num2
[root@localhost ~]# echo $?
1
[root@localhost ~]# test $num1 != $num2
[root@localhost ~]# echo $?
0
实践2-空值判断
判断内容是否为空
[root@localhost ~]# string=nihao
[root@localhost ~]# test -z $string
[root@localhost ~]# echo $?
1
[root@localhost ~]# test -z $string1
[root@localhost ~]# echo $?
0判断内容是否为不空,可以理解为变量是否被设置
[root@localhost ~]# unset str
[root@localhost ~]# [ -n $str ]
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ -n "$str" ]
[root@localhost ~]# echo $?
1
[root@localhost ~]# str=value
[root@localhost ~]# [ -n "$str" ]
[root@localhost ~]# echo $?
0
1.4 文件表达式
表达式解读
文件属性判断-d 检查文件是否存在且为目录文件 -f 检查文件是否存在且为普通文件-S 检查文件是否存在且为socket文件-L 检查文件是否存在且为链接文件-O 检查文件是否存在并且被当前用户拥有-G 检查文件是否存在并且默认组为当前用户组文件权限判断 -r 检查文件是否存在且可读-w 检查文件是否存在且可写-x 检查文件是否存在且可执行文件存在判断-e 检查文件是否存在-s 检查文件是否存在且不为空文件新旧判断file1 -nt file2 检查file1是否比file2新file1 -ot file2 检查file1是否比file2旧file1 -ef file2 检查file1是否与file2是同一个文件,判定依据的是i节点
简单实践
实践1- 文件属性判断
[root@localhost ~]# [ -f weizhi.sh ] && echo "是一个文件"
[root@localhost ~]# [ -f weizhi.sddh ] || echo "不是一个文件"
不是一个文件
[root@localhost ~]# [ -d weizhi.sddh ] || echo "不是一个目录"
不是一个目录
[root@localhost ~]# [ -d /tmp ] && echo "是一个目录"
是一个目录
实践2-文件权限判断
#!/bin/bash
# 功能: 统计内存使用率信息# 定制普通变量
tmp_file='/tmp/mem.txt'# 设定内存的基本信息
free -m > /tmp/mem.txt 2>&1
mem_total=$(grep Mem /tmp/mem.txt | tr -s " " | cut -d " " -f2)
mem_used=$(grep Mem /tmp/mem.txt | tr -s " " | cut -d " " -f3)
mem_free=$(grep Mem /tmp/mem.txt | tr -s " " | cut -d " " -f4)# 统计内存的使用率
percentage_used=$(echo "scale=2; ${mem_used} / ${mem_total} * 100" | bc)
percentage_free=$(echo "scale=2; ${mem_free} / ${mem_total} * 100" | bc)# 信息的显示
echo -e "\e[31m\t $(hostname) 内存使用信息统计\e[0m"
echo "----------------------------------------"
echo -e "\e[32m内存总量: ${mem_total}
内存使用量: ${mem_used}
内存空闲量: ${mem_free}
内存使用占比: ${percentage_used}
内存空闲占比: ${percentage_free}\e[0m"
echo "----------------------------------------"
1.5 数字表达式
语法解读
n1 -eq n2 相等 n1 -ne n2 不等于 n1 -ge n2 大于等于 n1 -gt n2 大于 n1 -lt n2 小于 n1 -le n2 小于等于
简单实践
实践1-命令实践
[root@localhost ~]# [ 3 -gt 2 ] && echo "3 大于 2"
3 大于 2
[root@localhost ~]# [ 3 -ne 2 ] && echo "3 不等于 2"
3 不等于 2
[root@localhost ~]# [ 3 -eq 3 ] && echo "3 等于 3"
3 等于 3
实践2-脚本安全
查看脚本内容
[root@localhost ~]# cat test_argnum.sh
#!/bin/bash
# -eq 和 -ne 演示# 设定普通变量
arg_num=$#[ $arg_num -eq 1 ] && echo "脚本参数为1,允许执行脚本"
[ $arg_num -ne 1 ] && echo "脚本参数不为1,不允许执行脚本"
脚本执行效果
root@localhost ~]# /bin/bash test_argnum.sh
脚本参数不为1,不允许执行脚本
[root@localhost ~]# /bin/bash test_argnum.sh 1
脚本参数为1,允许执行脚本
[root@localhost ~]# /bin/bash test_argnum.sh 1 2
脚本参数不为1,不允许执行脚本
1.6 集合基础
语法解析
方法1:[ 条件1 -a 条件2 ] - 两个条件都为真,整体为真,否则为假[ 条件1 -o 条件2 ] - 两个条件都为假,整体为假,否则为真
方法2:[[ 条件1 && 条件2 ]] - 两个条件都为真,整体为真,否则为假[[ 条件1 || 条件2 ]] - 两个条件都为假,整体为假,否则为真
简单实践
实践1-[]组合实践
[root@localhost ~]# user=root pass=123456
[root@localhost ~]# [ $user == "root" -a $pass == "123456" ]
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ $user == "root" -a $pass == "1234567" ]
[root@localhost ~]# echo $?
1
[root@localhost ~]# [ $user == "root" -o $pass == "1234567" ]
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ $user == "root1" -o $pass == "1234567" ]
[root@localhost ~]# echo $?
1
实践2 - [[]]组合实践
[root@localhost ~]# [[ $user == "root" && $pass == "123456" ]]
[root@localhost ~]# echo $?
0
[root@localhost ~]# [[ $user == "root" && $pass == "1234567" ]]
[root@localhost ~]# echo $?
1
[root@localhost ~]# [[ $user == "root" || $pass == "1234567" ]]
[root@localhost ~]# echo $?
0
[root@localhost ~]# [[ $user == "root1" || $pass == "1234567" ]]
[root@localhost ~]# echo $?
1
1.7 综合实践
跳板机登录
脚本功能-扩充用户名和密码验证功能
[root@localhost ~]# cat simple_jumpserver.sh
#!/bin/bash
# 功能:定制跳板机的展示页面
# 版本:v0.3
# 作者:书记
# 联系:www.superopsmsb.com# 定制普通变量
login_user='root'
login_pass='123456'# 跳板机的信息提示
echo -e "\e[31m \t\t 欢迎使用跳板机"
echo -e "\e[32m
-----------请选择你要登录的远程主机-----------1: 10.0.0.14 (nginx)2: 10.0.0.15 (tomcat)3: 10.0.0.19 (apache)q: 使用本地主机
----------------------------------------------
"'\033[0m'# 由于暂时没有学习条件判断,所以暂时选择 q
read -p "请输入您要选择的远程主机编号: " host_index
read -p "请输入登录本地主机的用户名: " user
read -s -p "请输入登录本地主机的密码: " password
echo
# 远程连接主机
[[ ${user} == ${login_user} && ${password} == ${login_pass} ]] && echo "主机登录验证成功" || echo "您输入的用户名或密码有误"
脚本执行效果
[root@localhost ~]# /bin/bash simple_jumpserver.sh欢迎使用跳板机-----------请选择你要登录的远程主机-----------1: 10.0.0.14 (nginx)2: 10.0.0.15 (tomcat)3: 10.0.0.19 (apache)q: 使用本地主机
----------------------------------------------请输入您要选择的远程主机编号: q
请输入登录本地主机的用户名: root
请输入登录本地主机的密码:
主机登录验证成功
[root@localhost ~]# /bin/bash simple_jumpserver.sh欢迎使用跳板机-----------请选择你要登录的远程主机-----------1: 10.0.0.14 (nginx)2: 10.0.0.15 (tomcat)3: 10.0.0.19 (apache)q: 使用本地主机
----------------------------------------------请输入您要选择的远程主机编号: q
请输入登录本地主机的用户名: python
请输入登录本地主机的密码:
您输入的用户名或密码有误
二、数组基础
2.1 数组定义
语法解读
单行定义array_name=(value0 value1 value2 value3)多行定义array_name=(value0value1value2value3)单元素定义array_name[0]=value0array_name[1]=value1array_name[2]=value2注意:单元素定义的时候,可以不使用连续的下标,而且下标的范围没有限制。命令定义就是value的值以命令方式来获取file_array=($(ls /tmp/))
简单实践
实践1-单行定义
定制数据数组
[root@localhost ~]# num_list=(123,234,345,456,567)
[root@localhost ~]# echo ${num_list[0]}
123,234,345,456,567数据元素之间使用空格隔开
[root@localhost ~]# num_list=(123 234 345 456 567)
[root@localhost ~]# echo ${num_list[0]}
123
[root@localhost ~]# echo ${num_list[@]}
123 234 345 456 567
实践2-多行定义
定制数组
[root@localhost ~]# class_one=(
> zhangsan
> lisi
> wangwu
> zhaoliu
> )查看数组元素
[root@localhost ~]# echo ${class_one[0]}
zhangsan
[root@localhost ~]# echo ${class_one[@]}
zhangsan lisi wangwu zhaoliu
实践3-单元素定义
定制数组
[root@localhost ~]# mix_list[0]=nihao
[root@localhost ~]# mix_list[2]=345
[root@localhost ~]# mix_list[4]="1.23,4.56"查看数组元素
[root@localhost ~]# echo ${mix_list[1]}
[root@localhost ~]# echo ${mix_list[@]}
nihao 345 1.23,4.56批量多元素定义
[root@localhost ~]# string_list=([0]="value-1" [3]="value-2")
[root@localhost ~]# echo ${string_list[@]}
value-1 value-2
[root@localhost ~]# echo ${!string_list[@]}
0 3
2.2 数组取值
从系统中获取所有的数组declare -a
简单实践
实践1-基于索引找内容
设定数组内容
[root@localhost ~]# num_list=(123 234 345 456 567)获取指定位置元素
[root@localhost ~]# echo ${num_list[0]}
123
[root@localhost ~]# echo ${num_list[1]}
234获取所有位置元素
[root@localhost ~]# echo ${num_list[*]}
123 234 345 456 567
[root@localhost ~]# echo ${num_list[@]}
123 234 345 456 567获取末尾位置元素
[root@localhost ~]# echo ${num_list[-1]}
567
[root@localhost ~]# echo ${num_list[-2]}
456获取指定范围元素
[root@localhost ~]# echo ${num_list[@]:1:1}
234
[root@localhost ~]# echo ${num_list[@]:1:3}
234 345 456
实践2-基于内容获取元素
[root@localhost ~]# echo ${!num_list[@]}
0 1 2 3 4
[root@localhost ~]# echo ${!num_list[@]}
0 1 2 3 4
实践3-获取数组长度
获取数组的元素数量
[root@localhost ~]# echo ${#num_list[@]}
5
[root@localhost ~]# echo ${#num_list[*]}
5获取数据元素的长度
[root@localhost ~]# echo ${#num_list[3]}
3
实践4-获取系统所有数组
设定数组
[root@localhost ~]# num_list=(123 234 345 456 567)查看所有数组
[root@localhost ~]# declare -a
declare -a BASH_ARGC='()'
declare -a BASH_ARGV='()'
declare -a BASH_LINENO='()'
declare -a BASH_SOURCE='()'
declare -ar BASH_VERSINFO='([0]="4" [1]="2" [2]="46" [3]="2" [4]="release" [5]="x86_64-redhat-linux-gnu")'
declare -a DIRSTACK='()'
declare -a FUNCNAME='()'
declare -a GROUPS='()'
declare -a PIPESTATUS='([0]="0")'
declare -a num_list='([0]="123" [1]="234" [2]="345" [3]="456" [4]="567")'
2.3 数组变动
元素修改
简单实践
修改指定位置的值
[root@localhost ~]# num_list[2]=aaa
[root@localhost ~]# echo ${num_list[@]}
123 234 aaa 456 567替换元素值的特定内容
[root@localhost ~]# echo ${num_list[2]/aa/lualu-}
lualu-a
[root@localhost ~]# num_list[2]=${num_list[2]/aa/lualu-}
[root@localhost ~]# echo ${num_list[@]}
123 234 lualu-a 456 567
元素删除
删除单元素unset array_name[index]
删除整个数组unset array_name
简单实践
删除指定的元素
[root@localhost ~]# echo ${num_list[@]}
123 234 lualu-a 456 567
[root@localhost ~]# unset num_list[2]
[root@localhost ~]# echo ${num_list[@]}
123 234 456 567
[root@localhost ~]# unset num_list[2]
[root@localhost ~]# echo ${num_list[@]}
123 234 456 567
[root@localhost ~]# unset num_list[1]
[root@localhost ~]# echo ${num_list[@]}
123 456 567
[root@localhost ~]# echo ${!num_list[@]}
0 3 4
替换元素值的特定内容
[root@localhost ~]# unset num_list
[root@localhost ~]# echo ${!num_list[@]}[root@localhost ~]#
三、综合实践
数组关联
上一节,我们学习了shell环境下的数组定制的简写方式。数组的定制主要有如下两种:
定制索引数组 - 数组的索引是普通的数字declare -a array_name- 普通数组可以不事先声明,直接使用定制关联数组 - 数组的索引是自定义的字母declare -A array_name- 关联数组必须先声明,再使用
简单实践
实践1-定制索引数组
定制一个空内容的数组
[root@localhost ~]# declare -a course
[root@localhost ~]# declare -a | grep course
declare -a course='()'定制一个包含元素的数组
[root@localhost ~]# course=(yuwen shuxue yingyu)
[root@localhost ~]# declare -a | grep course
declare -a course='([0]="yuwen" [1]="shuxue" [2]="yingyu")'
实践2-定制关联数组
定制关联数组
[root@localhost ~]# declare -A score
[root@localhost ~]# declare -a | grep score
[root@localhost ~]# declare -A | grep score
declare -A score='()'关联数组和数字索引数组不能通用
[root@localhost ~]# declare -a score
-bash: declare: score: 无法将关联数组转化为索引数组
关联数组的操作
[root@localhost ~]# declare -A | grep score
declare -A score='([yingyu]="32" [yuwen]="67" [shuxue]="65" )'
[root@localhost ~]# echo ${!score[@]}
yingyu yuwen shuxue
[root@localhost ~]# echo ${score[@]}
32 67 65
数组案例
需求:
分别打印CPU 1min 5min 15min load负载值
命令提示:uptime信息显示:CPU 1 min平均负载为: 0.00CPU 5 min平均负载为: 0.01CPU 15 min平均负载为: 0.05
编写脚本
查看脚本内容
[root@localhost ~]# cat cpu_load.sh
#!/bin/bash
# 功能:采集系统cpu负载信息
# 版本:v0.1
# 作者:书记
# 联系:www.superopsmsb.com# 获取CPU负载情况
cpu_load=($(uptime | tr -s " " | cut -d " " -f 9-11 | tr "," " "))# 信息输出
echo -e "\e[31m\t系统cpu负载信息\e[0m"
echo -e "\e[32m================================"
echo "CPU 1 min平均负载为: ${cpu_load[0]}"
echo "CPU 5 min平均负载为: ${cpu_load[1]}"
echo "CPU 15 min平均负载为: ${cpu_load[2]}"
echo -e "================================\e[0m"
脚本执行后效果
[root@localhost ~]# /bin/bash cpu_load.sh系统cpu负载信息
================================
CPU 1 min平均负载为: 0.00
CPU 5 min平均负载为: 0.01
CPU 15 min平均负载为: 0.05
================================
服务管理
需求
服务的管理动作有:"启动" "关闭" "重启" "重载" "状态"
服务的管理命令有:"start" "stop" "restart" "reload" "status"
选择不同的动作,输出不同的服务执行命令,格式如下:systemctl xxx service_name
编写脚本
[root@localhost ~]# cat service_manager.sh
#!/bin/bash
# 功能:定制服务管理的功能
# 版本:v0.1
# 作者:书记
# 联系:www.superopsmsb.com# 定制普通数组
oper_array=(启动 关闭 重启 重载 状态)
# 定制关联数组
declare -A cmd_array
cmd_array=([启动]=start [关闭]=stop [重启]=restart [重载]=reload [状态]=status)# 服务的操作提示
echo -e "\e[31m---------------服务的操作动作---------------1: 启动 2: 关闭 3: 重启 4: 重载 5: 状态
--------------------------------------------"'\033[0m'# 选择服务操作类型
read -p "> 请输入服务的操作动作: " oper_num
echo
echo -e "\e[31m您选择的服务操作动作是: ${oper_array[$oper_num-1]}\e[0m"
echo -e "\e[32m===============服务的执行动作===============
您即将对服务执行如下命令:
\tsystemctl ${cmd_array[${oper_array[$oper_num-1]}]} service_name
=========================================="'\033[0m'
脚本执行效果
[root@localhost ~]# /bin/bash service_manager.sh
---------------服务的操作动作---------------1: 启动 2: 关闭 3: 重启 4: 重载 5: 状态
--------------------------------------------
> 请输入服务的操作动作: 3您选择的服务操作动作是: 重启
===============服务的执行动作===============
您即将对服务执行如下命令:systemctl restart service_name
==========================================