Shell编程DAY11. 为什么要学习shell?2. 学习shell用到的基础知识3. 编程语言4. shell的工作方式5. shell脚本规范6. 第一个shell脚本6.1 第一个shell脚本6.2 执行脚本常用的方式6.2.1 通过bash或sh解释器执行6.2.2 使用路径方式:全路径或相对路径6.2.4 其他的shell执行方式7. 变量7.1 什么是变量?7.2 变量的种类:7.4 和环境变量相关的文件7.5 定义环境变量7.6 变量值的定义7.7 核心位置变量8. 脚本传参的三种方式9.作业:DAY21. 变量子串1.1 变量子串切片1.2 子串的长度统计1.3 子串的删除(支持通配符)1.4 子串的替换2. 数值运算3. 条件表达式4. 数值比较5. 字符串比较DAY31. 流程控制语句1.1 if判断语句1.1.1 if单分支1.1.2 if双分支1.1.3 if多分支1.1.4 if判断案例1.1.5 菜单的使用方法2.for循环语句2.1 for循环语法格式2.2 案例3. while循环语句3.1 while循环语法格式3.2 案例3.3 while读取文件值3,4 流程控制语句参数DAY44. case循环语句4.1 case语法结构4.2 案例
安装操作系统 CentOS6.X CentOS7.X 手动方式安装 克隆方式
优化 SSH 关闭Selinux 优化防火墙 放行 80 443 SSH端口 127.0.0.1 zabbix监控 10051 个人需求 加大文件描述符 时间同步
硬件时间 软件时间 YUM源...... 写入shell脚本
安装服务 Nginx Apache Tomcat PHP MySQL Redis Mongo docker.....
代码上线 shell脚本自动化发布自动化回滚
zabbix监控 硬件 软件 进程 端口号 自定义监控 shell脚本+定时任务
日志分析日志统计 三剑客+定时任务+shell脚本 日志展示-->ELK
业务层面
辅助开发程序 python nohup python3.5 test.py & nohup.out 大量的日志
shell Python Go ruby c c++ java perl...
编译型语言 只编译一次 后面直接运行代码即可
解释型语言 运行一次 解释一次
shell和python区别
通过xshell登录到系统中 当前的位置属于父shell 所有的文件 在执行的时候调用子shell执行 执行结束子shell退出
[root@shell scripts]# vim first_shell.sh#this is first shell script #脚本的注释echo "hello world" #脚本内容xxxxxxxxxx[root@shell scripts]# sh first_shell.sh hello world[root@shell scripts]# bash first_shell.sh hello worldxxxxxxxxxx#使用此种方式执行脚本时,必须给与脚本执行权限 x[root@shell scripts]# chmod +x first_shell.sh [root@shell scripts]# ./first_shell.sh hello world[root@shell scripts]# /server/scripts/first_shell.sh hello world
xxxxxxxxxx[root@shell scripts]# cat first_shell.sh |bashhello world[root@shell scripts]# bash < first_shell.sh hello world用一个固定的字符串表示不固定的值称为变量
xxxxxxxxxx#变量的执行加载顺序 不一定是生效顺序 变量谁最后定义的谁优先生效 重复赋值1./etc/profile2..bash_profile #家目录中隐藏文件3..bashrc #家目录中的隐藏文件4./etc/bashrcxxxxxxxxxx#变量名的定义方式: 要求字符串下划线数字的组合 下划线或者字符串开头 不能以数字开头 名称见名知其意 等号两端不允许有空格#变量名的书写方式:NAME_AGE= #全大写 系统默认的变量都是大写Name_Age #大驼峰语法name_Age #小驼峰语法name_age #全小写xxxxxxxxxx#字符串定义 必须是连续的字符串 值不允许有空格[root@shell ~]# name=iamjoker[root@shell ~]# echo $nameiamjoker[root@shell ~]# name='i am joker'[root@shell ~]# echo $namei am joker[root@shell ~]# name="i am joker"[root@shell ~]# echo $namei am joker
#双引号和单引号的区别 双引号解析变量 单引号所见即所得不能解析变量 不加引号可以解析变量
#数字的定义[root@shell ~]# age="12 23 2 34"[root@shell ~]# echo $age12 23 2 34
#命令的定义:使用``或$()[root@shell ~]# time=`date +%F-%H-%M-%S`[root@shell ~]# echo $time2024-03-06-11-14-09
[root@shell ~]# time=$(date +%F-%H-%M-%S)[root@shell ~]# echo $time2024-03-06-11-14-30[root@shell ~]# echo $time2024-03-06-11-14-30[root@shell ~]# echo $time2024-03-06-11-14-30
#问题:按照此种方式定义如时间这样的值会变的变量,发现每次执行结果都是相同的,原因是在第一次定义变量的时候已经将命令执行结果的值赋予了time这个变量,所以每次提取变量的值也只是在提取第一次命令的执行结果,因此不会发生变化。
[root@shell scripts]# vim time.shtime='date +%F-%H-%M-%S' #变量值加上单引号,实际上是将单引号里的命令赋予变量time,并不是将变量值赋予timeecho `$time` #加上反引号,实际上执行的是echo `date +%F-%H-%M-%S`,因此每次执行都是在执行反引号中的命令,所以结果会发生变化sleep 2echo `$time`[root@shell scripts]# sh time.sh 2024-03-06-11-20-342024-03-06-11-20-36
#变量定义变量
[root@shell scripts]# ip=`ifconfig eth0|awk 'NR==2{print $2}'`[root@shell scripts]# echo $ip10.0.0.13[root@shell scripts]# dir=${ip}_${time} #变量定义变量时,=右边的变量值中的变量,需要分别加上{}[root@shell scripts]# echo $dir10.0.0.13_2024-03-06-11-14-30
#当shell脚本中出现2条以上相同的命令,最好定义成变量xxxxxxxxxx$0 #获取shell脚本的名称 执行如果带全路径 则$0带全路径 *****$n #n为数字 从1开始 $1为脚本的第一个参数 从$9往后 我们需要加${10} ***** [root@shell scripts]# cat test.sh #!/bin/bash echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} #变量为两位数时,需要加上{} [root@shell scripts]# sh test.sh {a..z} a b c d e f g h i j k$# #获取脚本传参的总个数 针对传入的个数进行判断 ***** $* #获取脚本传参的所有的参数 在循环体中不同 加上顺引号视为单个字符串 了解 $@ #获取脚本传参的所有的参数 在循环体中不同 加上双引号视为独立的参数 了解$? #获取上一条命令的返回值 0为成功 非0失败 ***** [root@shell ~]# ping -c1 -W1 www.baidu.com &>/dev/null [root@shell ~]# echo $? 0$$ #获取脚本的PID进程号 **$! #获取上一个在后台运行脚本的PID号 测试常用 **$_ #获取脚本的最后一个参数或者是字符串等 类似esc . 了解
[root@localhost ~]# vim example.sh# exampleecho "当前脚本的名称是$0"echo "总共有$#个参数"echo "分别是$*"echo "第一个是$1,第二个是$2,第三个是$3"[root@localhost ~]# bash example.sh 1 1 2 3 4 5 6当前脚本的名称是exampl.sh总共有7个参数分别是1 1 2 3 4 5 6第一个是1,第二个是1,第三个是2xxxxxxxxxx#第一种:直接传参[root@shell scripts]# sh chuancan1.sh joker 300joker 300
#第二种:赋值传参[root@shell scripts]# vim chuancan1.shname=$1age=$2
echo $nameecho $age[root@shell scripts]# sh chuancan2.sh joker 300joker300
#第三种:read读入#第一种书写方式:[root@shell scripts]# vim chuancan3.shread -p "请输入你的姓名:" nameread -p "请输入你的年龄:" ageecho "你的姓名是:$name"echo "你的年龄是:$age"
[root@shell scripts]# sh chuancan3.sh 请输入你的姓名:joker请输入你的年龄:18你的姓名是:joker你的年龄是:18
#第二种书写方式read -p "请输入你的姓名和年龄:" name age
echo "你的姓名是:$name"echo "你的年龄是:$age"
[root@shell scripts]# sh chuancan3.sh 请输入你的姓名:joker请输入你的年龄:18你的姓名是:joker你的年龄是:18xxxxxxxxxx#修改主机名称read -p "输入主机名称: " namehostnamectl set-hostname $name
#修改IP地址#获取当前的IP地址ip_dir=/etc/sysconfig/network-scripts/ifcfg-eth0sip=`awk -F= '/IPADDR/{print $NF }' $ip_dir`read -p "输入IP: " ipsed -i "s#$sip#$ip#g" $ip_dirgrep $ip $ip_dirxxxxxxxxxx[root@shell ~]# name="i am joker"[root@shell ~]# echo ${name:2:2}am[root@shell ~]# echo ${name:2:3}am[root@shell ~]# echo ${name:2:4}am jx
#第一种方式:[root@shell ~]# echo $name|wc -L10#第二种方式:[root@shell ~]# expr length "$name"10#第三种方式:[root@shell ~]# echo $name|awk '{print length}'10#第四种方式:[root@shell ~]# echo ${#name}10
xxxxxxxxxx# #从前往后删除 ##贪婪匹配[root@shell scripts]# vim for_length.sh[root@shell scripts]# url=www.joker.org[root@shell scripts]# echo ${url#www.}joker.org[root@shell scripts]# echo ${url#*.}joker.org[root@shell scripts]# echo ${url##*.}org
# %从后往前删除[root@shell scripts]# echo ${url%.*}www.joker[root@shell scripts]# echo ${url%.*.*}wwwxxxxxxxxxx[root@shell scripts]# echo ${url/w/J}Jww.joker.org[root@shell scripts]# echo ${url/www/JJJ}JJJ.joker.orgxxxxxxxxxxexpr #只支持整数运算[root@shell ~]# expr 1 + 12[root@shell ~]# expr 1 + 100101[root@shell ~]# expr 10 - 100[root@shell ~]# expr 10 * 10expr: syntax error[root@shell ~]# expr 10 \* 10100[root@shell ~]# expr 10 / 101
$(()) #只支持整数运算[root@shell scripts]# echo $((10+10))20[root@shell scripts]# echo $((10-10))0[root@shell scripts]# echo $((10*10))100[root@shell scripts]# echo $((10/10))1#随机数取余数 RANDOM 0-32767之间的数字[root@shell scripts]# echo $((RANDOM%100+1))82
$[] #只支持整数运算[root@shell scripts]# echo $[10+10]20[root@shell scripts]# echo $[10-10]0[root@shell scripts]# echo $[10/10]1[root@shell scripts]# echo $[10*10]100[root@shell scripts]# echo $[10**10]10000000000
let #只支持整数运算[root@shell ~]# let a=1+1[root@shell ~]# echo $a2[root@shell ~]# let a=1*10[root@shell ~]# echo $a10[root@shell ~]# let i=i+1[root@shell ~]# echo $i2[root@shell ~]# let i++[root@shell ~]# echo $i3[root@shell ~]# let i=i+1[root@shell ~]# echo $i4
bc #支持整数和小数运算[root@shell ~]# echo 10+10|bc20[root@shell ~]# echo 10+10.5|bc20.5[root@shell ~]# echo 10*10.5|bc105.0[root@shell ~]# echo 10-10.5|bc-.5[root@shell ~]# echo 10/10.5|bc0
awk [root@shell ~]# awk 'BEGIN{print 10+10}'20[root@shell ~]# echo 10 20|awk '{print $1+$2}'30[root@shell ~]# echo 10 20|awk '{print $1*$2}'200[root@shell ~]# echo 10 20|awk '{print $1/$2}'0.5[root@shell ~]# echo 10 20|awk '{print $1^$2}'100000000000000000000xxxxxxxxxx1)文件表达式语法结构:第一种: test -f /etc/hosts [root@shell ~]# test -f /etc/hosts && echo "文件存在"文件存在[root@shell ~]# test -f /etc/host && echo "文件存在"[root@shell ~]# test -f /etc/host && echo "文件存在" || echo "文件不存在"文件不存在[root@shell ~]# test -f /etc/hosts && echo "文件存在" || echo "文件不存在"文件存在
第二种: 常用 [ -f /etc/hosts ] # 判断是否为普通文件 [ -d file ] # 文件存在并且为目录 [ -e file ] # 文件存在则为真 [ -r file ] # 文件可读则为真 [ -w file ] # 文件可写则为真 [ -x file ] # 文件可执行则为真 [root@shell ~]# [ -f /etc/passwd ] && echo "文件存在" || echo "文件不存在"文件存在[root@shell ~]# [ -f /etc/passwdddd ] && echo "文件存在" || echo "文件不存在"文件不存在
[root@shell ~]# [ -d /etc/passwd ] && echo "文件存在" || echo "文件不存在"文件不存在[root@shell ~]# [ -d /etc/ ] && echo "文件存在" || echo "文件不存在"文件存在
[root@shell ~]# [ -x /etc/ ] && echo "文件存在" || echo "文件不存在"文件存在
#注意: 表达式中支持变量和命令
[root@shell ~]# dir=/tmp[root@shell ~]# [root@shell ~]# [ -d $dir ] && echo "文件存在" || echo "文件不存在"文件存在[root@shell ~]# dir=/tmppppp[root@shell ~]# [ -d $dir ] && echo "文件存在" || echo "文件不存在"文件不存在
[root@shell ~]# ls -d /etc/sysconfig//etc/sysconfig/[root@shell ~]# [ -d `ls -d /etc/sysconfig/` ] && echo "文件存在" || echo "文件不存在"文件存在
案例:1. -d[root@shell ~]# [ -d ${name}_$ip ] || mkdir ${name}_$ip
2. -f 案例 functions shell脚本的函数库[root@shell ~]# [ -f /etc/init.d/functions ]
判断函数库是否存在 存在则加载[root@shell ~]# [ -f /etc/init.d/functions ] && . /etc/init.d/functions
[root@shell scripts]# cat ping.sh [ -f /etc/init.d/functions ] && . /etc/init.d/functionsping -c1 -W1 $1 &>/dev/null[ $? -eq 0 ] && action "ping $1 is.." /bin/true || action "ping $1 is.." /bin/false
[root@shell scripts]# sh ping.sh www.baidu.comping www.baidu.com is.. [ OK ][root@shell scripts]# sh ping.sh www.baidu.commmmmmping www.baidu.commmmmm is.. [FAILED]xxxxxxxxxx语法结构第一种: test 整数1 比较符 整数2第二种: [ 整数1 比较符 整数2 ] 比较符INTEGER1 -eq INTEGER2 相等 -eqINTEGER1 -ge INTEGER2 大于或者等于 -ge INTEGER1 -gt INTEGER2 大于 -gtINTEGER1 -le INTEGER2 小于或者等于 -leINTEGER1 -lt INTEGER2 小于 -ltINTEGER1 -ne INTEGER2 不等于 -ne
[root@shell ~]# test 10 -eq 10 && echo 成立 || echo 不成立成立[root@shell ~]# test 10 -ne 10 && echo 成立 || echo 不成立不成立[root@shell ~]# test 10 -ne 5 && echo 成立 || echo 不成立成立
[root@shell ~]# [ 10 -eq 10 ] && echo 成立 || echo 不成立成立[root@shell ~]# [ 10 -ne 10 ] && echo 成立 || echo 不成立不成立[root@shell ~]# [ 15 -ne 10 ] && echo 成立 || echo 不成立成立[root@shell ~]# [ 15 -gt 10 ] && echo 成立 || echo 不成立成立[root@shell ~]# [ 10 -ge 10 ] && echo 成立 || echo 不成立成立[root@shell ~]# [ 10 -le 10 ] && echo 成立 || echo 不成立成立
支持命令[root@shell ~]# [ 50 -gt `echo $((RANDOM%100))|tee file.txt` ] && echo "成立" || echo 不成立成立[root@shell ~]# cat file.txt 20
[root@shell ~]# [ 20 -eq `cat /etc/passwd|wc -l` ][root@shell ~]# echo $?0
案例1:统计磁盘使用率 如果大于80%则发送邮件 否则输出当前的使用率正常1.查看磁盘使用率df -h 取行[root@shell ~]# df -h|awk 'NR==6'/dev/sda3 18G 1.9G 16G 11% /
[root@shell ~]# df -h|grep /dev/sda3/dev/sda3 18G 1.9G 16G 11% /
[root@shell ~]# df -h|grep /$/dev/sda3 18G 1.9G 16G 11% /
[root@shell ~]# df -h|sed -n '/\/$/p'/dev/sda3 18G 1.9G 16G 11% /
[root@shell ~]# df -h|awk '/\/$/'/dev/sda3 18G 1.9G 16G 11% /
取到百分比[root@shell ~]# df -h|awk '/\/$/'|awk '{print $(NF-1)}'11%
和我们的值进行比较 test []
写入脚本[root@shell scripts]# cat disk.sh use_disk=`df -h|awk '/\/$/'|awk '{print $(NF-1)}'`[ ${use_disk%\%} -gt 10 ] && echo "send mail......" || echo "磁盘使用率正常 当前使用率为: $use_disk"
案例2: 内存使用百分比 大于5报警 小于5输出正常值统计百分比[root@shell ~]# free|awk 'NR==2{print $3/$2*100}'8.49266
整数比较案例 输入两个数字进行比对 大于 等于 小于[root@shell scripts]# cat diff.sh[ $1 -gt $2 ] && echo "$1>$2"[ $1 -lt $2 ] && echo "$1<$2"[ $1 -eq $2 ] && echo "$1=$2"[root@shell scripts]# sh diff.sh 20 3020<30[root@shell scripts]# sh diff.sh 20 1020>10[root@shell scripts]# sh diff.sh 20 2020=20
多整数比较语法结构: [ 整数1 比较符 整数2 ] -o or 或者 -a and并且 [ 整数1 比较符 整数2 -o 整数1 比较符 整数2 -o 整数1 比较符 整数2 ]
[root@shell ~]# [ 10 -eq 10 -o 10 -gt 20 -o 20 -lt 10 ] && echo "成立" ||echo "不成立"成立[root@shell ~]# [ 10 -eq 10 -a 10 -gt 20 -o 20 -lt 10 ] && echo "成立" ||echo "不成立"不成立[root@shell ~]# [ 10 -eq 10 -a 10 -gt 20 -o 2 -lt 10 ] && echo "成立" ||echo "不成立"成立
支持正则 [[]] && 并且 || 或者[root@shell ~]# [[ 10 -eq 10 && 10 -gt 5 ]] && echo "成立" ||echo "不成立"成立[root@shell ~]# [[ 10 -eq 20 && 10 -gt 5 ]] && echo "成立" ||echo "不成立"不成立[root@shell ~]# [[ 10 -eq 20 || 10 -gt 5 ]] && echo "成立" ||echo "不成立"成立x
字符串比对语法结构: test user = user [ "user" = "user" ]
[root@shell ~]# [ "root" = "root" ] && echo 成立 || echo 不成立成立[root@shell ~]# [ "roo" = "root" ] && echo 成立 || echo 不成立不成立[root@shell ~]# [ ! "roo" = "root" ] && echo 成立 || echo 不成立成立
[root@shell ~]# [ $USER = "root" ] && echo 成立 || echo 不成立成立
[root@shell ~]# [ root = root -a user = user ][root@shell ~]# [ root = root -a user = user ] && echo 成立 || echo 不成立成立[root@shell ~]# [ oot = root -a user = user ] && echo 成立 || echo 不成立不成立[root@shell ~]# [ oot = root -o user = user ] && echo 成立 || echo 不成立成立
[root@shell ~]# AAA=""[root@shell ~]# [ -z $AAA ] && echo 成立 || echo 不成立成立[root@shell ~]# AAA="aaa"[root@shell ~]# [ -z $AAA ] && echo 成立 || echo 不成立不成立[root@shell ~]# [ -n $AAA ] && echo 成立 || echo 不成立成立
案例: 传参不允许字符串为空[root@shell scripts]# cat ping.sh [ -f /etc/init.d/functions ] && . /etc/init.d/functionswhile truedo read -p "请输入一个ip或url地址: " url [ $url = exit -o $url = q ] && exit ping -c1 -W1 $url &>/dev/null re=$? [ -z $url ] && echo "必须传一个url地址" && exit [ $re -eq 0 ] && action "ping $url is.." /bin/true || action "ping $url is.." /bin/false
done
正则比对
[root@shell ~]# [[ root =~ ^r ]] && echo 成立 || echo 不成立成立[root@shell ~]# [[ root =~ t$ ]] && echo 成立 || echo 不成立成立
[root@shell ~]# [[ $USER =~ t$ ]] && echo 成立 || echo 不成立成立xxxxxxxxxx单分支: 一个条件一个结果
if [ 条件表达式 ];then [ 10 -eq 10 ] && echo ok 命令的集合fi
if [ 条件表达式 ]then 命令的集合fi
举例: 一个条件 只对应的是一个结果if [ 你有钱 ]then 我就嫁给你fixxxxxxxxxx双分支结构: 一个条件 两个结果if [ 条件表达式 ] [ 10 -eq 10 ] && echo ok || echo error then 执行的命令else 否则执行什么命令fi
if [ 你有钱 ]then 我就嫁给你else 拜拜fixxxxxxxxxx多分支: 多个条件 多个结果if [ 条件表达式 ];then 成立执行的命令elif [ 条件表达式 ];then 成立执行的命令 elif [ 条件表达式 ];then 成立执行的命令else 以上条件都没匹配到 执行的命令fi
if [ 你有钱 ];then 我就嫁给你elif [ 你有房 ];then 我也嫁给你elif [ 你有车 ];then 咱们先谈朋友elif [ 活好 ];then 运维学的好 倒贴也得嫁给你elif [ 如果你在老男孩学运维 ];then 潜力股 先谈恋爱else 拜拜fi
x
1.根据不同的操作系统版本 安装不同的YUM源【先写脚本的框架】 [root@shell day3]# cat yum.sh #更新前进行备份 backup_yum='mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup'os_version=`cat /etc/redhat-release |awk '{print $(NF-1)}'`if [ ${os_version%%.*} -eq 7 ];then $backup_yum wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repoelif [ ${os_version%%.*} -eq 6 ];then $backup_yum wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-6.repoelif [ ${os_version%%.*} -eq 8 ];then $backup_yum wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repofi
【完善脚本】[root@shell scripts]# cat if_first.sh #更新前备份[ -f /etc/init.d/functions ] && . /etc/init.d/functionsbackup_yum='mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak'os_version=`cat /etc/redhat-release|awk '{print $(NF-1)}'`ping -c1 -w1 www.baidu.com &>/dev/nullif [ $? -ne 0 ];thenecho "网络故障,请重启网络"systemctl restart networkping -c1 -w1 www.baidu.com &>/dev/null[ $? -ne 0 ] && echo "网络故障,请网路管理员检查网络....."fi
which wget &>/dev/nullif [ $? -ne 0 ];thenecho "未安装wget,正在安装wget......."yum install -y wget &>>/var/log/yum.log[ $? -eq 0 ] && echo "wget 安装成功,正在更新yum源......"fi
if [ ${os_version%%.*} -eq 7 ];then$backup_yumwget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo &>>/var/log/yum.logelif [ ${os_version%%.*} -eq 6 ];then$backup_yumwget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-6.repo &>>/var/log/yum.logelif [ ${os_version%%.*} -eq 8 ];then$backup_yumwget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo &>>/var/log/yum.logfi[ $? -eq 0 ] && action "yum源更新成功..." /bin/true || action "yum源更新失败,请重试或检查脚本..." /bin/false
2.使用if判断比较两个的数字大小
[root@shell scripts]# cat if_second.sh read -p "请输入两个整数,以空格作为分隔:" num1 num2if [[ ! $num1 =~ ^[0-9]+$ ]];thenecho "请输入整数"exitfiif [[ ! $num2 =~ ^[0-9]+$ ]];thenecho "请输入整数"exitfiecho $num1 $num2
判断num1数字如果是不是纯数字 或者num2不是纯数字 表达式都成立[root@shell day3]# cat diff.shread -p "请输入两个数字: " num1 num2if [[ ! $num1 =~ ^[0-9]+$ || ! $num2 =~ ^[0-9]+$ ]];then echo "请输入整数" exitfiecho $num1 $num2
或者使用expr判断read -p "请输入两个数字: " num1 num2expr $num1 + $num2 &>/dev/nullif [ $? -ne 0 ];then echo "请输入整数"fi
[root@shell scripts]# cat diff.sh read -p "请输入两个整数:" num1 num2if [[ ! $num1 =~ ^[0-9]+$ || ! $num2 =~ ^[0-9]+$ ]];then echo "请输入整数"exitfiif [ $num1 -gt $num2 ];then echo "$num1 > $num2"elif [ $num1 -lt $num2 ];then echo "$num1 < $num2"else echo "$num1 = $num2"fixxxxxxxxxxif案例:安装不同的PHP版本
[root@shell scripts]# cat if_php.sh cat <<EOF 1.PHP5.4 2.PHP5.5 3.PHP7.1 4.PHP7.2EOFread -p "请选择要安装的PHP版本(输入序号)" numif [ $num = 1 ];then echo "yum install PHP5.4......"elif [ $num = 2 ];then echo "yum install PHP5.5......"elif [ $num = 3 ];then echo "yum install PHP7.1......"else echo "yum install PHP7.2......"fi
二级菜单:[root@shell scripts]# cat if_menu.sh while truedocat <<EOF 1.MySQL 2.Nginx 3.PHPEOFread -p "请输入要安装的服务的序号或者名称:" numif [ $num = 1 -o $num = MySQL ];thencat <<EOF 1.MySQL5.5 2.MySQL5.6 3.MySQL5.7 4.MySQL8.0EOF read -p "请输入要安装的版本号对应的序号或者版本号:" num1 if [ $num1 = 1 -o $num1 = "MySQL5.5" ];then echo "yum install MySQL5.5......" elif [ $num1 = 2 -o $num1 = "MySQL5.6" ];then echo "yum isntall MySQL5.6......" elif [ $num1 = 3 -o $num1 = "MySQL5.7"];then echo "yum install MySQL5.7......" else echo "yum install MySQL8.0......" fielif [ $num = 2 -o $num = Nginx ];thencat <<EOF 1.Nginx1.20 2.Nginx1.21 3.Nginx.1.22EOF read -p"请输入要安装的版本号对应的序号或者版本号:" num2 if [ $num2 = 1 -o $num2 = "Nginx1.20" ];then echo "yum install Nginx1.20......" elif [ $num2 = 2 -o $num2 = "Nginx1.21" ];then echo "yum isntall Nginx1.21......" else echo "yum install Nginx.1.22......" fielif [ $num = 3 -o $num = "PHP" ];thencat <<EOF 1.PHP5.5 2.PHP7.1EOF read -p "请输入要安装的版本号对应的序号或者版本号:" num3 if [ $num3 = 1 -o $num3 = "PHP5.5" ];then echo "yum install PHP5.5......" else [ $num3 = 2 -o $num3 = "PHP7.1" ] echo "yum isntall PHP7.1......" fiexitfidone
xxxxxxxxxxfor 变量 in 值的列表 值: 数字 字符串 命令 序列 默认以空格来分隔do 执行的动作 命令的集合done
[root@shell scripts]# cat for_first.sh for i in {1..10}do echo $idone
x
1.统计for循环总共循环了多少次[root@shell scripts]# cat for_second.sh for num in {1..1000}do let i++doneecho $i
2.for循环,值为命令[root@shell scripts]# cat for_third.sh for i in `cat /etc/hosts`do echo $idone
3.检测主机是否在线[root@shell scripts]# cat for_ping.sh ip_prefix=10.0.0.read -p "请输入要检测的IP地址主机:" hostfor i in $hostdoping -c1 -w1 $ip_prefix$i &>/dev/nullif [ $? = 0 ];thenecho "$$ip_prefix$i在线"else echo "$ip_prefix$i不在线"fidone
wait 等待所有在后台运行的进程完毕后继续执行shell脚本[root@shell day3]# cat for.sh for i in `seq 254`do { ip=10.0.0.$i ping -c1 -W1 $ip &>/dev/null if [ $? -eq 0 ];then echo "$ip 在线" fi } &donewaitecho done................
5.批量创见用户[root@shell scripts]# cat for_user.sh read -p "请输入要创建用户的个数:" numread -p "请输入要创建用户的前缀:" prefixfor i in `seq $num`do user=${prefix}$i id $user &>/dev/nullif [ $? -ne 0 ];then useradd $user &>/dev/null [ $? -eq 0 ] && echo "用户 $user 创建成功"else echo "用户 $user 已存在"fidone
6.批量添加和删除用户[root@shell scripts]# cat for_user1.sh[root@shell scripts]# cat for_user1.sh [ -f /etc/init.d/functions ] && . /etc/init.d/functionswhile truedoread -p "请输入要对用户执行的操作(add|del):" userif [ $user = "add" ];thenread -p "请输入要添加的用户前缀:" prefix_addread -p "请输入要添加的用户个数:" numfor i in `seq $num`do username=${prefix_add}$i id $username &>/dev/null if [ $? -ne 0 ];then useradd $username && echo "123" |passwd $username --stdin [ $? -eq 0 ] && action "$username 创建成功" /bin/true else action "$username 已存在" /bin/false fi doneelif [ $user = "del" ];thenread -p "请输入要删除的用户前缀:" prefix_delread -p "请输入要删除的用户个数:" num1for i in `seq $num1`do username1=${prefix_del}$i id $username1 &>/dev/null if [ $? -ne 0 ];then action "$username1 不存在" /bin/false else userdel -r $username1 &>/dev/null [ $? -eq 0 ] && action "$username1 已删除" /bin/true fi doneficat <<EOF 继续请按 "1" 退出请按 "2"EOFread -p "请选择是否继续创建或删除用户:" num2[ $num2 = 1 ] && continue || exit
donexxxxxxxxxx语法结构:while [ 条件表达式 ] 条件表达式成立(为真)则执行 否则不执行do 命令done
死循环:[root@shell scripts]# cat while_first.sh while truedoecho hehesleep 1donexxxxxxxxxx1.从1加到100[root@shell scripts]# cat while_second.sh i=1while [ $i -le 100 ]do count=$((count+$i)) let i++doneecho $countxxxxxxxxxx语法结构:while read line # line变量名称 自定义do 执行的命令done<file
[root@shell scripts]# cat while_third.sh while read abcdoecho $abcdone</etc/hosts
[root@shell scripts]# cat while_user.sh [ -f /etc/init.d/functions ] && . /etc/init.d/functionswhile read linedouser=`echo $line|awk -F: '{print $1}'`pass=`echo $line|awk -F: '{print $2}'`useradd $user &>/dev/null[ $? = 0 ] && action "$user add succesed" /bin/true || action "$user add false" /bin/trueecho $pass | passwd $user --stdin &>/dev/null[ $? = 0 ] && action "$user password add succesed" /bin/true || action "$user password add false" /bin/truedone</server/scripts/user.txtxxxxxxxxxxexit #退出整个脚本break #跳出当前的循环continue #结束剩下的语句继续从头开始read #交互
#exit[root@shell scripts]# cat while_exit.sh while truedo echo joker exit echo linuxdone[root@shell scripts]# sh while_exit.sh joker
#break[root@shell scripts]# cat while_break.sh while truedo echo joker1 break echo joker2doneecho joker3[root@shell scripts]# sh while_break.sh joker1joker3
#break等级跳[root@shell day3]# cat exit.sh while truedo echo "第一层" while true do echo 第二层 sleep 1 while true do echo 第三层 sleep 1 break 3 echo joker....... done donedoneecho hehe...........
#continue[root@shell scripts]# cat while_continue.sh while truedo echo test....... continue echo joker.......doneecho hehe...........
xxxxxxxxxxcase 变量 in 变量 直接传参 赋值传参 匹配模式1) 执行的命令集合 ;; 匹配模式2) 执行命令集合 ;; 匹配模式3) 执行命令集合 ;; *) 无匹配后序列 执行命令集合 esacxxxxxxxxxx1.简单案例[root@shell case]# cat case_first.sh case $1 in shell)echo shell;; mysql)echo mysql;; nginx)echo nginx;; php)echo php;; *)echo "啥都不是"esac
2.使用case写一个菜单 显示系统的登录 负载 磁盘 内存等信息[root@shell case]# cat case_second.sh cat <<EOF 1.查看内存 2.查看负载 3.查看磁盘 4.查看登录信息 5.退出EOFwhile truedoread -p "请输入要查看的信息编号:" numcase $num in 1) free -h;; 2) uptime;; 3) df -h;; 4) last;; 5) exit;; *) echo "Usage: $0 [1|2|3|4|5]"esacdone
3.启动Nginx的脚本[root@shell case]# cat case_nginx.sh [root@shell case]# cat case_nginx.sh [ -f /etc/init.d/functions ] && . /etc/init.d/functionscat <<EOF 1.启动Nginx 2.停止Nginx 3.重启Nginx 4.重载Nginx 5.查看PID和端口号(PID:PORT) 输入其他字符退出EOFread -p "请输入要执行的操作:" numcase $num in 1) /sbin/nginx &>/dev/null [ $? -eq 0 ] && action "Nginx启动成功" /bin/true || action "Nginx启动失败,请检查......" /bin/false;; 2) /sbin/nginx -s stop &>/dev/null [ $? -eq 0 ] && action "Nginx停止成功" /bin/true || action "Nginx停止失败,请检查......" /bin/false;; 3) /sbin/nginx -s stop &>/dev/null && sleep 2 && /sbin/nginx &>/dev/null [ $? -eq 0 ] && action "Nginx重启成功" /bin/true || action "Nginx重启失败,请检查......" /bin/false;; 4) /sbin/nginx -s reload &>/dev/null [ $? -eq 0 ] && action "Nginx重载成功" /bin/true || action "Nginx重载失败,请检查......" /bin/false;; 5) PID=`netstat -tunlp|grep nginx|grep '\btcp\b'|awk '{print $(NF-1)}'` PORT=`netstat -tunlp|grep nginx|grep '\btcp\b'|awk '{print $4}'` echo $PID$PORT;; *) exitesac