1、read赋值

read通过交互式的方式进行赋值

-p:交互的时候提示信息
-t:超过这个时间没有操作,自动退出
-s:不显示用户的输入,记录密码才用

基本用法:

[root@m01 ~]#read -p "请输入密码:" pass
请输入密码:12345
[root@m01 ~]#echo $pass
12345
[root@m01 ~]#read -p '请输入密码ip和用户名'  ip  user
请输入密码ip和用户名192.168.10.6 test
[root@m01 ~]#echo $ip
192.168.10.6
[root@m01 ~]#echo $user
test
[root@m01 ~]#

案例1:书写脚本,检查输入的域名是否可以ping通

[root@m01 /server/script/devops-shell]#vim check_url_ping.sh
read -p '请输入域名:' url
ping -c 3 $url &> /dev/null
if [ $? -eq 0 ]
then
   echo "域名$url可以ping通。"
else
   echo "域名$url ping不通"
fi

2、运算符

shell运算符含义
+加法
减法
*乘法
/除法
%取余,可以用于生成指定范围的随机数
^、**幂、指数,如2^10=1024,10个2相乘
i=i+1,i++计数
j=j+??、j+=??求和
&&并且,前一个命令执行成功,再执行后面的命令(判断)
||或者,前一个命令执行失败,再执行后面的命令(判断)

%:取余

[root@m01 ~]#echo $((4%3))
1

任何一个数对10取余,余数为0-9之间

[root@m01 ~]#echo $((RANDOM%10))
2
[root@m01 ~]#echo $((RANDOM%10))
5
[root@m01 ~]#echo $((RANDOM%10))
8
[root@m01 ~]#echo $((RANDOM%10))
2
[root@m01 ~]#

随机的数字(n)对一个数字取余,可以得到0到n-1范围的随机数

[root@m01 ~]#echo $RANDOM%5 | bc

&&:并且

[root@m01 ~]#ls /etc &> /dev/null  && echo 目录存在
目录存在
[root@m01 ~]#

||:或者

[root@m01 ~]#ls /etc &> /dev/null  ||  echo 目录存在
[root@m01 ~]#ls /etc000 &> /dev/null  ||  echo 目录b不存在
目录b不存在
[root@m01 ~]#

3、运算方法

运算的命令、符号说明应用场景
awk可以进行计算、带小数,可以与shell脚本进行变量传递一般计算都可以使用awk
bc带小数一般计算都可以使用bc,需要安装
expr计算,整数用于检查输入内容是否为数字的一种方法
let计算,整数,变量直接使用即可用于计算i++
$(())计算,整数,变量直接使用即可
$[]计算,整数,变量直接使用即可

1)awk计算

基础用法:

[root@m01 ~]#awk 'BEGIN{print 1/3}'
0.333333
[root@m01 ~]#awk 'BEGIN{print 1/3*100}'
33.3333
[root@m01 ~]#

在shell中使用awk

[root@m01 ~]#a=1
[root@m01 ~]#b=2
[root@m01 ~]#awk -v x=$a -v y=$b 'BEGIN{print x/y,x+y}'
0.5 3
[root@m01 ~]#

案例2:输入两个数字,进行计算

[root@m01 /server/script/devops-shell]#vim 11.num.calc.sh
#输入两个数字
read -p "请输入第1个数字:" num1
read -p "请输入第1个数字:" num2

#计算
awk -vn1=$num1 -vn2=$num2 'BEGIN{print "加法:"n1+n2}'

[root@m01 /server/script/devops-shell]#sh 11.num.calc.sh
请输入第1个数字:2
请输入第1个数字:3
加法:5
[root@m01 /server/script/devops-shell]#

2)bc

安装bc:yum install bc -y

基本用法,-l显示小数

[root@m01 ~]#echo 1/3 | bc
0
[root@m01 ~]#echo 1/3 | bc -l
.33333333333333333333
[root@m01 ~]#

3)expr

使用注意事项:需要使用空格,使用*的时候要转义

[root@m01 ~]#expr 1+2
1+2
[root@m01 ~]#expr 1 + 2  #要使用空格
3
[root@m01 ~]#

*的使用:

[root@m01 ~]#expr 1 * 2
expr: syntax error
[root@m01 ~]#expr 1 \* 2
2
[root@m01 ~]#

注意:expr 0 + 0的返回值是1

[root@m01 ~]#expr 0 + 0
0
[root@m01 ~]#echo $?
1
[root@m01 ~]#

案例3:前面的计算脚本修改:加入判断:

#输入两个数字
read -p "请输入第1个数字:" num1
read -p "请输入第1个数字:" num2
#判断输入的是否为数字
expr "$num1" + "$num2" &> /dev/null
if [ $? -gt 1 ];then  #判断返回值是否大于1
  echo "Usage:输入必须为数字"
  exit 1
fi
#计算
awk -vn1=$num1 -vn2=$num2 'BEGIN{print "加法:"n1+n2}'

4)let、$(())、$[]

不支持小数,一般进行简单计算

let

[root@m01 ~]#a=1
[root@m01 ~]#b=2
[root@m01 ~]#let c=a+b
[root@m01 ~]#echo $c
3
[root@m01 ~]#let x=3+5
[root@m01 ~]#echo $x
8
[root@m01 ~]#

let与i++

[root@m01 ~]#i=1
[root@m01 ~]#let i++
[root@m01 ~]#echo $i
2
[root@m01 ~]#

$(())

[root@m01 ~]#a=1
[root@m01 ~]#b=2
[root@m01 ~]#echo $((a+b))
3
[root@m01 ~]#

$[]

[root@m01 ~]#a=1
[root@m01 ~]#b=2
[root@m01 ~]#echo $[a+b]
3
[root@m01 ~]#

4、判断

4.1 条件表达式

条件表达式属于判断中的核心

1)格式

条件表达式也可以叫做条件测试语句。

查看帮助:man test

[]与[[]]的区别

含义与特点test 或 [][[]] 或 (())
共同点都可以用于判断都可以用于判断
区别1仅支持普通判断,不支持正则[[]]普通判断,支持正则
区别2表示逻辑关系(与、或、非)符号不同:-a、-o、!、-gt等[[]]使用的是:&&、||、!、>、<、>=、<=等
应用场景大部分情况下可以使用[]进行常见判断[[]]使用正则的时候使用2对中括号,(())可以用于运算

例如:

[root@m01 ~]#[ 1 -eq 2 ] && echo 成功 || echo 失败
失败
[root@m01 ~]#test 1 -eq 2  && echo 成功 || echo 失败
失败
[root@m01 ~]#
2)判断文件
条件表达-文件说明
-ff,file。判断是否存在,是否文件,如果是,则为真
-ddir,判断是否存在否是目录,如果是,则为真
-xexecutable,判断是否存在,是否有执行权限
-ssize,小写s。判断是否存在,文件大小是否大于0(是否为空),非空为真
-r是否有读权限
-w是否有写权限
-ntnewer then,两个文件修改时间,是否更加新
-otolder then,两个文件修改时间,是否更加旧
-L软连接
-e是否存在(任何类型的文件)

条件测试语句,不会直接显示提示对错,通过返回值提示(0则表示真,非0为假)

检查指定文件是否存在

[root@m01 ~]#[ -f 11.txt ] && echo 成功 || echo 失败
失败
[root@m01 ~]#[ -d /etc ] && echo 成功 || echo 失败
成功
[root@m01 ~]#
3)字符串比较

对比两个字符串的内容

字符串对比说明
“str1” = “str2”str1是否等于str2,如果相等则为真
“str1” != “str2”str1是否不等于str2,如果不相等则为真
-z “str”z,zero。检查str字符串是否为空,空则为真
-n “str”not zero。检查str字符串是否为空,非空则为真

一般情况下,字符串比较使用双引号引起来。如果不使用双引号可以写成:

${str}x=rootx
后面添加一个字符,来确保等号左边的字符串是空的情况下,不会报错

例如:

[root@m01 ~]#input=start
[root@m01 ~]#[ "$input" = "start" ] && echo "成立" || echo "失败"
成立
[root@m01 ~]#

判断是否是root用户执行

[ "$UID" != "0" ] && exit 4

判断服务是否运行、是否开机启动:

[root@m01 ~]#systemctl is-active sshd
active
[root@m01 ~]#systemctl is-enabled sshd
enabled
[root@m01 ~]#
4)比较大小(整数)
大小比较-整数[][[]]
大于-gt>
大于等于-ge>=
小于-lt<
小于等于-le<=
等于-eq==
不等于-ne!=

不支持小数的对比

比较小数,可以使用awk

例如:

free -h | awk -F"[ G]+" 'NR==2 && $(NF-1)>=1.2'
5)逻辑判断

逻辑判断:与、或、非

逻辑判断[][[]]
与(同时成立)条件1 -a 条件2 (a:and)&&
或(至少一个成立)条件1 -o 条件2 (o:or)||
非(取反)!!

与:

[root@m01 ~]#[[ 1 > 2 && 1 == 1 ]] && echo 成功 || echo 失败
失败
[root@m01 ~]#[ 1 -gt 2 -a 1 -eq 1 ] && echo 成功 || echo 失败
失败

或:

[root@m01 ~]#[[ 1 > 2 || 1 == 1 ]] && echo 成功 || echo 失败
成功
[root@m01 ~]#[ 1 -gt 2 -o 1 -eq 1 ] && echo 成功 || echo 失败
成功
[root@m01 ~]#[ "a" = "a"  -o 1 -eq 1 ] && echo 成功 || echo 失败
成功

非:

[root@m01 ~]#[[ ! 1 == 1 ]] && echo 成功 || echo 失败
失败
[root@m01 ~]#[ ! 1 -eq 1 ] && echo 成功 || echo 失败
失败
[root@m01 ~]#
6)正则表达式

初步使用正则

[root@m01 ~]#a=123
[root@m01 ~]#[[ $a =~ [0-9] ]] && echo 成功 || echo 失败
成功
[root@m01 ~]#b=123ss
[root@m01 ~]#[[ $b =~ [0-9] ]] && echo 成功 || echo 失败
成功
[root@m01 ~]#

上面案例中的正则,仅仅表示变量中只要有数字即可。

案例:精确匹配数字

[root@m01 ~]#b=123ss
[root@m01 ~]#[[ $b =~ ^[0-9]+$ ]] && echo 成功 || echo 失败
失败
[root@m01 ~]#b=123
[root@m01 ~]#[[ $b =~ ^[0-9]+$ ]] && echo 成功 || echo 失败
成功
[root@m01 ~]#[[ "$b" =~ ^[0-9]+$ ]] && echo 成功 || echo 失败
成功
[root@m01 ~]#
#匹配开头中间结尾全是数字

案例02:判断输入的是否为数字

[root@m01 /server/script/devops-shell]#vim 16.check_str.sh
#1、vars
read -p "请输入内容:" str
#2、判断
#是否为纯数字
[[ "$str" =~ ^[0-9]+$ ]] && {
   echo "$str是纯数字"
   exit  #默认是0
}
#是否为纯字母
[[ "$str" =~ ^[a-zA-Z]+$ ]] && {
   echo "$str是纯字母"
   exit  #默认是0
}
#其他
echo "$str 是数字、字母、其他组合"

缺点:如果输入的是小数,则会认为是其他,但小数也数字。

[[]]判断的坑:

[root@m01 ~]#[[ 100 > 20 ]] && echo 成功 || echo 失败
失败  #100大于20,但是结果为失败
[root@m01 ~]#[[ 300 > 20 ]] && echo 成功 || echo 失败
成功
[root@m01 ~]#

[[]]比较大小的时候,是一位一位的比较,先比较第1位,然后第2位…

[[ 100 > 20 ]]:

先比较第1位,1>2,结果为假

[[]]使用>=也可能会报错:

[root@m01 ~]#[[ 100 >=  20 ]] && echo 成功 || echo 失败
-bash: syntax error in conditional expression
-bash: syntax error near `20'
[root@m01 ~]#

因此,不太建议使用[[]]进行比较大小

4.2 if判断

格式1(单分支):

if [];then
  xxx
fi

或
if []
then
  xxx
fi

格式2(多分支):

if [];then
  xx
else
  xxx
fi

或者
if [];then
  xx
elif
then
  xxx
else
  xxx
fi

if单分支也可以使用以下方式代替:

[] && xxx
或
[] || xxx
1)单分支判断

应用场景:与&&、||类似,用于放在脚本开头进行判断

if 条件;then
   满足条件后执行的内容
fi

if、then可以分开写:

if 条件
then
   满足条件后执行的内容
fi

这种形式类似于&&或||形式

if [ 1 -eq 1 ];then
  echo "正确"
  exit 0
fi

可以写成:
[ 1 -eq 1 ] && {
  echo  "正确"
  exit
}
2)多分支判断

双分支:

if 条件;then
   xxx
else
   xxx
fi

多分支(2个以上分支):

if 条件;then
   xxx
elif  #else if可以有多个
then
   xxx
elif
then
   xxx
else
   xxx
fi

案例01:输入服务名称,检查其状态脚本

输入服务名字的方法:read方式或$1

检查是否运行:systemctl is-active 服务

是否开机启动:systemctl is-enabled 服务

[root@m01 /server/script/devops-shell]#vim 17.check_service.sh
#1、var
name=$1
#2、参数个数1个
[ $# -ne 1 ] && {
  echo "Please input service name"
  exit 1
}
#3、判断状态
run=`systemctl is-active $name`
#是否运行
if [ "$run" = "active" ];then
   echo "$name服务is running"
else
   echo "$name服务is not running"
fi
#是否开机启动
enable=`systemctl is-enabled $name`
if [ "$enable" = "enabled" ];then
   echo "$name服务开机启动"
else
   echo "$name服务没有开机启动"
fi

执行脚本:

[root@m01 /server/script/devops-shell]#sh 17.check_service.sh sshd
sshd服务is running
sshd服务开机启动
[root@m01 /server/script/devops-shell]#

案例02:检查根分区磁盘空间使用率

如果大于等于80%,提示磁盘空间不足,否则,提示磁盘空间正常

[root@m01 /server/script/devops-shell]#vim 18.check_disk.sh
#1、vars
root_used=`df -h | grep -w  / | awk '{print $(NF-1)}' | awk -F'%' '{print $1}'`
#2、判断
if [ $root_used -gt 80 ];then
  echo "磁盘空间不足"
else
  echo "磁盘空间正常"
fi

取出使用率也可以写成:

df -h | grep -w  / | awk -F'[ %]+' '{print $(NF-1)}'

-w:word

案例03:比大小

num1=20
num2=30
if [ $num1 -eq $num2 ];then
   echo "$num1 等于 $num2"
elif [ $num1 -lt $num2 ];then
   echo "$num1 小于 $num2"
else
   echo "$num1 大于 $num2"
fi

案例04:输出指定用户的信息

检查:

是否输入了用户名
用户是否存在,如果不存在,则退出,提示用户不存在
如果用户存在,则输出:
  是否可以登录
  uid、gid
  用户家目录
  最近一次登录情况

脚本:

[root@m01 /server/script/devops-shell]#vim 20.check_user_info.sh
#1、vars
username=$1

#2、检查输入的是否合规
# [[ ! "$username" =~ ^[a-zA-Z0-9_]+$ ]] && {
[[ "$username" =~ ^[a-zA-Z0-9_]+$ ]] || {
   echo "请输入正确格式的用户名"
   exit 1
}
#3、检查用户是否存在
id $username &> /dev/null
[ $? -ne 0 ] && {
  echo "用户不存在"
  exit 2
}
#4、获取信息
#是否可以登录(/bin/bash)
shell=`grep -w "^${username}" /etc/passwd | awk -F':' '{print $NF}'`
if [ "$shell" = "/bin/bash" ];then
  denglu=yes
else
  denglu=no
fi
#uid、gid
ids=`grep -w "^${username}" /etc/passwd | awk -F':' '{print $3,$4}'`
#家目录
homedir=`grep -w "^${username}" /etc/passwd | awk -F':' '{print $(NF-1)}'`
#最后1次登录情况
#lastlog -u 用户名
login=`lastlog -u $username | tail`
#5、信息显示
cat << EOF
#################################
  用户名:${username}
  是否可以登录:$denglu
  uid、gid:${ids}
  用户家目录:$homedir
  最后一次登录情况:
  $login
#################################
EOF

测试脚本:

[root@m01 /server/script/devops-shell]#sh 20.check_user_info.sh 
请输入正确格式的用户名
[root@m01 /server/script/devops-shell]#sh 20.check_user_info.sh 66
用户不存在
[root@m01 /server/script/devops-shell]#sh 20.check_user_info.sh root
#################################
  用户名:root
  是否可以登录:yes
  uid、gid:0 0
  用户家目录:/root
  最后一次登录情况:
  Username         Port     From             Latest
root             pts/1    192.168.10.1     Sat Jul 15 14:35:09 +0800 2023
#################################
[root@m01 /server/script/devops-shell]#