SHELL脚本
一、shell概述
1、基本信息
概念:利用Linux命令写成的代码,通过解释器进行运行的程序。
- /bin/bash:默认解释器
- cat /etc/shells:查看所有解释器
- yum -y install ksh:安装新解释器
- bash的优点:
- tab键,快捷键,历史记录,管道符,重定向。
2、规范的shell脚本
- 声明解释器:#!/bin/bash
- 注释脚本功能,变量含义等
- 可执行的代码。
3、脚本的运行方式
- 添加x执行权限
- 使用解释器执行,开启子进程:bash xxx.sh
- 使用当前解释器执行,不开启子进程:source xxx.sh
/dev/null # 黑洞设备,专用于收集不要的输出信息
exit 1 # 在shell脚本中,放在一个命令执行后,将此命令定义为错误输出,即$?为非0
二、变量
1、自定义变量
变量名称=值
- 名称:大小写字母、数字、下划线
- 不能用特殊字符,不能以数字开头
2、环境变量
- 系统默认存在的变量
- USER、UID、HOME、HOSTNAME、 SHELL、PATH、PS1、PS2
3、位置变量
#!/bin/bash
echo $1 #脚本后第1个参数
echo $2 #脚本后第2个参数
echo $3 #脚本后第3个参数
... ...
echo $10 #脚本后第10个参数
4、预定义变量
#!/bin/bash
echo $0 #脚本名
echo $$ #脚本执行时的进程ID号
echo $* #所有参数
echo $? #上一条命令是否执行成功
echo $# #参数的个数
5、查看变量
[root@server ~]# env #查看所有环境变量
[root@server ~]# set #查看所有变量
6、扩展知识
-
" " :双引号,界定范围
-
’ ’ :单引号,界定范围。屏蔽特殊符号
-
`` :反撇号,获取命令执行的结果
-
$():跟反撇号等同,获取命令执行的结果
-
交互式脚本:read -p “提示信息,自定义” 变量
-
stty -echo:屏蔽回显
-
stty echo :恢复回显
7、变量的发布
[root@ser ~]# export #发布全局变量
[root@ser ~]# export a=10 #发布新的全局变量
[root@ser ~]# export b #将局部变量扩展为全局变量
[root@ser ~]# export -n a #取消全局变量
[root@ser ~]# unset a #取消变量定义(删除变量)
三、运算
1、expr
#注:数字与运算符号之间要有空格
expr 1 + 1 加
expr 1 - 1 减
expr 2 \* 2 乘
expr 10 / 5 除
expr 10 % 3 求模,取余数
2、$[] 或 $(())
#无需空格
ehco $[1+1] 加
echo $[1-1] 减
echo [2*2] 乘
echo [10/2] 除
echo [10%5] 取余数
3、let
let 用于变量计算。结果不显示
let a=1+1
let b=c+d
变量的自增减:
let a=a-1 相当于 let a--
let a=a+1 相当于 let a++
let a=a+2 let a+=2
let a=a-2 let a-=2
let a=a*2 let a*=2
let a=a/2 let a/=2
let a=a%2 let a%=2
4、bc
bc 常用于小数的计算
echo "1.2+3.5" | bc
echo "scale=3;10/3" | bc #scale定义小数点后显示几位。
四、条件测试
1、字符串
- ==是否相等
- != 是否不等
- -z 是否为空
2、数字
- -eq:等于;-ne:不等于
- -lt:小于;-le:小于等于
- -gt:大于;-ge:大于等于
3、文件
- -e:存在为真,不管是文件还是目录
- -f:存在,且是文件才为真
- -d:存在,且是目录才为真
- -r:是否有读权限
- -w:是否有写权限
- -x:是否有执行权限
4、逻辑测试
- &&(并且):之前的任务成功,则执行后面的任务
- || (或者):之前的任务失败,才执行后面的任务
五、判断结构
1、if 判断
# 基本格式
#单分支
if [条件测试];then
命令
fi
# 双分支
if [条件测试];then
命令
else
命令
fi
# 多分支
if [条件测试];then
命令
elif [条件测试];then
命令
elif [条件测试];then
命令
... ...
else
命令
fi
2、case 分支
- case分支,相当于简化版本的if,功能 不如if强大,但是代码比较精简。一般用于制作一些小工具。
# 格式:
case 变量 in
模式1)
命令序列1;;
模式2)
命令序列2;;
*)
默认命令序列 # 最后一个可以不用分号。
esac
-----------------------------------------------------------------------
#!/bin/bash
case $1 in
redhat)
echo "fedora";;
fedora)
echo "redhat";;
*) //默认输出脚本用法
echo "用法: $0 {redhat|fedora}"
esac
六、循环结构
1、for循环
- 有限的循环,循环的次数和值有关
#基本结构:
for 变量名 in 循环值1、2、3....
do
命令
done
----------------------------
例1:
#!/bin/bash
for i in {1..10}
do
echo $i
done
----------------------------
例2:
#!/bin/bash
a=10
for i in `seq $a` #这里有变量时不能用大括号{}
do
echo $i
done
2、while循环
- 无限循环(死循环)
#基本结构:
while 条件测试
do
命令
done
-------------------------------------------
#!/bin/bash
x=$[RANDOM%100] #RANDOM:生成随机数。
y=0
while : #这里':'是指任何条件都成立
do
let y++
read -p "猜数(0-99):" n
if [ $n -gt $x ];then
echo "大了"
elif [ $n -lt $x ];then
echo "小了"
else
echo "对了"
echo "共猜了$y次"
fi
done
3、循环的控制
- exit:退出脚本
- break:终止循环,执行循环之后的任务
- continue:终止当前循环,继续下一次循环
七、函数
- 函数一般用在脚本里面,对于一些经常性用到的命令进行一个定义,然后在脚本中可以直接调用。
# 格式1:
function 函数名 {
命令序列1
命令序列2
... ...
}
# 格式2:
函数名 () {
命令序列
... ...
}
例:
# 使用函数编写方便调用不同颜色字体的脚本:
#!/bin/bash
cecho (){
echo -e "\033[$1m$2\033[0m" # 定义了一个函数命令
}
cecho 31 ABCDEFG # 调用函数命令
cecho 32 ABCDEFG
cecho 33 ABCDEFG
cecho 34 ABCDEFG
cecho 35 ABCDEFG
cecho 36 ABCDEFG
cecho 37 ABCDEFG
# 炸弹脚本
#!/bin/bash
abc(){
abc|abc &
}
abc
八、字符串的处理
1、截取
# 格式:
${变量名:起始位置:长度} # 起始位置的计算从0开始
# 例:
b=65498165
echo ${b:3:4} # 截取变量b,从第4位开始截取4位
echo ${b::4} # 起始为0时可省略0
# 应用:编写随机获取6位密码的脚本
#!/bin/bash
x=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
for i in {1..6}
do
n=${RANDOM%62}
p=${x:n:1}
pass=$p$pass
done
echo $pass
2、替换
# 格式:
${变量名/旧/新}
# 例:
b=1802874632
echo ${b/1/a} # 将 1 替换为 a
echo ${b/8/a} # 将 8 替换为 a
echo ${b//8/a} # 将所有 8 替换为 a
echo ${b/0/} # 将数字 0 替换为空,相当于删除
3、删除(掐头去尾)
# 格式:
${变量名#*关键词} # 从左往右删除 掐头
# 例
a="root:x:0:0:root:/root:/bin/bash"
echo ${a#root} # 删除到第一个 root
echo ${a##*root} # 删除到最后一个 root,以及此 root 左边所有
echo ${a##*/} # 删除到最后一个/,以及此/左边所有
echo ${a#*:root} # 删除:root,以及左边所有
--------------------------------------------
# 格式
${变量名%关键词*} # 从右往左删除 去尾
# 例
echo ${a%bash} # 从右往左删除到 bash
echo ${a%root*} # 从右往左删除到第一个 root,以及 root 右边所有
echo ${a%/*} # 从右往左删除到第一个/,以及/右边所有
echo ${a%%/*} # 从右往左删除到最后一个/,以及/右边所有
--------------------------------------------------------------------
# 利用字符串删除功能,编写批量修改文件扩展名的脚本:
#!/bin/bash
for i in `ls *.txt` 首先找到修改目标
do
n=${i%.*} 利用删除中的去尾将扩展名删除,剩下不带扩展名的文件名
mv $i $n.doc 在将上述文件名与.doc 组合,修改为新名字
done
4、初值
# 格式
${变量名:-}
# 例
[root@server0 opt]# a=
[root@server0 opt]# echo ${a:-123} //当变量是空时调用初值
123
[root@server0 opt]# a=789
[root@server0 opt]# echo ${a:-123} //变量有值时不使用初值
789
------------------------------------------------------------------------
# 配置密码时使用初值
#!/bin/bash
read -p "请输入用户名:" u
useradd $u
read -p "请输入密码:" p
echo ${p:-123456} | passwd --stdin $u # 当输入密码为空时,默认密码为123456。
九、正则
1、基本正则
正则符号 | 描述 |
---|---|
^ | 匹配行首 |
$ | 匹配行尾 |
[ ] | 集合,匹配集合中的任意单个字符 |
[^] | 对集合取反 |
. | 匹配任意单个字符 |
* | 匹配前一个字符任意次数。不允许单独使用 |
\ {n,m\ } | 匹配前一个字符:n 到 m 次 |
\ {n\ } | 匹配前一个字符:n 次 |
\ {n,\ } | 匹配前一个字符:n 次 及以上 |
\(\ ) | 保留 |
2、扩展正则
正则符号 | 描述 |
---|---|
+ | 最少匹配一次 |
? | 最多匹配一次 |
{n,m} | 匹配 n 到 m 次 |
( ) | 保留,使组合成整体 |
| | 或者 |
\b | 单词边界 |
3、grep
- 配合基本正则
- 格式为:grep “正则” 文件
# 基本正则的使用:
cat /etc/passwd > user # 素材
grep ^root user # 搜索以root开头的
grep in$ user # 搜索以in结尾的
grep [in] user # 搜索字母 i 或者 n
grep [^in] user # 搜索除了字母 i 或者 n 以外所有的
grep "." user 搜索任意单个字符。包括空格,但不包括空行。
grep ".*" user 搜索任意。包括空行。
grep "ro*t" user # 搜索r?t,r与t之间任意个o
grep "0:\{2\}" user # 搜索 0::
grep "\(0:\)\{2\}" user # 搜索 0:0:
- 扩展正则
- grep -E 或 egrep
grep -E "ro+t" user
egrep "ro+t" user
grep -E "bi?n" user
egrep "bi?n" user
grep -E "ro{2,4}t" user # 搜索ro?t,其中o出现2到4次
grep -E "ro|in" user # 搜索ro或in
grep -E "\bthe" user # 搜索单词the,前面不能有数字字母下划线
grep -E "0:{2}" user # 搜索0::
grep -E "(0:){2}" user # 搜索 0:0:
十、Sed
1、格式
流式编辑器。非交互式修改文本,支持正则。
- 工作方式:逐行处理。
# 使用方式:
sed 选项 '(定址符)/正则/指令' 被处理文件
前置命令 | sed 选项 '(定址符)/正则/指令'
sed 选项 '(定址符)/正则/指令1;(定址符)/正则/指令2;' 文件 # 用分号;隔开多条指令。
# 选项:
-n:屏蔽默认输出
-r:支持扩展正则
-i:写入文件
# 指令:
p:输出
d:删除
s:替换
a:在行下追加
i:在行上追加
c:整行替换
# 定址符,定址符可以不写,不写时,默认逐行处理。
'p' # 逐行处理。即输出全部
'1p' # 输出:第1行
'2,5p' # 输出:第2~5行
'3p;7p' # 输出:第3行,第7行
'4,+2p' # 输出:第4行,及后面的2行
'1~2p' # 输出:奇数行
'2~2p' # 输出:偶数行
'=' # 显示全部行号
'$=' # 显示最后一行行号
2、基本应用
# 替换
sed 's/xml/abc/' a.txt # 将每行中的第1个xml替换成abc
sed 's/xml/abc/3' a.txt # 将每行中的第3个xml替换成abc
sed 's/xml/abc/g' a.txt # 将全部xml替换成abc
sed 's/xml//g' a.txt # 将全部xml替换成空,即删除
sed 's/\/bin\/bash/\/sbin\/sh/' user # 将/bin/bash 替换成 /sbin/sh
sed 's#/bin/bash#/sbin/sh' user
sed 's!/bin/bash!/sbin/sh' user
sed 's(/bin/bash(/sbin/sh' user
# 效果与上一条一致。当替换字符中有与替换符冲突时,可以使用数字键上方的任意一种特殊符号代替
------------------------------------------------------------------------
# 正则中保留的特殊使用:()保留,也相当于复制,使用\1\2\3 进行粘贴
sed -r 's/^(.)(.*)(.)$/\3\2\1/' a.tat # 将每行的第一个字符与最后一个字符对调
表示全部数字[0-9],全部大写字母[A-Z],全部大小写字母[a-Z]
-------------------------------------------------------------------------
# 行下、行上追加,整行替换(在与替换内容之间空格一下)
sed 'a xxxxxx' a.txt # 所有行下添加
sed '1a xxxxxx' a.txt # 第1行行下添加
sed '1,2a xxxx' a.txt # 1~2行下添加
sed 'i xxxxxx' a.txt # 所有行上添加
sed '2i xxxxx' a.txt # 第2行上添加
sed 'c xxxxx' a.txt # 所有行替换
sed '/abc/c xxxx' a.txt # 包含abc的行替换成xxxx
3、实际使用
- 编写脚本,找出使用 bash 的用户,按照 名字 --> 密码 的格式输出
#!/bin/bash
u=`sed -n '/bash$/s/:.*//p' /etc/passwd` # 找到bash用户,并把名字存入变量b
for i in $u
do
x=`grep $i:/etc/shadow`
a1=${x#*:} # 掐头
a2=${a1%%:*} # 去尾
echo "$i ---> $a2"
done
十一、awk
1、格式
- awk 数据过滤软件:可以进行精确搜索
- awk 的默认工作模式:逐行处理。
# 格式:
awk 选项 '条件{指令}' 被处理文件 # 条件和指令需要使用单引号,指令必须用{}
前置命令 | awk 选项 '条件{指令}'
awk 选项 '条件{指令1;指令2;指令3}' 文件 # 多条指令间用分号;隔开
# 常用选项
-F # 自定义分隔符。默认情况下,分隔符是空格或tab
-F: # 以:为分隔符
-F[:/] # 以:和/ 为分隔符
# 常用指令
print 输出
# 内置变量
$0 所有列
$1 第1列
$2 第2列
... ...
NF 列
NR 行
2、条件的使用
2.1、正则
awk '/正则条件/指令' # 在使用正则时:要用斜线
# ~ 包含; !~ 不包含; 当内置变量与正则使用时需要用到
awk '$1~/正则/指令‘ # 第1列包含...
awk '$1!~/正则/指令' # 第1列不包含...
2.2、字符、数值比较
==(等于)、!=(不等于)、>(大于)、<(小于)、>=(大于等于)、<=(小于等于)
# 不写指令时,默认指令为输出{print}
# 常量必须用双引号""标注。
awk 'NR==2' a.txt # 输出行数等于2的内容。
awk '$1=="root"{print}' a.txt #
awk '$1!="root"' a.txt
awk '$3<5' a.txt # 输出第3列小于5的行
awk '$3=="5"' a.txt # 输出第3列的字符等于0的行。
2.3、逻辑符号:&&、||
# 逻辑符号一般配合其它的条件因素进行使用。
awk '$2<10 && $2>5' a.txt
awk '$2<10 || $4>15' a.txt
2.4、计算
seq 100 | awk '$1%7==0 || $1~/7/' # 列出100以内整数中7的位数,或包含7的数。
awk 'BEGIN{x++;print x}'
awk 'BEGIN{x=8; print x+=2}'
awk 'BEGIN{print 2+3}'
awk 'BEGIN{print 2*3}'
awk 'BEGIN{print 23%8}'
3、工作流程的控制
3.1、if
# if中的条件仍然可以使用正则。
if(条件){命令}
if(条件){命令} else{命令}
if(条件){} else if(条件){}.....
# awk中if是个指令,必须放在{}中,但是可以用空格隔开,awk不关心空格。
awk 选项 '(条件){ if(){} else{} }' 文件
3.2、BEGIN、END
# BEGIN{}任务:只执行一次;{}常规任务:逐行执行;END{}:只执行一次
awk 选项 '(条件) BEGIN{} {} END{}' 文件
# 在awk中,是无视空格的。如果输出需要一定的排版,可以用\t
\t :制表符。相当于tab键。在输出的时候可以起到一定的排版效果。
awk -F: 'BEGIN{print "User \t UID \t Hone"} {print $1 "\t" $3 "\t" $6} END{print "总计 "NR" 行"}' /etc/passwd
4、数组
- 数组:一个可以存多个值的变量。本质上,仍是一个变量。
- 定义数组:数组名[下标]=元素值
- 调用数组:数组名[下标]
- 遍历数组:for(变量 in 数组名){print 数组名[变量]}
- awk数组的下标除了可以使用数字,也可以使用字符串,字符串需要使用双引号
[root@svr5 ~]# awk 'BEGIN{a[0]=0;a[1]=11;a[2]=22; for(i in a){print i,a[i]}}'
0 0
1 11
2 22
[root@svr5 ~]# awk 'BEGIN{a["hehe"]=11;print a["hehe"]}'
11
遍历数组:
for(变量 in 数组名){print 数组名[变量]}
详解:这里for循环中,是将数组的下标分别赋值给变量,再通过输出数组的格式,逐一输出数组值。
- 实际应用
# 统计Web访问量
[root@svr5 ~]# awk '{ip[$1]++} \
> END{for(i in ip) {print ip[i],i }}' /var/log/httpd/access_log
4 127.0.0.1
17 192.168.4.5
13 192.168.4.110
.. ..
# 对访问量排序排名:
[root@svr5 ~]# awk '{ip[$1]++} END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log | sort -nr
17 192.168.4.5
13 192.168.4.110
4 127.0.0.1
.. ..
# 排序命令
sort -r # 按数字升序排列
sort -n # 反序
sort -k # 指定按第几个字段排序
awk细节注意点
- 指令中如果输出常量,则需要使用双引号。否则,系统会识别为变量,输出会为空。
- 但是,在常量中,如果包含了变量,需要输出变量,则需要为变量也加上双引号,以抵消外面的双引效果。
- END{print “总计 “NR” 行”}
- 条件和指令需要使用单引号,指令必须用{}
应用案例
1、监控脚本
查看性能数据的命令
[root@svr5 ~]# uptime //查看CPU负载
[root@svr5 ~]# ifconfig eth0 //查看网卡流量
[root@svr5 ~]# free //查看内存信息
[root@svr5 ~]# df //查看磁盘空间
[root@svr5 ~]# wc -l /etc/passwd //查看计算机账户数量
[root@svr5 ~]# who |wc -l //查看登录账户数量
[root@svr5 ~]# rpm -qa |wc -l //查看已安装软件包数量
#!/bin/bash
ip=`ifconfig eth0 | awk '/inet /{print $2}'`
echo "本地IP地址是:"$ip
cpu=`uptime | awk '{print $NF}'`
#awk中NF为当前行的列数,$NF是最后一列
echo "本机CPU最近15分钟的负载是:"$cpu
net_in=`ifconfig eth0 | awk '/RX p/{print $5}'`
echo "入站网卡流量为:"$net_in
net_out=`ifconfig eth0 | awk '/TX p/{print $5}'`
echo "出站网卡流量为:"$net_out
mem=`free | awk '/Mem/{print $4}'`
echo "内存剩余容量为:"$mem
disk=`df | awk '/\/$/{print $4}'`
echo "根分区剩余容量为:"$disk
user=`cat /etc/passwd |wc -l`
echo "本地账户数量为:"$user
login=`who | wc -l`
echo "当前登陆计算机的账户数量为:"$login
process=`ps aux | wc -l`
echo "当前计算机启动的进程数量为:"$process
soft=`rpm -qa | wc -l`
echo "当前计算机已安装的软件数量为:"$soft
2、安全检测脚本
- 检测ssh登录日志,如果远程登陆账号名错误3次,则屏蔽远程主机的IP
- 检测ssh登录日志,如果远程登陆密码错误3次,则屏蔽远程主机的IP
过滤帐户名失败的命令(登陆日志文件为/var/log/secure)
[root@svr5 ~]# awk '/Invalid user/{print $10}' /var/log/secure
过滤密码失败的命令
[root@svr5 ~]# awk '/Failed password/{print $11}' /var/log/secure
#!/bin/bash
awk '/Failed password/{print $11}' /var/log/secure | awk '{ip[$1]++}END{for(i in ip){print ip[i],i}}' | awk '$1>3{print $2}'
awk '/Invalid user/{print $10}' /var/log/secure | awk '{ip[$1]++}END{for(i in ip){print ip[i],i}}' | awk '$1>3{print $2}'
3、sed、awk对同一案例的不同应用
要求:
- 分析出使用bash作登录Shell的本地用户
- 列出这些用户的shadow密码记录
- 按每行“用户名 – 密码记录”保存结果
#/bin/bash
A=$(sed -n '/bash$/s/:.*//p' /etc/passwd) # 提取符合条件的账号记录
for i in $A # 遍历账号记录
do
pass1=$(grep $i /etc/shadow)
pass2=${pass1#*:}
pass=${pass2%%:*}
echo "$i --> $pass"
done
#/bin/bash
A=$(awk -F: '/bash$/{print $1}' /etc/passwd) # 提取符合条件的账号记录
for i in $A
do
grep $i /etc/shadow | awk -F: '{print $1,"-->",$2}'
done
3、监控 web 服务
监控 web 服务是否正常,不低于 3 种监控策略。要求间隔 1 分钟,持续监控。
#!/bin/bash
# . /etc/init.d/functions # 声明调用此文件中的函数。functions文件内有默认已经定义好的一些函数,如:echo_success、action "" /bin/true 等
url=wwchengbi.cn
Port=80
check_web() {
[ -f /etc/init.d/functions ]&& . /etc/init.d/functions
if [ "`nc -z $url $Port && echo ok`" = "ok" ];then
#if [ "`echo -e '\n'| telnet $url $Port |grep Connected|wc -l`" = "1" ];then
#if [ "`nmap $url -p $Port |grep open |wc -l`" = "1" ];then
#if [ "`curl -I http://$url 2>/dev/null |head -1 |egrep "200|302|301" |wc -l`" ="1" ];then
#if [ "`curl -I -s -o /dev/null -w '%{http_code}\n' http://$url`" = "200" ];then
action "$url $Port" /bin/true # 打印指定内容,并提示是[OK]
else
action "$url $Port /bin/false" # 打印指定内容,并提示是[FAILED]
fi
}
main() {
while true
do
check_web
sleep 1m
done
}
main
4、监控 db 服务
- 监控 db 服务是否正常,不低于 3 种监控策略。要求间隔 1 分钟,持续监控。
#!bin/bash
Port=3306
user=
pw=
IP=
check_db() {
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
if [ `lsof -i:$Port|wc -l` -gt 1 ];then
#if [ "`netstat -tunlp |grep 3306 |wc -l`" = "1" ];then
#if [ `mysql -u$user -p$pw -h$IP -P $Port -e "show databases;" |wc -l` -gt 1 ];then
action "MySQL $Port online" /bin/true
else
action "MySQL $Port down" /bin/false
fi
}
main() {
while true
do
check_db
sleep 1s
done
}
main
5、监控 web 站点目录
- 监控 web 站点目录(/var/html/www)下所有文件是否被恶意篡改(文件内容被改了),如果有就打印改动的文件名(发邮件),定时任务每 3 分钟执行一次(10 分钟时间完成)。
#!/bin/bash
# exec < filename:此命令会将stdin重定向到文件中. 从这句开始, 所有的stdin就都来自于这个文件了, 而不是标准输入(通常都是键盘输入); 这样就提供了一种按行读取文件的方法,并且可以使用sed和/或awk来对每一行进行分析。
# read line:读取上一条标准输出
#find /var/www/html/ -type f -exec md5sum {} \; > /tmp/md5_www.log
check_www () {
md5sum -c /tmp/md5_www.log > /tmp/result_www.log
[ ! -f /tmp/result_www.log ] && echo "/tmp/result_www.log not exist." && exit 2
exec < /tmp/result_www.log
while read line
do
file=`echo $line | awk -F':' '{print $1}'`
result=`echo $line | awk -F':' '{print $NF}'`
#echo $file
#echo $result
#sleep 2s
[ ! $result = "OK" ] && action "$file" /bin/false
done
}
main () {
while true
do
LANG=en #
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
[ ! -f /tmp/md5_www.log ] && echo "/tmp/md5_www.log not exist."&& exit 1
check_www
action "Alii check done." /bin/true
sleep 10s
done
}
main
6、监控 MySQL 主从同步
- 监控 MySQL 主从同步是否异常,如果异常,则发送短信或者邮件给管理员。
- 提示:如果没主从同步环境,可以用下面文本放到文件里读取来模拟
- 阶段 1:开发一个守护进程脚本每 30 秒实现检测一次。
- 阶段 2:如果同步出现如下错误号(1158,1159,1008,1007,1062),则跳过错误。
- 阶段 3:请使用数组技术实现上述脚本(获取主从判断及错误号部分)
#!/bin/bash
port=3306
error=(1158 1159 1008 1007 1062)
MysqlCmd1="mysql -h192.168.4.52 -uroot -p123456 -e"
MysqlCmd2="mysql -h192.168.4.52 -uroot -p123456 -e 'show slave status\G' | egrep '_Running|Last_Errno|Behind_Master' |awk '{print \$NF}'"
is_run() {
[ `lsof -i:$port |wc -l` -lt 2 ] && {
echo "mysql is stop"
exit 1
}
}
mysql_status() {
array=(`echo $MysqlCmd2 | bash`)
}
judge_error() {
for i in ${error[*]}
do
if [ "${array[2]}" == "$i" ];then
${MysqlCmd1} "stop slave;SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;start slave;"
else
echo "mysql is failed,error id is ${array[2]}"
fi
done
}
judge_status() {
mysql_status
echo ${array[*]}
if [ "${array[0]}" == "Yes" -a "${array[1]}" == "Yes" -a "${array[3]}" == "0" ];then
echo "Mysql slave is ok"
else
judge_error #${array[2]}
fi
}
main() {
while true
do
is_run
judge_status
sleep 3
done
}
main
7、解决DOS攻击
- 用至少两种方法实现!写一个脚本解决 DOS 攻击生产案例