shell编程(二)
一、运算
1.运算符
运算符 | 含义 |
---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 取余 |
^或** 幂、指数 | |
i=i+1 i++ | 计算次数 |
j=j+ j+= | 求和,累加 |
&& | 并且,前一个命令执行成功,再执行后面的命令(判断) |
|| | 或者,前一个命令执行失败了,再执行后面的命令(判断) |
2.运算方法
运算的命令/符号 | 说明 | 应用场景 |
---|---|---|
awk | 可以进行计算,带小数,可以与shell脚本进行变量传递 | 一般计算都可以用awk |
bc | 带小数 | 一般计算都可以用bc.需要安装. |
expr | 进行计算,整数 | 一般用于检查输入内容是否为数字(方法之一). |
let | 进行计算,整数,变量直接使用即可 | 用于计算i++ |
$(()) | 进行计算,整数,变量直接使用即可 | |
$[] | 进行计算,整数,变量直接使用即可 |
2.1 awk
[root@m01 /server/scripts/devops-shell]# awk -vnum1=1 -vnum2=1 'BEGIN{print num1,num2,num1-num2}'
1 1 0
[root@m01 /server/scripts/devops-shell]# num1=2
[root@m01 /server/scripts/devops-shell]# num2=3
[root@m01 /server/scripts/devops-shell]# awk -vnum1=$num1 -vnum2=$num2 'BEGIN{print num1,num2,num1-num2}'
2 3 -1
[root@m01 /server/scripts/devops-shell]# awk -vnum1=$num1 -vnum2=$num2 'BEGIN{print num1,num2,num1**num2}'
2 3 8
[root@m01 /server/scripts/devops-shell]# awk -vnum1=$num1 -vnum2=$num2 'BEGIN{print num1,num2,num1^num2}'
2 3 8
补充:
awk -v 选项用于创建或修改awk的变量。-v是shell脚本与awk的桥梁
在awk各种变量直接使用即可,不要加上$n1,如果加上了会被awk识别为取列
2.2 bc
-l 显示小数
[root@m01 /server/scripts/devops-shell]# echo 5/3 |bc -l
1.66666666666666666666
[root@m01 /server/scripts/devops-shell]# echo 5/3 |bc
1
2.3 expr
#expr的+号等符号前后要加空格,使用*号要进行转义
[root@m01 /server/scripts/devops-shell]# expr 1 + 1
2
[root@m01 /server/scripts/devops-shell]# expr 1+1
1+1
[root@m01 /server/scripts/devops-shell]# expr 1 + 1
2
[root@m01 /server/scripts/devops-shell]# expr 0 + 0
0
[root@m01 /server/scripts/devops-shell]# echo $?
1
[root@m01 /server/scripts/devops-shell]# expr 0 + 0 + 1
1
[root@m01 /server/scripts/devops-shell]# echo $?
0
[root@m01 /server/scripts/devops-shell]# num1=1
[root@m01 /server/scripts/devops-shell]# num2=2
[root@m01 /server/scripts/devops-shell]# expr $num1 + $num2
3
[root@m01 /server/scripts/devops-shell]# echo $?
注意事项:
expr计算0+0 查看命令的返回值
expr进行计算的时候,结果为0,$? 返回值就是1
2.4 案例:对输入的内容检查是否为数字
[root@m01 /server/scripts/devops-shell]# cat check_num.sh
#!/bin/bash
##############################################################
# File Name:check_num.sh
# Version:V1.0
# Author:wh
# Desc:
##############################################################
read -p "请输入信息:" num
expr ${num} + 999 &>/dev/null
if [ $? -eq 0 ];then
echo "您输入${num}的是数字"
else
echo "您输入${num}的不是数字"
fi
2.5 案例:计算器,传入脚本中2个参数,进行计算, 输出结果。
[root@m01 /server/scripts/devops-shell]# cat calc.sh
#!/bin/bash
##############################################################
# File Name:calc.sh
# Version:V1.0
# Author:wh
# Desc:
##############################################################
num1=$1
num2=$2
expr ${num1} + ${num2} + 999 &>/dev/null
if [ $? -ne 0 ];then
echo "执行$0 脚本,请输入两个数字"
exit 1
fi
jia=`awk -vn1=$num1 -vn2=$num2 'BEGIN{ print n1+n2 }'`
jian=`awk -vn1=$num1 -vn2=$num2 'BEGIN{ print n1-n2 }'`
cheng=`awk -vn1=$num1 -vn2=$num2 'BEGIN{ print n1*n2 }'`
chu=`awk -vn1=$num1 -vn2=$num2 'BEGIN{ print n1/n2 }'`
cat<<EOF
$num1 + $num2 的结果为 $jia
$num1 - $num2 的结果为 $jian
$num1 * $num2 的结果为 $cheng
$num1 / $num2 的结果为 $chu
EOF
二、判断
1.条件表达式
1.1格式
条件表达式也可以叫条件测试语句
1.2面试题 [] [[]]区别
含义与特点 | test或[] | [[ ]]与(( )) |
---|---|---|
共同点 | 都可以用于判断 | 都可以用于判断 |
区别1 | 仅支持普通判断,不支持正则 | 普通判断,支持正则 |
区别2 | 表示逻辑关系(与或非)符号不同 -a -o ! -gt | [[]] && || ! > < <= >= |
1.3 判断文件
条件表达式 | 说明 |
---|---|
-f |
file 判断是否存在,判断这个是否为文件,如果是则为真(成立) |
-d |
dir 判断是否存在,判断这个是否为目录,如果是则为真(成立) |
-x |
executable 判断是否存在,是否有执行权限 |
-s | size 判断是否存在,文件大小是否大于0 (是否为空) 非空为真 |
-r | 是否有读权限 |
-w | 是否有写权限 |
-nt | newer than 两个文件修改时间 是否更加新 |
-ot | older than 两个文件修改时间 是否更加老 |
-L | 软连接 |
-e | 是否存在(任何类型文件) |
[root@m01 /server/scripts/devops-shell]# [ -f /etc/hostnam ] && echo 存在 || echo 不存在
不存在
[root@m01 /server/scripts/devops-shell]# [ -f /etc/hostname ] && echo 存在 || echo 不存在
存在
[root@m01 /server/scripts/devops-shell]# [ -d /etc/ ] && echo 存在 || echo 不存在
存在
[root@m01 /server/scripts/devops-shell]# [ -d /etc1/ ] && echo 存在 || echo 不存在
不存在
温馨提示:执行流程
&& 表示前面命令执行成功然后执行echo 成立。
|| 表示前面命令执行失败了,echo 失败
1.4 对比字符串
条件表达式 | 说明 |
---|---|
"str1" = "str2" | str1 是否等于str2,如果相等则为真 |
"str1" != "str2" | str1 是否等于str2,如果不相等则为真 |
-z "str" | zero 检查str字符串是否为空,空的则为真 |
-n "str" | not zero 检查str字符串是否为空,非空的则为真 |
[root@m01 /server/scripts/devops-shell]# test=123
[root@m01 /server/scripts/devops-shell]# [ -n "$test" ] && echo "变量存在且有值" ||echo "变量不存在或没值"
变量存在且有值
[root@m01 /server/scripts/devops-shell]# unset test
[root@m01 /server/scripts/devops-shell]# [ -n "$test" ] && echo "变量存在且有值" ||echo "变量不存在或没值"
变量不存在或没值
1.5 比大小(整数)
不支持小数的对比,仅支持整数
条件表达式 | [] | [[ ]] |
---|---|---|
大于 | -gt great than | > |
大于等于 | -ge great equal | >= |
小于 | -lt less than | < |
小于等于 | -le less equal | <= |
等于 | -eq equal | == |
不等于 | -ne not equal | != |
1.6 逻辑判断
条件表达式 | [] | [[ ]] |
---|---|---|
与(同时成立) | 条件1 -a 条件2 (and) | && |
或(只有有个成立的就行) | 条件1 -o 条件2 (or) | || |
非(取反) | ! | ! |
1.7 使用正则判断
#案例:使用正则精确匹配数字
[root@m01 /server/scripts/devops-shell]# num=123
[root@m01 /server/scripts/devops-shell]# [[ $num =~ ^[0-9]+$ ]]
[root@m01 /server/scripts/devops-shell]# [[ $num =~ ^[0-9]+$ ]] && echo "是数字" || echo "不是数字"
是数字
[root@m01 /server/scripts/devops-shell]# num=123aaa
[root@m01 /server/scripts/devops-shell]# [[ $num =~ ^[0-9]+$ ]] && echo "是数字" || echo "不是数字"
不是数字
[root@m01 /server/scripts/devops-shell]# num=-1
[root@m01 /server/scripts/devops-shell]# [[ $num =~ ^-?[0-9]+$ ]] && echo "是数字" || echo "不是数字"
是数字
1.8 案例:优化之前的计算器脚本,加入正则判断参 数是否为数字
[root@m01 /server/scripts/devops-shell]# cat calc_regx.sh
#!/bin/bash
##############################################################
# File Name:calc.sh
# Version:V1.0
# Author:wh
# Desc:
##############################################################
num1=$1
num2=$2
[[ $num1 =~ ^-?[0-9]+$ ]]||{
echo $num1 不是数字
exit 1
}
[[ $num2 =~ ^-?[0-9]+$ ]]||{
echo $num2 不是数字
exit 1
}
jia=`awk -vn1=$num1 -vn2=$num2 'BEGIN{ print n1+n2 }'`
jian=`awk -vn1=$num1 -vn2=$num2 'BEGIN{ print n1-n2 }'`
cheng=`awk -vn1=$num1 -vn2=$num2 'BEGIN{ print n1*n2 }'`
chu=`awk -vn1=$num1 -vn2=$num2 'BEGIN{ print n1/n2 }'`
cat<<EOF
$num1 + $num2 的结果为 $jia
$num1 - $num2 的结果为 $jian
$num1 * $num2 的结果为 $cheng
$num1 / $num2 的结果为 $chu
EOF
[root@m01 /server/scripts/devops-shell]# sh calc_regx.sh 10 20
10 + 20 的结果为 30
10 - 20 的结果为 -10
10 * 20 的结果为 200
10 / 20 的结果为 0.5
[root@m01 /server/scripts/devops-shell]# sh calc_regx.sh aa 20
aa 不是数字
[root@m01 /server/scripts/devops-shell]# sh calc_regx.sh 10 aa
aa 不是数字
2. if
2.1 单分支判断
if 条件;then
满足条件后执行的内容。
fi
if 条件
then
满足条件后执行的内容。
fi
2.2 双分支判断
if 条件;then
满足条件后执行的内容。
else
不满足条件执行的内容。
fi
#案例:检查根分区磁盘空间使用率
#如果大于等于80%提示磁盘空间不足.
#否则提示磁盘空间正常.
[root@m01 /server/scripts/devops-shell]# cat disk_check.sh
#!/bin/bash
##############################################################
# File Name:disk_check.sh
# Version:V1.0
# Author:wh
# Desc:
##############################################################
error=80
used=`df -h|awk '$6=="/"{print $5}'|awk -F '%' '{print $1}'`
if [ ${used} -ge ${error} ];then
echo "磁盘使用率为${used}%,磁盘空间不足"
else
echo "磁盘使用率为${used}%"
fi
2.3 多分支判断
if 条件;then
满足条件后执行的内容。
elif 条件;then #else if
满足elif条件,执行的内容。
elif 条件;then
满足elif条件,执行的内容。
else
不满足条件执行的内容。
fi
[root@m01 /server/scripts/devops-shell]# cat compare_num.sh
#!/bin/bash
##############################################################
# File Name:compare_num.sh
# Version:V1.0
# Author:wh
# Desc:
##############################################################
read -p '请输入两个数字:' num1 num2
[[ $num1 =~ ^-?[0-9]+$ ]]||{
echo $num1 不是数字
exit 1
}
[[ $num2 =~ ^-?[0-9]+$ ]]||{
echo $num2 不是数字
exit 1
}
if [ $num1 -eq $num2 ];then
echo "$num1 = $num2"
elif [ $num1 -gt $num2 ];then
echo "$num1 > $num2"
else
echo "$num1 < $num2"
fi
#案例:输出指定用户的信息
温馨提示:这个脚本未来可以用于做安全检查。
检查
是否输入了用户名。
这个用户是否存在,如果不存在则退出,提示用户不存在。
如果用户存在则输出下面的信息:
是否可以登录
用户uid,gid
用户家目录
最近1次登录情况。
[root@m01 /server/scripts/devops-shell]# cat secure_check_user.sh
#!/bin/bash
##############################################################
# File Name:secure_check_user.sh
# Version:V1.0
# Author:wh
# Desc:
##############################################################
#输入用户名
read -p "请输入用户名:" user
#检查是否输入
if [ $# -eq 1 ];then
echo "请输入用户名"
fi
id ${user} &> /dev/null
#判断用户是否存在
if [ $? -ne 0 ];then
echo "${user} 不存在"
exit 1
fi
#判断用户是否可以登录
user_shell=`awk -F ':' -vname=${user} '$1==name{print $NF}' /etc/passwd`
if [ ${user_shell} = '/bin/bash' ];then
user_login="用户可以登录"
else
user_login="用户不可以登录"
fi
user_uid=`awk -F ':' -vname=${user} '$1==name{print $3}' /etc/passwd`
user_gid=`awk -F ':' -vname=${user} '$1==name{print $4}' /etc/passwd`
user_home=`awk -F ':' -vname=${user} '$1==name{print $(NF-1)}' /etc/passwd`
user_lastlog=`lastlog |grep -w ${user}`
#输出结果
echo "===================================="
echo "用户名:${user}"
echo "用户uid:${user_uid}"
echo "用户gid:${user_gid}"
echo "用户家目录:${user_home}"
echo "用户最后一次登录信息:${user_lastlog}"
echo "===================================="
[root@m01 /server/scripts/devops-shell]# sh secure_check_user.sh
请输入用户名:a
a 不存在
[root@m01 /server/scripts/devops-shell]# sh secure_check_user.sh
请输入用户名:root
====================================
用户名:root
用户uid:0
用户gid:0
用户家目录:/root
用户最后一次登录信息:root pts/0 10.0.0.1 Fri Feb 24 14:53:20 +0800 2023
====================================
#注意:
awk在脚本中用的话,参数要用-v
3.case
3.1 概述
case语句格式
case "变量" in
start)
命令1
stop)
命令2
restart)
命令3
*)
错误提示
esac
case语句vs if多分支
case 一般用于固定的菜单选择情况.运行脚本用户输入1,2,3,4. start|stop|restart....
if 可以用于一些范围的比较.
3.2案例 会所菜单展示程序
[root@m01 /server/scripts/devops-shell]# cat case_menu.sh
#!/bin/bash
##############################################################
# File Name:case_menu.sh
# Version:V1.0
# Author:wh
# Desc:
##############################################################
cat <<EOF
本会所可选的套餐
输入1选择: 138套餐) 吃饱套餐
输入2选择: 443套餐) 吃饱喝足套餐
输入3选择: 888套餐) 吃喝拉撒套餐
输入4选择: 1688套餐) 你想干啥就干啥套餐
EOF
read -p "请您选择套餐:" num
case "$num" in
1)
echo "您选择了138套餐) 吃饱套餐"
;;
2)
echo "您选择了443套餐) 吃饱喝足套餐"
;;
3)
echo "您选择了888套餐) 吃喝拉撒套餐"
;;
4)
echo "您选择了1688套餐) 你想干啥就干啥套餐"
;;
5)
echo "恭喜您,激活了会所的惊喜套餐"
;;
*)
echo "本会所没有此套餐,请重新选择"
esac
3.3 案例 判断用户输入的是yes还是no
[root@m01 /server/scripts/devops-shell]# cat case_yes_no.sh
#!/bin/bash
##############################################################
# File Name:case_yes_no.sh
# Version:V1.0
# Author:wh
# Desc:
##############################################################
read -p "input yes or no:" choice
case "$choice" in
yes|y|Y|Yes) echo "您输入的是yes" ;;
no|n|N|No) echo "您输入的是no" ;;
esac
[root@m01 /server/scripts/devops-shell]# sh case_yes_no.sh
input yes or no:y
您输入的是yes
[root@m01 /server/scripts/devops-shell]# sh case_yes_no.sh
input yes or no:n
您输入的是no
三、函数
1.概述
应用场景:
在书写脚本的时候,尽量使用函数,规范脚本。
让脚本的开发,更加模块化。
方便后期调试,调试的时候只需要注释函数即可。
2.格式及实战应用
#定义方式01 最完整
function show() {
命令
命令
内容
return n #函数的返回值
}
#定义方式02 精简写法 一般使用这一种.
show() {
命令
命令
内容
return n #函数的返回值
}
#定义方式03
function show {
命令
命令
内容
return n #函数的返回值
}
3.函数基本格式与使用
[root@m01 /server/scripts/devops-shell]# cat func.sh
#!/bin/bash
##############################################################
# File Name:func.sh
# Version:V1.0
# Author:wh
# Desc:
##############################################################
show(){
echo "世界,你好!!!!"
}
show
[root@m01 /server/scripts/devops-shell]# sh func.sh
世界,你好!!!!
4.函数传参
位置参数 | shell脚本中 | 函数中 |
---|---|---|
$n | 脚本的第n个参数 | 函数的第n个参数 |
$0 | 脚本的名字 | 脚本的名字 |
$# | 脚本的参数的格式 | 函数参数个数 |
$@/$* | 脚本所有的参数 | 函数所有的参数 |
[root@m01 /server/scripts/devops-shell]# cat func_params.sh
#!/bin/bash
##############################################################
# File Name:func_params.sh
# Version:V1.0
# Author:wh
# Desc:
##############################################################
show() {
cat <<EOF
show函数的参数个数:$#
show函数的所有参数:$*
$1.com
$1.cn
$1.org
$1.企业
$1.icu
$1.我爱你
EOF
}
show wh wh123
#show $1 #这是脚本的第1个参数
[root@m01 /server/scripts/devops-shell]# sh func_params.sh
show函数的参数个数:2
show函数的所有参数:wh wh123
wh.com
wh.cn
wh.org
wh.企业
wh.icu
wh.我爱你
5.案例:sersync服务管理脚本
书写脚本,用于管理sersync服务.
sh data_sync.sh start|stop|restart|status
分析
如果用户输入的是start,则运行sersync启动的命令。
如果用户输入的是stop,则运行关闭sersync的命令。
如果用户输入的是status,则显示sersync是否运行中,pid。
如果用户输入的是restart,则运行stop的命令,然后运行start的命令。
如果用户输入的是其他的内容,则提示输入错误,提示格式。
[root@m01 /server/scripts/devops-shell]# cat sersync.sh
#!/bin/bash
##############################################################
# File Name:sersync.sh
# Version:V1.0
# Author:wh
# Desc:
##############################################################
choice=$1
sersync_pid=`ps -ef |grep sersync2.*xml|grep -v grep |awk '{print $2}'`
sersync_count=`ps -ef |grep sersync2.*xml |grep -v grep |wc -l`
#开启服务
sersync_start(){
if [ ${sersync_count} -eq 0 ];then
sersync2 -rdo /app/tools/sersync/confxml.xml &>/dev/null
else
echo "sersync已启动"
fi
}
#关闭服务
sersync_stop(){
if [ ${sersync_count} -eq 0 ];then
echo "sersync未启动"
else
kill ${sersync_pid}
fi
}
#重启服务
sersync_restart(){
if [ ${sersync_count} -ne 0 ];then
kill ${sersync_pid}
fi
sersync2 -rdo /app/tools/sersync/confxml.xml &>/dev/null
}
#服务状态
sersync_status(){
if [ ${sersync_count} -eq 0 ];then
echo "sersync未启动"
else
echo "sersync is running,pid为${sersync_pid}"
fi
}
#错误提示
error_msg(){
echo "help:$0 {start|stop|restart|status}"
}
case $choice in
start) sersync_start ;;
stop) sersync_stop ;;
restart) sersync_restart ;;
status) sersync_status ;;
*) error_msg ;;
esac
温馨提示:
脚本名字尽量不要包含服务名字.
原因: 脚本运行的时候也是个进程,ps会过滤出这个进程,导致判断失败.
解决:
方案01: 书写脚本,脚本的文件名不包含服务名字即可.
方案02: 过滤进程的时候排除下文件名字(脚本文件)
四、案例 检查指定的地址的端口是否可以访问
[root@m01 /server/scripts/devops-shell]# cat check_access.sh
#!/bin/bash
##############################################################
# File Name:check_access.sh
# Version:V1.0
# Author:wh
# Desc: 检查指定的地址的端口是否可以访问
##############################################################
ip=$1
port=$2
if [ $# -ne 2 ];then
echo "请输入ip和端口"
exit
fi
check_port(){
state=`nmap -p${port} ${ip} |grep ${port}|awk '{print $2}'`
# state=`nmap -p${port} ${ip} |grep -wc open|wc -l`
# state=`echo q |telnet -e q ${port} ${ip}`
if [ "$state" = "open" ];then
echo "${ip}的${port}开启"
else
echo "${ip}的${port}关闭"
fi
}
main(){
check_port
}
main
五、案例 检查指定url是否可以访问
[root@m01 /server/scripts/devops-shell]# cat check_url.sh
#!/bin/bash
##############################################################
# File Name:check_url.sh
# Version:V1.0
# Author:wh
# Desc:检查url是否可以访问
##############################################################
url=$1
if [ $# -ne 1 ];then
echo "请输入正确的url"
exit
fi
check_url(){
curl ${url} &>/dev/null
# curl -s -I www.baidu.com |awk 'NR==1{print $2}'
if [ $? -eq 0 ];then
echo "${url} 可以访问"
else
echo "${url} 不能访问"
fi
}
check_url
#补充:
wget方法
wget -q spider www.baiduavavavavavaavvvvvvv.com
-q不输出额外内容
spider不下载文件,仅仅访问测试.
标签:shell,Linux,编程,devops,echo,scripts,server,root
From: https://www.cnblogs.com/world-of-yuan/p/17169454.html