shell编程
1.什么情况下使用Shell
1)安装CentOS系统 自动化安装操作系统(kickstart cobbler) 底层shell
2)网络IP地址
3)初始化操作系统(ntp时间同步,更改默认YUM源,SSH端口,SSH远程连接禁止DNS解析,禁止root登录,关闭seilnux,防火墙优化(c6 iptables c7 firewald) 80 443 22 8080 10050 ,
安装常用的软件命令 lrzsz wget net-tools... 加大文件描述符 中文字符集 内核参数优化 别名 重要的文件加上i a....等)
当前centos7的系统 如何更换为iptables
1.关闭firewalld 永久禁止启动
systemctl stop firewalld
systemctl disable firewalld
2.安装iptables-services
需要放行的端口?
以上都是shell脚本实现
4)安装服务 Nginx PHP MySQL Redis MHA Rsync NFS mongo KVM Docker Zabbix ELK.....
shell脚本自动安装不同版本的服务
5)配置文件 shell
6)启动服务(系统默认的就是shell脚本) python产品
python3.5 conut.py --redis 10.0.0.10 --port 3306 --传参 --- 写入shell脚本
conut_start.sh conut_stop.sh
ps axu|grep php|grep -v grep|awk '{print $2}'|xargs kill -9
7)监控 zabbix 常用 服务器的各种状态 进程 cacti 监控流量 nagios 交换机 路由器
shell脚本统计需要的数据进行监控
8)日志统计 日志切割 日志收集 +800M vim 或者命令 (排除大数据公司) ELK
三剑客等命令+shell脚本+定时任务
9)命令+shell脚本+定时任务 数据备份
2.学习shell脚本需要用到的知识
1)远程连接工具 Xshll CRT(作业)
2)lINUX的常用命令 熟练掌握
3)三剑客命令熟练
4)vim编辑器熟练
3.如何学好shell编程
环境变量 条件表达式 if判断 for循环 while循环 case语句 数组 函数
先学好shell基础
读懂shell 修改shell脚本 自己编写shell脚本
不可拿来主义
有一本教材 shell编程
4.shell入门
1)什么是shell 壳
命令解释器 用户输入命令 解释器负责解释给内核 处理后的结果 反馈用户 称为解释
交互式shell 用户输入命令 解释器解释把处理后的结果反馈给用户的过程称为 交互式
非交互shell shell执行文本中的命令 当执行到文件的末尾 bash退出
父shell 不能继承子shell变量 子shell可继承父shell变量
2)什么是shell脚本
把可执行命令堆积到一个文本中则称为shell脚本(条件表达式 for循环 if判断等等语句)
5.shell脚本的书写规范
- 目录统一
- shell脚本的结尾要以.sh结尾
- 脚本的开头需要有解释器 /bin/bash /bin/sh
- 脚本中需要有作者信息 #Author lzy date version 做什么的
- 脚本每行 或者 一个语句 给一个注释
- shell中的文字尽量使用英文 py都是中文
- 成对的符号一次性书写完毕 语句
6.第一个shell脚本
hello world!
执行脚本的三种方式
1)bash test.sh
[root@web01 scripts]# bash test.sh
Hello World!
2)全路径执行
[root@web01 scripts]# chmod +x test.sh
[root@web01 scripts]# /server/scripts/test.sh
Hello World!
3). 或者source执行
[root@web01 scripts]# . test.sh
Hello World!
[root@web01 scripts]# source test.sh
Hello World!
什么区别?
1 2 在子shell中执行
. source 父进程下执行
7. 环境变量
1)什么是环境变量?
右边一堆内容,用一个名字来代替称为环境变量
name="I am lizhenya"
如何查看环境变量? 名称的前面加上$
echo $name
如何查看系统定义好的环境变量
env set
如何取消环境变量?
unset name
环境变量(全局变量) 普通变量(局部变量)
按照生存周期划分
永久性 修改配置文件 /etc/profile
临时性 使用export 变量名称 声明即可
不加export 只对当前的shell生效
加export 对当前登录窗口所有的shell生效
环境的相关文件
- /etc/profile 开机或者新连接的窗口执行一次
- .bashrc
- .bash_profile
- /etc/bashrc
2)如何定义环境变量
变量名=变量值
环境变量名称的定义 字符 下划线 数字的组合 尽量以字母开头(禁止使用数字开头) 等号两端不允许有空格 见名知其意
书写方式
- OLDBOY_AGE=18 系统中变量的定义格式
- oldboy_age=18
- oldboy_Age=18 小驼峰语法
- Oldboy_Age=18 大驼峰语法
变量值的定义方式
数字的定义
oldboy_age=18 连续的数字
字符串的定义
name="oldboy" 使用双引号 不知道加什么符号 就加双引号 解析变量
name='oldboy' 所见即所得 吃什么吐什么
命令的定义
time=`date` 反引号 里面必须跟可执行命令
time=$(date) $()
[root@web01 scripts]# name=oldboy
[root@web01 scripts]# echo "$oldboyisok"
[root@web01 scripts]# echo "${oldboy}isok"
isok
[root@web01 scripts]# echo "${name}isok"
oldboyisok
[root@web01 scripts]# echo '${name}isok'
${name}isok
8. 重要的特殊位置变量
$0 脚本的名称,如果全路径执行脚本,则脚本名称也带全路径 basename 获取脚本的名称 重要
案例: 给用户提示如何使用此脚本
echo $"Usage: $0 {start|stop|status|restart|force-reload}"
$n 脚本的第n个参数 $0被脚本名称占用 从$1开始 $9以后 需要加{}
$# 代表了脚本的传参的总个数 重要
案例:
[ $# -ne 2 ] && echo "你请输入两个参数" && exit
$* 脚本的所有的传参的参数 如果不加双引号则和$@相同 加上双引号则把所有参数视为一个整体
$@ 脚本的所有的传参的参数 如果不加双引号则和$*相同加上双引号则把所有参数视为独立的参数
$* 和$@ 正常情况下一样 循环体内不同
$? 获取上一条命令的结果 0为成功 非0 失败 重要
$$ 获取脚本的PID
案例
服务器运行大量的名称相同的脚本
echo $$ > /tmp/count.pid
$! 上一个在后台运行脚本的PID 调试使用
$_ 获取脚本的最后一个参数 相当于ESC .
9. 传参的三种方式
1)直接传参
2)赋值传参
3)read传参
#第一种传参方式
echo $1 $2
#第二种传参方式
name=$1
age=$2
echo $name $age
read -p "请输入名字和年龄" name1 age1
echo $name1 $age1
案例:
使用read 传参的方式 更改系统的主机名称和IP地址的最后一位 192.168.12.X
#!/bin/sh
sdir="/etc/sysconfig/network-scripts/ifcfg-eth0"
sip=`cat /etc/sysconfig/network-scripts/ifcfg-eth0|awk -F. '/IPADDR/{print $NF}'|cut -c1`
read -p "请输入主机名称: " name
hostnamectl set-hostname $name
read -p "请输入IP地址的最后一位: " ip
sed -i "s#$sip#$ip#g" $sdir
案例:
[root@web01 scripts]# sh ping.sh www.baidu.com
ping www.baidu.com is ok
[root@web01 scripts]# sh ping.sh www.xxxxx.com
ping www.xxxxx.com is error
[root@web01 scripts]# cat ping.sh
#!/bin/sh
read -p "请输入一个网址: " url
ping -c 1 -W 1 $url >/dev/null 2>&1
[ $? -eq 0 ] && echo "ping $url is ok" || echo "ping $url is error"
10. 变量的字符串知识
10.1 统计变量的长度 重点
[root@web01 scripts]# name="I am lizhenya"
[root@web01 scripts]# echo $name
I am lizhenya
[root@web01 scripts]# echo "I am lizhenya"
I am lizhenya
[root@web01 scripts]# echo "I am lizhenya"|wc -L
13
[root@web01 scripts]# echo $name|wc -L
13
[root@web01 scripts]# echo ${#name}
13
10.2 变量的切片
[root@web01 scripts]# echo ${name:0:1}
I
[root@web01 scripts]# echo ${name:2:2}
am
[root@web01 scripts]# echo ${name:0:1}
I
[root@web01 scripts]# echo ${name:1}
am lizhenya
[root@web01 scripts]# echo ${name:2:5}
am li
10.3 取字符串长度
I am lizhenya teacher I am 18
方法1
echo I am lizhenya teacher I am 18|wc -L
方法2
name="I am lizhenya teacher I am 18"
echo ${#name}
方法3
[root@web01 scripts]# expr length "$name"
29
方法4
[root@web01 scripts]# echo $name|awk '{print length}'
29
面试题:取字符串长度小于3的
方法1
for循环方式
[root@web01 scripts]# cat for.sh
#!/bin/sh
for i in I am lizhenya teacher I am 18
do
[ ${#i} -lt 3 ] && echo $i
done
方法2
[root@web01 scripts]# echo I am lizhenya teacher I am 18|xargs -n1|awk '{if(length<3)print}'
I
am
I
am
18
方法3
[root@web01 scripts]# echo I am lizhenya teacher I am 18|awk '{for(i=1;i<=NF;i++)if(length($i)<3)print $i}'
11.变量的删除和替换
11.1 从前往后删除变量内容
[root@web01 scripts]# echo $url
www.sina.com.cn
[root@web01 scripts]# echo ${url#*.}
sina.com.cn
[root@web01 scripts]# echo ${url#*.*.}
com.cn
[root@web01 scripts]# echo ${url##*.}
cn
11.2 从后往前删除变量内容
[root@web01 scripts]# echo $url
www.sina.com.cn
[root@web01 scripts]# echo ${url%.*}
www.sina.com
[root@web01 scripts]# echo ${url%%.*}
www
11.3 变量的替换
[root@web01 scripts]# echo $url
www.sina.com.cn
[root@web01 scripts]# echo ${url/w/a}
aww.sina.com.cn
[root@web01 scripts]# echo ${url/w/aa}
aaww.sina.com.cn
[root@web01 scripts]# echo ${url/w/a}
aww.sina.com.cn
[root@web01 scripts]# echo ${url//w/a}
aaa.sina.com.cn
[root@web01 scripts]# echo ${url/sina/baidu}
www.baidu.com.cn
12. 数值的运算
12.1 expr 整数运算
[root@web01 scripts]# expr 1+1
1+1
[root@web01 scripts]# expr oldboy
oldboy
[root@web01 scripts]# expr 1 + 1
2
[root@web01 scripts]# expr 1 - 1
0
[root@web01 scripts]# expr 1 * 11
expr: 语法错误
[root@web01 scripts]# expr 1 \* 11
11
[root@web01 scripts]# expr 110 / 11
10
[root@web01 scripts]# expr 1 + 1.5
expr: 非整数参数
案例: 判断传参输入是否为整数
[root@web01 scripts]# num1=10
[root@web01 scripts]# num2=11q
[root@web01 scripts]# expr $num1 + 1 >/dev/null 2>&1
[root@web01 scripts]# [ $? -ne 0 ] && echo "你输入的是非整数" || echo "你输入的是整数"
你输入的是整数
[root@web01 scripts]# expr $num2 + 1 >/dev/null 2>&1
[root@web01 scripts]# [ $? -ne 0 ] && echo "你输入的是非整数" || echo "你输入的是整数"
你输入的是非整数
11.2 $(()) 整数运算 运算效率最高
[root@web01 scripts]# echo $((10+10))
20
[root@web01 scripts]# echo $((10-10))
0
[root@web01 scripts]# echo $((10*10))
100
[root@web01 scripts]# echo $((10/10))
1
11.3 $[] 整数运算
[root@web01 scripts]# echo $[10+10]
20
[root@web01 scripts]# echo $[10-10]
0
[root@web01 scripts]# echo $[10*10]
100
[root@web01 scripts]# echo $[10/10]
1
[root@web01 scripts]# echo $[10-10.5]
-bash: 10-10.5: 语法错误: 无效的算术运算符 (错误符号是 ".5")
11.4 let 重点
[root@web01 scripts]# let sum=10+10
[root@web01 scripts]# echo $sum
20
[root@web01 scripts]# num1=100
[root@web01 scripts]# num2=50
[root@web01 scripts]# let sum=$num1+$num2
[root@web01 scripts]# echo $sum
150
[root@web01 scripts]# let sum=$num1-$num2
[root@web01 scripts]# echo $sum
50
[root@web01 scripts]# let sum=$num1*$num2
[root@web01 scripts]# echo $sum
5000
[root@web01 scripts]# let sum=$num1/$num2
[root@web01 scripts]# echo $sum
2
11.5 i++ 变量自增
[root@web01 scripts]# let i=i+1
[root@web01 scripts]# echo $i
1
[root@web01 scripts]# let i++
[root@web01 scripts]# echo $i
2
[root@web01 scripts]# let i++
[root@web01 scripts]# let i++
[root@web01 scripts]# let i++
[root@web01 scripts]# let i++
[root@web01 scripts]# echo $i
6
[root@web01 scripts]# sh for.sh
7
[root@web01 scripts]# sh -x for.sh
+ for i in I am lizhenya teacher I am 18
+ let a++
+ for i in I am lizhenya teacher I am 18
+ let a++
+ for i in I am lizhenya teacher I am 18
+ let a++
+ for i in I am lizhenya teacher I am 18
+ let a++
+ for i in I am lizhenya teacher I am 18
+ let a++
+ for i in I am lizhenya teacher I am 18
+ let a++
+ for i in I am lizhenya teacher I am 18
+ let a++
+ echo 7
7
[root@web01 scripts]# let c++
[root@web01 scripts]# let c++
[root@web01 scripts]# let c++
[root@web01 scripts]# let c++
[root@web01 scripts]# let c++
[root@web01 scripts]# let c++
[root@web01 scripts]# let c++
[root@web01 scripts]# echo $c
7
11.6 bc awk python (bc需要安装)
bc
[root@web01 scripts]# echo 10+10|bc
20
[root@web01 scripts]# echo 10-10|bc
0
[root@web01 scripts]# echo 10*10|bc
100
[root@web01 scripts]# echo 10/10|bc
1
[root@web01 scripts]# echo 10+10.5|bc
20.5
awk
[root@web01 scripts]# awk 'BEGIN{print 10+10}'
20
[root@web01 scripts]# awk 'BEGIN{print 10-10}'
0
[root@web01 scripts]# awk 'BEGIN{print 10/10.5}'
0.952381
[root@web01 scripts]# awk 'BEGIN{print 10*10.5}'
105
[root@web01 scripts]# awk 'BEGIN{print 10^10.5}'
3.16228e+10
[root@web01 scripts]# awk 'BEGIN{print 10^10}'
10000000000
[root@web01 scripts]# echo 100 200
100 200
[root@web01 scripts]# echo 100 200|awk '{print $1+$2}'
300
python
[root@web01 scripts]# python
Python 2.7.5 (default, Oct 30 2018, 23:45:53)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 10+10
20
>>> 10-10
0
>>> 10*10
100
>>> 10/10
1
>>> 10/10.5
0.9523809523809523
>>>
小结 expr $(()) $[] let bc awk python
案例1:
ps axu 中的VSZ 列 所有的数相加 得出结果
[root@web01 scripts]# ps axuf|awk '{print $5}'|grep -v VSZ|tr "\n" "+"|sed -r 's#(.*)#\10\n#g'|bc
12778952
案例2:
做一个加减乘除的计算器
例如:
请输入第一个数字 10
请输入第二个数字 20
显示的结果 10+20=30
[root@web01 scripts]# cat count.sh
#!/bin/sh
read -p "请输入第一个数字: " num1
read -p "请输入第二个数字: " num2
echo "$num1+$num2=$[$num1+$num2]"
echo "$num1-$num2=$[$num1-$num2]"
echo "$num1*$num2=$[$num1*$num2]"
echo "$num1/$num2=$[$num1/$num2]"
13 条件表达式
[]======test []常用
[ -f file ] 文件是否存在 且为普通文件 重点
[ -e file ] 文件存在则为真
[ -d file ] 目录存在则为真 重点
[ -x file ] 文件有执行权限则为真
[ -w file ] 文件可写则为真
[ -r file ] 文件可读则为真
[root@web01 scripts]# [ -f /etc/hosts ] && echo 为真 || echo 为假
为真
[root@web01 scripts]# [ -f /etc/hostsss ] && echo 为真 || echo 为假
为假
[root@web01 scripts]# [ -d /etc/hosts ] && echo 为真 || echo 为假
为假
[root@web01 scripts]# [ ! -d /etc/hosts ] && echo 为真 || echo 为假
为真
[root@web01 scripts]# [ -e /etc/hosts ] && echo 为真 || echo 为假
为真
[root@web01 scripts]# [ -e /etc/ ] && echo 为真 || echo 为假
为真
[root@web01 scripts]# [ -r /etc/ ] && echo 为真 || echo 为假
为真
[root@web01 scripts]# [ -w /etc/ ] && echo 为真 || echo 为假
为真
[root@web01 scripts]# [ -x /etc/ ] && echo 为真 || echo 为假
为真
[root@web01 scripts]# [ -x /etc/hosts ] && echo 为真 || echo 为假
[root@web01 scripts]# [ -x /etc/hosts ] && echo 为真 || echo 为假
为假
[root@web01 scripts]# [ -x /etc/hosts ] && echo 为真 || echo 为假
为假
[root@web01 scripts]# ll
总用量 24
-rw-r--r-- 1 root root 230 8月 1 16:07 count.sh
-rw-r--r-- 1 root root 74 8月 1 15:33 for.sh
-rw-r--r-- 1 root root 297 7月 31 16:59 ip.sh
-rw-r--r-- 1 root root 14 8月 1 15:06 oldboy.sh
-rw-r--r-- 1 root root 152 7月 31 17:12 ping.sh
-rwxr-xr-x 1 root root 225 7月 31 16:34 test.sh
[root@web01 scripts]# [ -x test.sh ] && echo 为真 || echo 为假
为真
-f 判断文件是否存在
案例:
[root@web01 scripts]# [ -f /etc/init.d/functions ] && . /etc/init.d/functions
[root@web01 scripts]# action "hehehe is" /bin/true
hehehe is [ 确定 ]
[root@web01 scripts]# action "hehehe is" /bin/false
hehehe is [失败]
函数库使用
[root@web01 scripts]# cat ping.sh
#!/bin/sh
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
read -p "请输入一个网址: " url
ping -c 1 -W 1 $url >/dev/null 2>&1
[ $? -eq 0 ] && action "ping $url is" /bin/true || action "ping $url is" /bin/false
-d 判断是否为目录 目录是否存在
[root@web01 scripts]# [ -d /alex ] || mkdir /alex
[root@web01 scripts]# test -f /etc/hosts && echo ok || echo error
ok
[root@web01 scripts]# test -d /etc/hosts && echo ok || echo error
error
[root@web01 scripts]# test -d /etc/ && echo ok || echo error
ok
14. 数值的比较
[ 数值1 比较符 数值2 ] [[]] = != >= < <=
-eq 相等
-ne 不等于
-gt 大于
-ge 大于等于
-lt 小于
-le 小于等于
[root@web01 scripts]# [ 10 -eq 10 ] && echo ok || echo error
ok
[root@web01 scripts]# [ 10 -gt 10 ] && echo ok || echo error
error
[root@web01 scripts]# [ 10 -ge 10 ] && echo ok || echo error
ok
[root@web01 scripts]# [ 10 -ne 10 ] && echo ok || echo error
error
[root@web01 scripts]# [ 10 -lt 10 ] && echo ok || echo error
error
[root@web01 scripts]# [ 10 -le 10 ] && echo ok || echo error
ok
案例1:
统计当前磁盘的使用率 如果大于5% 则把内容写入到以日期为名称的文本中 2019-08-01.txt
如果小了 则把当前的使用率 写入 2019-08-01.txt
1.如何取出当前的使用率
df -h|awk 'NR==2{print $(NF-1)}'
df -h|grep /$|awk '{print $(NF-1)}'
2.条件表达式 整数的比较
3.输出结果到文本
4.调试
[root@shell scripts]# cat usedisk.sh
#!/bin/sh
time=`date +%F`
usedisk=`df -h|grep /$|awk '{print $(NF-1)}'`
[ ${usedisk%\%} -gt 5 ] && echo "当前使用率不正常 $usedisk" >> ${time}.txt || echo "当前使用率正常 $usedisk" >> ${time}.txt
[root@web01 scripts]# [ `df -h|grep /$|awk -F "[ %]+" '{print $(NF-1)}'` -gt 5 ] && echo error || echo ok
error
[root@web01 scripts]# [ `df -h|grep /$|awk -F "[ %]+" '{print $(NF-1)}'` -gt 80 ] && echo error || echo ok
ok
案例2:
统计系统内存的使用率 如果大于10则 echo 使用率到 以时间命名的文件中
1.如何取出当前的使用率
百分比=====使用的除总数乘100
2.条件表达式 整数的比较
3.输出结果到文本
4.调试
[root@web01 scripts]# free|awk 'NR==2{print $3/$2*100}'
19.0124
[root@web01 scripts]# free=`free|awk 'NR==2{print $3/$2*100}'`
[root@web01 scripts]# [ ${free%.*} -gt 10 ] && echo error || echo ok
error
[root@web01 scripts]# [ ${free%.*} -gt 80 ] && echo error || echo ok
ok
案例3:
统计系统的负载 负载超过2 则发送到文件中 否则提示正常
1.如何查看统计负载
2.取值做比较
3.输出结果
4.调试
案例4:
使用脚本统计 主机名称 网卡IP地址 虚拟平台 系统版本号 外网IP地址 磁盘使用率
例如
sh os.sh
当前系统的主机名称是 web01
当前系统的IP地址是 10.0.0.7
15.字符串比对
15.1 字符串必须使用双引号
[ "name" = "name" ]
[ "name" != "name" ]
[root@web ~]# [ "$USER" = "root" ]
[root@web ~]# echo $USER
root
[root@web ~]# [ "$USER" = "root" ]
[root@web ~]# echo $?
0
[root@web ~]# [ "$USER" = "alex" ]
[root@web ~]# echo $?
1
[root@web ~]# [ "$USER" != "alex" ]
[root@web ~]# echo $?
0
15.2 -z -n
[root@web ~]# name=""
[root@web ~]# [ -z $name ]
[root@web ~]# echo $?
0
[root@web ~]# [ ! -z $name ]
[root@web ~]# echo $?
1
[root@web ~]# name="alex"
[root@web ~]# [ -z $name ]
[root@web ~]# echo $?
1
[root@web ~]# [ -n $name ]
[root@web ~]# echo $?
0
-z 案例:
read -p "请输入名字" name1
[ -z $name1 ] && echo "请输入姓名否则不继续执行" && exit
read -p "请输入年龄" age1
echo $name1 $age1
15.3 正则比对
[[]]
[root@web01 scripts]# [ "$USER" = "root" ]
[root@web01 scripts]# echo $?
0
[root@web01 scripts]# [[ "$USER" =~ ^r ]]
[root@web01 scripts]# echo $?
0
[root@web01 scripts]# [[ "$USER" =~ t$ ]]
[root@web01 scripts]# echo $?
0
[root@web01 scripts]# [[ ! "$USER" =~ t$ ]]
[root@web01 scripts]# echo $?
1
15.4 判读传参的参数是否为整数
方法1
[root@web01 scripts]# age=188
[root@web01 scripts]#
[root@web01 scripts]#
[root@web01 scripts]# [[ "$age" =~ ^[0-9]+$ ]]
[root@web01 scripts]# echo $?
0
[root@web01 scripts]# age=188q
[root@web01 scripts]# [[ "$age" =~ ^[0-9]+$ ]] && echo $?
[root@web01 scripts]# [[ "$age" =~ ^[0-9]+$ ]] || echo $?
1
[root@web01 scripts]# age=18.8
[root@web01 scripts]# [[ "$age" =~ ^[0-9]+$ ]]
[root@web01 scripts]# echo $?
1
方法2
expr $1 + 0 >/dev/null 2>&1
[ $? -ne 0 ] && exit
16.多整数比对
-a and
-o or
[ 10 -eq 10 -a 100 -ne 100 ]
[root@web01 scripts]# [ 10 -eq 10 -a 100 -ne 100 ]
[root@web01 scripts]# echo $?
1
[root@web01 scripts]# [ 10 -eq 10 -a 100 -eq 100 ]
[root@web01 scripts]# echo $?
0
[root@web01 scripts]# [ 10 -eq 10 -o 100 -ne 100 ]
[root@web01 scripts]# echo $?
0
[root@web01 scripts]# [[ 10 -eq 10 && 100 -ne 100 ]]
[root@web01 scripts]# [[ 10 -eq 10 -a 100 -ne 100 ]]
-bash: 条件表达式中有语法错误
-bash: `-a' 附近有语法错误
[root@web01 scripts]# [[ 10 -eq 10 && 100 -ne 100 ]]
[root@web01 scripts]# echo $?
1
[root@web01 scripts]# [[ 10 -eq 10 || 100 -ne 100 ]]
[root@web01 scripts]# echo $?
0
案例:
传入两个数字 比对两个数字的大小
例如
sh count.sh 10 10 要求判读是否传入两个参数 要求数字加判读是否为整数(禁止if)
10=10
#!/bin/sh
[ $# -ne 2 ] && echo "please input two number" && exit
[[ ! $1 =~ ^[0-9]+$ ]] && echo "请输入整数" && exit 50
[[ ! $2 =~ ^[0-9]+$ ]] && echo "请输入整数" && exit 100
[ $1 -eq $2 ] && echo "$1=$2"
[ $1 -gt $2 ] && echo "$1>$2"
[ $1 -lt $2 ] && echo "$1<$2"
案例:
批量创建用户 批量创建10个用户 oldboy1 oldboy2 oldboy3...oldboy10
要求密码统一设置为123456
1.输入用户的前缀 oldboy
判断如果为空 则退出
2.输入需要创建用户的个数 10
判断是否为整数
[root@web01 scripts]# cat useradd.sh
#!/bin/sh
#read -p "please input prefix: " name
#read -p "创建的个数: " num
for i in {1..10}
do
echo oldboy$i
done
[root@web01 scripts]# cat useradd.sh
#!/bin/sh
read -p "please input prefix: " name
read -p "创建的个数: " num
for i in `seq $num`
do
useradd $name$i >/dev/null 2>&1
echo 123456|passwd --stdin $name$i &>/dev/null
[ $? -eq 0 ] && echo "$name$i create is ok"
done
案例:
判断当前10.0.0.0/24网络中 有哪些IP地址在线 ping通则在线
[root@web01 scripts]# cat ping.sh
#!/bin/sh
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
for i in `seq 254`
do
{ IP=10.0.0.$i
ping -c 1 -W 1 $IP >/dev/null 2>&1
[ $? -eq 0 ] && action "ping $IP is" /bin/true
} &
done
10.0.0.1-254都通 网卡可配置多个IP
网络相关
ip addr add 10.0.0.3/24 dev eth0 临时生效 重启失效
面试题 配置一条默认网关
route add default gw 10.0.0.254
删除网关
route add default gw 10.0.0.254
其他方法 静态路由方式
ip route add 0/0 via 10.0.0.254
策略路由
服务器使用vpn常用 网关被替换成vpn
pptpstup 拨号命令
查看网关
route -n
开机启动配置文件(/etc/rc.local) +x 权限 rc.d/rc.local (禁止使用alias和变量)
17.if判断
单分支
if [你有房];then [ -f file ] && echo ok
if [你有房]
then
我就嫁给你
fi
双分支
if [ 你有房 ] [ -f file ] && echo ok || echo error
then
我就嫁给你
else
拜拜
fi
多分支
if [ 你有房 ]
then
我就嫁给你
elif [ 你有钱 ]
then
我也嫁给你
elif [ 你爸是李刚 ]
then
我也嫁给你
elif [ 活好!运维技术好 ]
then
我倒贴也嫁给你
elif [ 你在老男孩学运维 ]
then
我考虑考虑
else
拜拜
fi
案例: 输入两个数字 是否为整数 使用if方式
#!/bin/bash
read -p "请输入第一个数字:" num1
read -p "请输入第二个数字:" num2
if [ -z $num1 ]
then
echo "您输入的第一个数字为空"&& exit
elif [ -z $num2 ]
then
echo "您输入的第二个数字为空"&& exit
elif [[ "$num1" =~ ^[0-9]+$ && "$num2" =~ ^[0-9]+$ ]]
then
if [ $num1 -lt $num2 ]
then
echo "$num1<$num2"
elif [ $num1 -gt $num2 ]
then
echo "$num1>$num2"
else
echo "$num1=$num2"
fi
else
echo "您输入了错误的值!"&& exit
fi
案例: 根据操作系统不同的版本安装不同的源
1. 如何取出版本号
2. 如何做版本号的比对
3. 比对完成执行相对应的安装源
[root@web scripts]# cat yum.sh
#!/bin/sh
ve=`cat /etc/redhat-release |awk '{print $(NF-1)}'`
#centos6.x使用以上命令获取不到版本号
if [ ${ve%%.*} -eq 7 ]
then
#判断网络是否通畅ping 如果不通 则重启systemctl restart network 通继续执行
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
#测试wget是否已安装 无安装先安装wget
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
elif [ ${ve%%.*} -eq 6 ]
then
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
fi
案例:猜数字 笔试题
生成一个随机数1-100之间
RANDOM 随机数的范围 0-32767
取余
echo $((RANDOM%100+1))
用户输入一个数字
判断用户输入的数字如果相等则退出提示猜对了 大了 提示比随机数大 小了 提示 比随机数小
[root@web scripts]# cat ran.sh
#!/bin/sh
ran=`echo $((RANDOM%100+1))`
while true
do
let i++
read -p "请输入一个数字[1-100]: " num
if [ $num -gt $ran ];then
echo "你输入的数字大了"
elif [ $num -lt $ran ];then
echo "你输入的数字小了"
else
echo "恭喜你猜对了 总共猜了 $i 次"
exit
fi
done
案例: 反向破解RANDOM 字符串比较
[root@web scripts]# echo $RANDOM
6500
[root@web scripts]# echo $RANDOM|md5sum|cut -c1-8
98f23d45
[root@web scripts]# echo 1|md5sum
b026324c6904b2a9cb4b88d6d61c81d1 -
[root@web scripts]# echo 1|md5sum |cut -c1-8
b026324c
[root@web scripts]# echo $RANDOM|md5sum|cut -c1-8
abafad14
[root@web scripts]# echo $RANDOM|md5sum|cut -c1-8
312c404c
[root@web scripts]# echo $RANDOM|md5sum|cut -c1-8
02ab2b9b
[root@web scripts]# echo $RANDOM|md5sum|cut -c1-8
ab1e7ee2
[root@web scripts]# echo 1|md5sum |cut -c1-8
b026324c
18. case 流程控制语句
case 变量名4 in
模式匹配1)
命令的集合
;;
模式匹配2)
命令的集合
;;
模式匹配3)
命令的集合
;;
*) *的下一行不需要有;;
echo USAGE[$0 1|2|3]
esac
[root@web scripts]# cat case.sh
#!/bin/sh
case $1 in
Linux)
echo linux......
;;
Shell)
echo Shell......
;;
MySQL)
echo MySQL.....
;;
*)
echo "USAGE $0 [Linux|Shell|MySQL]"
esac
case 批量删除用户
[root@web scripts]# cat casedel.sh
#!/bin/sh
read -p "请输入用户名前缀: " prefix
read -p "请输入要删除几个用户: " num
for i in `seq $num`
do
echo $prefix$i
done
read -p "你确定要删除以上用户吗?[y|yes|YES|n|N|no]" ready
for n in `seq $num`
do
name=$prefix$n
case $ready in
y|yes|YES)
id $name &>/dev/null
if [ $? -eq 0 ];then
userdel -r $name
[ $? -eq 0 ] && echo "$name del is ok"
else
echo "id: $name: no such user"
fi
;;
n|N|no)
echo "不删除我玩啥呢?" && exit
;;
*)
echo "USAGE $0 [y|yes|YES|n|N|no]"
esac
done
菜单
[root@web scripts]# cat menu.sh
#!/bin/sh
echo -e "\t\t#########################"
echo -e "\t\t#\t1.系统负载\t#"
echo -e "\t\t#\t2.磁盘使用率\t#"
echo -e "\t\t#\t3.内存使用率\t#"
echo -e "\t\t#\t4.当前登录用户\t#"
echo -e "\t\t#\t5.当前eth0的IP\t#"
echo -e "\t\t#\t6.显示菜单\t#"
echo -e "\t\t#########################"
menu(){
cat<<EOF
1.u 系统负载
2.d 磁盘使用率
3.f 内存使用率
4.w 当前登录用户
5.ip 当前eth0的IP
6.h 显示帮助(菜单)
7.q 退出
EOF
}
menu
while true
do
read -p "请输入你想要查看的系统信息的编号: " num
case $num in
1|u)
uptime
;;
2|d)
df -h
;;
3|f)
free -h
;;
4|w)
w
;;
5|ip)
ip add
;;
6|h)
clear
menu
;;
7|q)
exit
;;
*)
menu
esac
done
案例:
Nginx 启动脚本 jumpserver跳板机
/usr/sbin/nginx 使用命令进行启动后 systemctl 无法管理命令行启动的Nginx
/usr/sbin/nginx 启动
/usr/sbin/nginx -s stop 停止
/usr/sbin/nginx -s reload 重新加载\
/usr/sbin/nginx -s stop 重启
sleep 2
/usr/sbin/nginx
自取状态 PID 端口 状态
[root@web scripts]# sh nginxstart.sh status
当前Nginx的PID:116528
[root@web scripts]# cat nginxstart.sh
#!/bin/sh
. /etc/init.d/functions
en=$1
fun(){
[ $? -eq 0 ] && action "Nginx $en is" /bin/true || action "Nginx $en is" /bin/false
}
case $1 in
start)
/usr/sbin/nginx
fun
;;
stop)
/usr/sbin/nginx -s stop
fun
;;
reload)
/usr/sbin/nginx -s reload
fun
;;
restart)
/usr/sbin/nginx -s stop
sleep 2
/usr/sbin/nginx
fun
;;
status)
echo "当前Nginx的PID:`ps axu|grep nginx|grep master|awk '{print $2}'`"
;;
*)
echo "USAGE $0 [start|stop|reload|restart|status]"
esac
jumpserver 跳板机
WEB01=10.0.0.7
WEB02=10.0.0.8
MySQL=10.0.0.51
NFS=10.0.0.31
菜单
1. WEB01=10.0.0.7
2. WEB02=10.0.0.8
3. MySQL=10.0.0.51
4. NFS=10.0.0.31
...
read -p 请输入连接服务器的编号或者是主机名 : num
case $num in
1|WEB01)
ssh root@$WEB01 免秘钥登录
esac
[root@web scripts]# cat jumpserver.sh
#!/bin/sh
menu(){
cat<<EOF
1. WEB01=10.0.0.7
2. WEB02=10.0.0.8
3. MySQL=10.0.0.51
4. NFS=10.0.0.31
5|h. 显示菜单
EOF
}
menu
trap "echo 不要乱输入!小心爆炸!" HUP INT TSTP
while true
do
read -p "请输入连接服务器的编号或者是主机名 :" num
case $num in
1|WEB01)
ssh root@$WEB01 # 免秘钥登录
;;
2|WEB02)
ssh root@$WEB02 # 免秘钥登录
;;
5|h)
clear
menu
;;
woshiyunwei)
exit
;;
*)
echo "USAGE:[WEB01|1|WEB02|2|h]"
esac
done
19. for循环
for 变量名 in [取值列表] 苹果 香蕉 梨 桃子 西瓜 字符串 数字{}序列 命令
do
命令体
echo 呵呵
done
案例:使用for循环创建用户
cat user.txt
zs
ls
em
oldboy
[root@web scripts]# cat for1.sh
#!/bin/sh
for i in `cat user.txt`
do
useradd $i
done
命令行中使用for循环批量删除用户
for i in `cat user.txt`;do userdel -r $i;done
案例2:笔试题
使用for循环 从1加到100 结果5050
seq -s + 100|bc
[root@web scripts]# cat ping.sh
#!/bin/sh
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
for i in `seq 254`
do
IP=10.0.0.$i
ping -c 1 -W 1 $IP >/dev/null 2>&1
[ $? -eq 0 ] && action "ping $IP is" /bin/true
done
for i in `seq 100`;do sum=$[sum+i];done;echo $sum
20. while循环
while [ 条件表达式 ]
do
命令
done
案例:
1加到100
#!/bin/sh
i=0
while [ $i -le 100 ]
do
sum=$[i+sum]
let i++
done
echo $sum
while 读行
while read line line 变量名 按行读取文件的内容 for循环是按照空格分隔读取文件内容
do
命令
done<user.txt
从文件中读取用户和密码,批量创建用户
[root@web scripts]# cat while3.sh
#!/bin/sh
. /etc/init.d/functions
while read line
do
user=`echo $line|awk '{print $1}'`
useradd $user
pass=`echo $line|awk '{print $2}'`
echo $pass|passwd --stdin $user &>/dev/null
[ $? -eq 0 ] && action "$user create is ok" /bin/true
done<user.txt
判断一个文件中总共的行数
统计行号
[root@web scripts]# cat while4.sh
#!/bin/sh
while read line
do
let i++
done</etc/passwd
echo $i
21. 流程控制语句 exit continue break
exit 退出整个脚本 不会继续执行
break 跳出本次循环 继续往下执行 跳出循环体
continue 结束当前此次的命令,继续下一次循环
[root@web scripts]# cat exit.sh
#!/bin/sh
while true
do
echo ok
exit
echo hehe
done
echo done......
[root@web scripts]# break.sh
#!/bin/sh
while true
do
echo ok
break
echo hehe
done
echo done......
[root@web scripts]# continue.sh
#!/bin/sh
while true
do
echo ok
continue
echo hehe
done
echo done......
案例2:
[root@web scripts]# cat break.sh
#!/bin/sh
for i in `seq 10`
do
user=oldboy$i
id $user &>/dev/null
if [ $? -ne 0 ];then
useradd $user
[ $? -eq 0 ] && echo "$user create is ok"
else
break
fi
done
echo hehe.......
[root@web scripts]# cat continue.sh
#!/bin/sh
for i in `seq 10`
do
user=oldboy$i
id $user &>/dev/null
if [ $? -ne 0 ];then
useradd $user
[ $? -eq 0 ] && echo "$user create is ok"
else
continue
fi
done
echo hehe.......
22. 函数
命令的集合 完成特定功能的代码块
模块化 复用
函数和变量类似 只有先定义才可以调用,如果只定义不调用 则不会执行
函数的定义和调用
三种方法
[root@web scripts]# cat fun.sh
#!/bin/sh
test1(){
echo "第一种函数定义方式"
}
function test2(){
echo "第二种函数定义方式"
}
function test3 {
echo "第三种函数定义方式"
}
test1
test2
test3
函数的传参 不能直接传参
- 在函数名的后面跟参数
- 全局配置 在函数的最上面 设置变量
- local 只在函数体内部生效
fun(){
if [ -f $1 ];then
echo "$1 is exsis"
else
echo "$1 is no ex"
fi
}
fun $1
[root@web scripts]# cat fun.sh
#!/bin/sh
fun(){
if [ -f $1 ];then
echo "$1 exists"
else
echo "$1 no exists"
fi
}
fun $2 $3
#!/bin/sh
fun(){
num=20
for i in `seq 10`
do
sum=$[num+i]
done
echo $sum
}
fun
[root@web scripts]# cat fun1.sh
#!/bin/sh
fun(){
num=20
for i in `seq $1`
do
sum=$[num+i]
done
echo $sum
}
fun $3 $1 $2
[root@web scripts]# cat fun1.sh
#!/bin/sh
fun(){
num=20
for i in `seq $1`
do
sum=$[num+i]
done
echo $sum
}
fun $1
echo $num
以下错误 先定义 在调用
[root@web scripts]# cat fun1.sh
#!/bin/sh
fun $1
fun(){
num=20
for i in `seq $1`
do
sum=$[num+i]
done
echo $sum
}
函数的返回值 return
#!/bin/sh
[ -f /etc/hosts ] && exit 50 || exit 100
#!/bin/sh
fun(){
if [ -f $1 ];then
return 50
else
return 100
fi
}
fun $1
re=$?
[ $re -eq 50 ] && echo "$1 该文件存在"
[ $re -eq 100 ] && echo "$1 该文件不存在"
[root@web scripts]# cat fun3.sh
#!/bin/sh
fun(){
if [ -f $1 ];then
return 50
else
return 100
fi
}
fun $1
if [ $? -eq 50 ];then
echo "ok"
else
echo "error"
fi
函数内如果执行的上一条是函数名 则不会返回函数本身执行的返回值
[root@web scripts]# cat fun4.sh
#!/bin/sh
fun(){
echo 50
return 1
}
re=`fun`
echo "函数的返回值是?: $?"
echo "函数执行的结果是?: $re"
[root@web scripts]# sh fun4.sh
函数的返回值是?: 1
函数执行的结果是?: 50
[root@web scripts]# cat fun4.sh
#!/bin/sh
fun(){
echo 50
return 1
}
re=`fun`
name=oldboy
echo "函数的返回值是?: $?"
echo "函数执行的结果是?: $re"
[root@web scripts]# sh fun4.sh
函数的返回值是?: 0
函数执行的结果是?: 50