81、题目要求 : 监控磁盘
阿里云的机器,今天收到客服来的电话,说服务器的磁盘io很重。于是登录到服务器查看,并没有发现问题,所以怀疑是间歇性地。正要考虑写个脚本的时候,幸运的抓到了一个线索,造成磁盘io很高的幕后黑手是mysql。此时去show processlist,但未发现有问题的队列。原来只是一瞬间。只好继续来写脚本,思路是,每5s检测一次磁盘io,当发现问题去查询mysql的processlist。
【核心要点】
iostat -xd 1 5 ,主要看%util ;-xd :只查看磁盘信息。
参考答案
#!/bin/bash
#这个脚本用来监控磁盘IO
#作者:猿课-阿铭 www.apelearn.com
#日期:2018-12-12
if ! while iostat &>/dev/null
then
yum install -y sysstat
fi
while :
do
t=`date +%T`
iostat -xd 1 5 |grep '^sda'> /tmp/io.log
sum=`awk '{sum=sum+$NF} END {print sum}' /tmp/io.log`
a=`echo "scale=2;$sum/5"|bc`
b=`echo $a|cut -d . -f 1`
if [ $b -gt 90 ]
then
mysql -uroot -pxxxx -e "show processlist" > mysql_$t.log
fi
sleep 1
done
实例 :
查看磁盘的读写速度。%util越大,说明磁盘越忙。
查看平均磁盘读写速率
查看磁盘sda的读写速度,查看最后一列。
将磁盘sda的读写速度写入到/tmp/io.log。取最后一列使用“$NF”,显示磁盘的读写速度是0.02
修改磁盘读写速度,用于测试。
6.92除以5,求磁盘平均读写速度。
取一位整数
执行脚本,查看结果
注意 :
yum install -y sysstat #安装查看io的命令软件包
if ! while iostat &>/dev/null #查看iostat有没有安装,如果没有,执行下面的任务。
t=`date +%T` #显示当前系统时间
iostat -xd 1 5 |grep '^sda'> /tmp/io.log #将磁盘sda的读写速度写入到/tmp/io.log。
sum=`awk '{sum=sum+$NF} END {print sum}' /tmp/io.log` #将磁盘sda的读写速度写入到/tmp/io.log。取最后一列使用“$NF”,写入到/tmp/io.log。
a=`echo "scale=2;$sum/5"|bc` #除以5,保留2位数字
b=`echo $a|cut -d . -f 1` #取一位整数
if [ $b -gt 90 ] #查看gt的值是否大于90
mysql -uroot -pxxxx -e "show processlist" > mysql_$t.log #如果当发现问题去查询mysql的processlist。,并写入到mysql_$t.log日志里面
82、题目要求 : 查看tomcat日志
写一个截取tomcat catalina.out日志的脚本 tomcat实例t1-t4
# find /opt/TOM/ -name catalina.out
/opt/TOM/t1/logs/catalina.out
/opt/TOM/t3/logs/catalina.out
/opt/TOM/t4/logs/catalina.out
/opt/TOM/t2/logs/catalina.out
要求:
- 这个脚本可以取tomcat实例t1-t4的日志
- 这个脚本可以自定义取日志的起始点 ,比如取今天早上10点之后到现在的数据
- 这个脚本可以自定义取日志的起始点和终点,比如取今天早上9点到晚上8点的数据 catalina.out 日志内容
Oct 29, 2018 01:52:24 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
Oct 29, 2018 01:52:24 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
Oct 29, 2018 01:52:24 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 2102 ms
【核心要点】
参考答案
#!/bin/bash
#这个脚本用来查看Tomcat日志
#作者:猿课-阿铭 www.apelearn.com
#日期:2018-12-12
LANG=en
logfile="/opt/TOM/$1/logs/catalina.out"
#将当天的英文月、数字日期、数字年作为变量赋值给d_mdy
d_mdy=`date "+%b %d, %Y"`
#判断参数个数
if [ $# -ne 2 ] && [ $# -ne 3 ]
then
echo "你提供的参数个数不对,请提供2个或者3个参数。例:sh $0 t1 08:01:00 14:00:00"
exit 1
fi
#判断第一个参数是否符合要求
if ! echo $1|grep -qE '^t1$|^t2$|^t3$|^t4$'
then
echo "第一个参数必须是t1、t2、t3或t4"
exit 1
fi
#判断时间有效性
judge_time()
{
date -d "$1" +%s &>/dev/null
if [ $? -ne 0 ]
then
echo "你提供的时间$1格式不正确"
exit 1
fi
}
#将24小时制时间转换为12小时
tr_24_12()
{
date -d "$1" +%r
}
#判断提供的时间点是否在日志中出现
judge_time_in_log()
{
if ! grep -q "$d_mdy $(tr_24_12 $1)" $logfile
then
echo "你提供的时间$1在日志$logfile中不曾出现,请换一个时间点"
exit 1
fi
}
#判断第2个参数是否合法
judge_time $2
#判断起始时间点是否出现在日志里
judge_time_in_log $2
#如果提供第3个参数
if [ $# -eq 3 ]
then
#判断第3个参数是否合法
judge_time $3
#判断起始时间是否早于结束时间
t1=`date -d "$2" +%s`
t2=`date -d "$3" +%s`
if [ $t2 -lt $t1 ]
then
echo "你提供的时间$2比$3要晚,应该把早的时间放到前面"
exit
fi
#判断提供的结束时间点是否出现在日志中
judge_time_in_log $3
fi
#取起始时间所在行行号
begin_n=`grep -n "$d_mdy $(tr_24_12 $2)" $logfile|head -1|awk -F ':' '{print $1}'`
#取结束时间所在行行号,并用sed截取日志内容
if [ $# -eq 3 ]
then
n=`grep -n "$d_mdy $(tr_24_12 $3)" $logfile|tail -1|awk -F ':' '{print $1}'`
#结束日期所在行的下一行才是日志的内容
end_n=$[$n+1]
sed -n "$begin_n,$end_n"p $logfile
else
sed -n "$begin_n,$"p $logfile
fi
实例 :
查看系统时间,是否和tomcat日志里面的时间一样。
将24小时时间制转换成12小时时间制,和Tomcat日志的时间格式一样,便于观察。
执行脚本,查看结果
注意 “:
date -d "$1" +%s &>/dev/null #将用户输入的参数,写入到/dev/null 中,-d测试,$1表示用户输入的时间
if [ $# -ne 2 ] && [ $# -ne 3 ] #提供的参数 不是2,也不是3时。提示用户。
if ! grep -q "$d_mdy $(tr_24_12 $1)" $logfile #将24小时时间制转换成12小时时间制,grep -p检查时间格式是不是和日志中的一样。
83、题目要求 : 打印城市名字
写一个脚本让用户输入多个城市的名字(可以是中文),要求不少于5个,然后把这些城市存到一个数组里,最后用for循环把它们打印出来。
【核心要点】
赋值数组 : arry=(1 2 a b c)
打印数组 : echo ${arry[@]}
参考答案
#!/bin/bash
#这个脚本用来打印城市名字
#作者:猿课-阿铭 www.apelearn.com
#日期:2018-12-12
read -p "输入不少于5个城市的名字,用空格分隔开。" name
n=`echo $name|awk '{print NF}'`
if [ $n -lt 5 ]
then
echo "请输入至少5个城市的名字."
exit
fi
city=($name)
for i in `seq 0 $[${#city[@]}-1]`
do
echo ${city[$i]}
done
实例 :
打印数组
查看数组的循环,发现是从0开始的。
数组的赋值 ;打印数组的值 ; 统计数组的个数 ;针对个别元素。
执行脚本,查看结果。
注意 :
n=`echo $name|awk '{print NF}'` #名字之间,用空格隔开。
if [ $n -lt 5 ] #$n的值小于5,
for i in `seq 0 $[${#city[@]}-1]` #打印用户输入的城市名,因为数组的循环是从0开始的,所以要减一。
84、题目要求 : 代码上线
需求背景是: 一个业务,有3台服务器(A,B,C)做负载均衡,由于规模太小目前并未使用专业的自动化运维工具。有新的需求时,开发同事改完代码会把变更上传到其中一台服务器A上。但是其他2台服务器也需要做相同变更。
写一个shell脚本,把A服务器上的变更代码同步到B和C上。 其中,你需要考虑到不需要同步的目录(假如有tmp、upload、logs、caches)
【核心要点】
rsync同步
密钥认证或者expect脚本
参考答案
#!/bin/bash
#这个脚本用来代码上线
#作者:猿课-阿铭 www.apelearn.com
#日期:2018-12-12
dir=/data/wwwroot/www.aaa.com
B_IP=1.1.1.1
C_IP=2.2.2.2
rs()
{
rsync -azP --exclude="logs" \
--exclude="tmp" --exclude="upload" \
--exclude="caches" $dir/ $1:$dir/
}
read -p "该脚本将会把本机的$dir下的文件同步到$B_IP和$C_IP上,是否要继续?y|n" c
case $c in
y|Y)
rs B_IP
rs C_IP
;;
n|N)
exit
;;
*)
echo "你只能输入y或者n."
;;
esac
注意 :
dir=/data/wwwroot/www.aaa.com #假如a ,b,c机器的变更代码需要同步的目录都是一样。
rsync -azP --exclude="logs" \
--exclude="tmp" --exclude="upload" \
--exclude="caches" $dir/ $1:$dir/ #把A服务器上的变更代码同步到B和C上,排除的目录tmp、upload、logs、caches。 $dir/ $1:$dir/表示$dir同步到b机器下的$dir目录下,$1是b机器的IP
85、题目要求 : 统计并发量
需求背景:
需要统计网站的并发量,并绘图。 说明: 只需要写出shell脚本即可,不用关心zabbix配置。
假设日志路径 /data/logs/www.aaa.com_access.log
日志格式如下:
112.107.15.12 - [07/Nov/2018:09:59:01 +0800] www.aaa.com "/api/live.php" 200"-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)"
【核心要点】
查看日志中1秒内的日志数量,即并发数(每秒请求多少次)
参考答案
#!/bin/bash
#这个脚本用来计算网站并发量
#作者:猿课-阿铭 www.apelearn.com
#日期:2018-12-12
LANG=en
t=`date -d "-1 second" +%d/%b/%Y:%`
log=/data/logs/www.aaa.com_access.log
tail -1000 $log |grep -c "$t"
实例 :
获取上一秒的时间。%b : 作用是显示月份。
获取上一秒的时间,与日志显示的时间一致。
执行脚本,查看结果
注意 :
t=`date -d "-1 second" +%d/%b/%Y:%` # 求上一秒的日志时间
log=/data/logs/www.aaa.com_access.log #访问日志,通过访问日志,计算网站的并发量
tail -1000 $log |grep -c "$t" #统计最后一千条并发量日志,并截取到日志时间
86、题目要求 : 关闭服务
在centos6系统里,我们可以使用ntsysv关闭不需要开机启动的服务,当然也可以使用chkconfig工具来实现。
写一个shell脚本,用chkconfig工具把不常用的服务关闭。脚本需要写成交互式的,需要我们给它提供关闭的服务名字。
【核心要点】
chkconfig --list
参考答案
#!/bin/bash
#这个脚本用来关闭服务
#作者:猿课-阿铭 www.apelearn.com
#日期:2018-12-14
LANG=en
while :
do
chkconfig --list 2>/dev/null|grep '3:on' |awk '{print $1}' > /tmp/on_sev.txt
echo -e "\033[32m系统里开启了这些服务: \033[0m"
cat /tmp/on_sev.txt
echo
read -p "Please select a service from this list: " s
if ! grep -qw "$s" /tmp/on_sev.txt
then
echo -e "\033[31m你提供的服务名并未开启.\033[0m"
continue
fi
chkconfig $s off
break
done
实例 :
查看服务列表
列出开启的服务,并显示在一列。
给字体添加颜色
执行脚本,查看结果
注意 :
chkconfig --list 2>/dev/null|grep '3:on' |awk '{print $1}' > /tmp/on_sev.txt #列出所有的on服务,
echo -e "\033[32m系统里开启了这些服务: \033[0m" #
if ! grep -qw "$s" /tmp/on_sev.txt #查看$s,是否在/tmp/on_sev.txt ,不存在,就提示用户。
chkconfig $s off #关闭不需要开机启动的$s服务。
87、题目要求 : 彻底关闭tomcat服务
在生产环境中,经常遇到tomcat无法彻底关闭,也就是说用tomcat自带shutdown.sh脚本无法将java进程完全关掉。所以,需要借助shell脚本,将进程杀死,然后再启动。
写一个shell脚本,实现上述功能。彻底杀死一个进程的命令是 kill -9 pid。
【核心要点】
kill -9 pid
参考答案
#!/bin/bash
#这个脚本用来彻底杀死Tomcat进程
#作者:猿课-阿铭 www.apelearn.com
#日期:2018-12-14
dir=/usr/local/tomcat/bin/
java_pc()
{
pgrep java|wc -l
}
cd $dir
./shutdown.sh
count=0
while [ $count -lt 5 ]
do
n=`java_pc`
if [ $n -gt 0 ]
then
killall java
count=$[$count+1]
sleep 1
else
break
fi
done
n=`java_pc`
if [ $n -gt 0 ]
then
killall -9 java
fi
n=`java_pc`
if [ $n -gt 0 ]
then
echo "Tomcat无法强制杀死。"
exit
fi
cd $dir
./startup.sh
实例 :
执行脚本,查看结果
注意 :
pgrep java|wc -l #把java方面的服务和进程行数,都统计出来。
while [ $count -lt 5 ] #当他关闭的次数小于5
if [ $n -gt 0 ] #当$n大于0。
88、题目要求 : 去掉文件名后缀
至少用两种方法,批量把当前目录下面所有文件名后缀为.bak的后缀去掉,比如1.txt.bak去掉后为1.txt
【核心要点】
方法一 :用sed把文件名结尾的.bak去掉
方法二 :awk截取去掉后缀的部分,复制变量
参考答案
#!/bin/bash
#这个脚本用来去掉文件名后缀
#作者:猿课-阿铭 www.apelearn.com
#日期:2018-12-14
for f in `ls -d ./*.bak `
do
# mv $f `echo $f|sed 's/.bak$//'`
f1=`echo $f|awk -F '.bak$' '{print $1}' `
mv $f $f1
done
实例 :
查看目录下的.bak的文件
执行脚本,查看结果
脚本生成的1。1
注意 :
for f in `ls -d ./*.bak ` #表示目录下的.bak的文件
mv $f `echo $f|sed 's/.bak$//'` #用sed把文件名结尾的.bak去掉
f1=`echo $f|awk -F '.bak$' '{print $1}' ` #awk截取去掉后缀的部分,复制变量,打印第一行。
89、题目要求 : 检查域名是否到期
写一个shell脚本,查询指定域名的过期时间,并在到期前一周,每天发一封提醒邮件。
【核心要点】
可以在Linux下使用命令“whois域名”,如“whois aplelearn.com” ,来获取该域名的一些信息
参考答案
#!/bin/bash
#这个脚本用来检查域名是否到期
#作者:猿课-阿铭 www.apelearn.com
#日期:2018-12-14
mail_u=admin@admin.com
#当前日期时间戳,用于和域名的到期时间做比较
t1=`date +%s`
#检测whois命令是否存在,不存在则安装jwhois包
is_install_whois()
{
which whois >/dev/null 2>/dev/null
if [ $? -ne 0 ]
then
yum install -y epel-release
yum install -y jwhois
fi
}
notify()
{
#e_d=`whois $1|grep 'Expiry Date'|awk '{print $4}'|cut -d 'T' -f 1`
e_d=`whois $1|grep 'Expiration'|tail -1 |awk '{print $5}' |awk -F 'T' '{print $1}'`
#如果e_d的值为空,则过滤关键词'Expiration Time'
if [ -z "$e_d" ]
then
e_d=`whois $1|grep 'Expiration Time'|awk '{print $3}'`
fi
#将域名过期的日期转化为时间戳
e_t=`date -d "$e_d" +%s`
#计算一周一共有多少秒
n=`echo "86400*7"|bc`
e_t1=$[$e_t-$n]
e_t2=$[$e_t+$n]
if [ $t1 -ge $e_t1 ] && [ $t1 -lt $e_t ]
then
python mail.py $mail_u "Domain $1 will to be expired." "Domain $1 expire date is $e_d."
fi
if [ $t1 -ge $e_t ] && [ $t1 -lt $e_t2 ]
then
python mail.py $mail_u "Domain $1 has been expired" "Domain $1 expire date is $e_d."
fi
}
#检测上次运行的whois查询进程是否存在
#若存在,需要杀死进程,以免影响本次脚本执行
if pgrep whois &>/dev/null
then
killall -9 whois
fi
is_install_whois
for d in aaa.com bbb.com aaa.cn
do
notify $d
done
实例 :
在输入栏里面输入”whois.chinaz.com“ ,查看某个域名的具体信息。
安装查看域名的whois命令软件包,
安装YUM之后,然后就可以安装了
查看aminglinux.com域名的具体信息。
查询百度的域名的过期时间。
只打印出过期的时间
执行脚本,查看结果
注意 :
which whois >/dev/null 2>/dev/null #检测whois软件包
e_d=`whois $1|grep 'Expiry Date'|awk '{print $4}'|cut -d 'T' -f 1` #获取域名的过期的详细信息,
e_d=`whois $1|grep 'Expiration'|tail -1 |awk '{print $5}' |awk -F 'T' '{print $1}'` #只打印出过期的时间
e_t1=$[$e_t-$n] #$e_t是过期时间,$n表示一周,$e_t-$n域名过期前的一周
e_t2=$[$e_t+$n] # $e_t+$n域名过期后的一周
if [ $t1 -ge $e_t ] && [ $t1 -lt $e_t2 ] #当前时间大于$e_t 域名的过期时间,并且,时间小于一周
e_d=`whois $1|grep 'Expiration Time'|awk '{print $3}'`
fi #只打印出过期的时间
if [ $t1 -ge $e_t1 ] && [ $t1 -lt $e_t ] #如果当前日期不是大于等于$e_t1的过期前的一周,并且,当前日期小于一周后的时间,表示域名过期时间不到一周了。 不到一周就过期或者过期了不到一周,就发邮件。
90、题目要求 : 自动密钥认证
写一个shell脚本,当我们执行时,提示要输入对方的ip和root密码,然后可以自动把本机的公钥增加到对方机器上,从而实现密钥认证。
【核心要点】
expect #分发脚本命令
ssh-copy-id #公钥
参考答案
#!/bin/bash
#这个脚本用来自动配置密钥认证
#作者:猿课-阿铭 www.apelearn.com
#日期:2018-12-14
read -p "输入一个IP地址: " ip
read -p "输入此机器的root密码: " pasd
is_install()
{
if ! rpm -q $1 &>/dev/null
then
yum installl -y $1
fi
}
is_install openssh-clients
is_install expect
if [ ! -f ~/.ssh/id_rsa.pub ]
then
echo -e "\n" |ssh-keygen -P ''
fi
cat > key.expect <<EOF
#!/usr/bin/expect
set host [lindex \$argv 0]
set passwd [lindex \$argv 1]
spawn ssh-copy-id root@\$host
expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "\$passwd\r" }
}
expect eof
EOF
chmod a+x key.expect
./key.expect $ip $pasd
实例 :
查看机器是否安装远程登录的命令软件包和分发脚本的命令 : openssh-clients、expect
远程登录登录B机器
查看本机密钥 : cat ~/.ssh/id_rsa.pub,ssh-copy-id root@1.1.1.1把本机的公钥增加到对方机器上,然后输入密码就行了。秘钥拷贝到129机器上拷贝成功,129机器上要拷贝到秘钥的目录 :~/.ssh/authorized_keys
查看本机器上的秘钥
写一个分发脚本1.expect ,使用分发脚本登录 B机器,然后输入IP地址和密码。
查看公钥
查看秘钥存放的目录
查看生成的秘钥
执行脚本,查看结果
注意 :
if ! rpm -q $1 &>/dev/null #查看命令是否运行openssh-clients、expect,如果没有,就安装。
if [ ! -f ~/.ssh/id_rsa.pub ] #查看本地家目录有没有秘钥id_rsa.pub,如果没有,就生成。
写入一个分发脚本,下面是内容
set host [lindex \$argv 0]
set passwd [lindex \$argv 1]
spawn ssh-copy-id root@\$host
来源 : https://github.com/aminglinux/shell100/blob/master/61.md