余苏明的幻想乡

第八 面试题实战 二

#第八 面试题实战 二
@(shell脚本)[学习]

[toc]

前言

本章内容来自《跟老男孩学Linux运维:Shell编程实战》第19章内容第二部分

面试题12:Web及MySQL服务异常监测

面试题13:监控Memcached缓存服务

问题分析

使用nc命令加上set/get来模拟监测

面试题14:开发脚本实现入侵检测与报警

问题分析

  1. 思考过程的积累比实际代码开发能力积累更重要
  2. 什么是恶意篡改,只要是为经过许可的改动都是篡改
  3. 文件内容被改动会有如下特征
    • 大小可能会改变
    • 修改时间会改变
    • 文件内容会改变,利用md5sum指纹校验
    • 增加或删除文件,比对每次检查前后的文件数量

第一步,建立基础指纹库

1
find /var/html/www -type f|xargs md5sum > /opt/zhiwen.db.ori

第二步,建立基础文件库

1
find /var/html/www -type f >/opt/wenjian.db.ori

第三步,比较文件内容和文件数量变化

1
2
3
4
5
md5sum -c --quiet /opt/zhiwen.db.ori
#获取检测前的所有文件数量及文件名
find /var/html/www -type f > /opt/wenjian.db_curr.ori
#比较新旧文件数量
diff /opt/wenjian.db*

脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/bin/bash
RETVAL=0
export LANG=en
CHECK_DIR=/var/html/www
[ -e $CHECK_DIR ] ||exit 1
ZhiWenDbOri="/opt/zhiwen.db.ori"
FileCountDbOri="/opt/wenjian.db.ori"
FileCountDbCurrOri="/opt/wenjian.db_Curr.ori"
ErrLog="/opt/err.log"
[ -e $ZhiWenDbOri ]|| exit 1
[ -e $FileCountDbOri ] || exit 1
#jude file content
echo "md5sum -c --quiet $ZhiWenDbOri ">$ErrLog
md5sum -c --quiet $ZhiWenDbOri &>>$ErrLog
RETVAL=$?
#com file count
find $CHECK_DIR -type f > $FileCountDbCurrOri
echo "diff $FileCountDbCurrOri $FileCountDbOri" &>>$ErrLog
diff $FileCountDbCurrOri $FileCountDbOri &>>$ErrLog
ErroCount=`diff $FileCountDbCurrOri $FileCountDbOri|wc -l`
if [ $RETVAL -ne 0 -o $ErroCount -ne 0]
then
mail -s "`uname -n $(date +%F) err`" 31333741-@qq.com <$ErrLog
fi

然后可以加入定时任务

面试题15:开发Rsync服务启动脚本

问题分析

  1. 要使用系统函数库技巧
  2. 要用函数
  3. 可被chkconfig管理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/bin/bash
# chkconfig: 2345 20 80
# description: Rsyncd Startup scripts by oldboy.
if [ $# -ne 1 ]
then
echo $"usage:$0 {start|stop|restart}"
exit 1
fi
if [ "$1" = "start" ]
then
rsync --daemon
sleep 2
if [ `netstat -lntup|grep rsync|wc -l` -gt 1 ]
then
echo "rsyncd is started."
exit 0
fi
elif [ "$1" = "stop" ]
then
killall rsync &>/dev/null
sleep 2
if [ `netstat -lntup|grep rsync|wc -l` -eq 0 ]
then
echo "rsyncd is stopped"
exit 0
fi
elif [ "$1" = "restart" ]
then
killall rsync
sleep 2
killpro=`netstat -lntup|grep rsync|wc -l`
rsync --daemon
sleep 2
startpro=`netstat -lntup|grep rsync|wc -l`
if [ $killpro -eq 0 -a $startpro -ge 1 ]
then
echo "rsyncd is restarted"
exit 0
fi
else
echo $"usage:$0 {start|stop|restart}"
exit 1
fi

面试题16:开发MySQL多实例启动脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#!/bin/bash
###################
#this scripts is created by oldboy at 2007-06-09
#blog:http://oldboy.blog.51cto.com
###################
#init
Port=3306
MysqlUser="root"
MysqlPass="oldboy123"
CmdPath="/appliction/mysql/bin"
#startup function
start()
{
if [ `netstat -lnt|grep "$Port"|wc -l` -eq 0 ]
then
printf "Starting MySQL...\n"
/bin/sh ${CmdPath}/mysqld_safe --defaults-file=/data/${Port}/my.cnf 2>&1 > /dev/null &
else
printf "MySQL is running...\n"
fi
}
#stop function
stop()
{
if [ `netstat -lnt|grep "$Port"|wc -l` -eq 0 ]
then
printf "Stoping MySQL...\n"
${CmdPath}/mysqladmin -u ${MysqlUser} -p${MysqlPass} -S /data/${Port}/mysql.sock shutdown
else
printf "MySQL is stopped...\n"
fi
}
#restart function
restart()
{
printf "Restarting MySQL...\n"
stop
sleep 2
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
*)
printf "Usage: $0 {start|stop|restart}\n"
esac

面试题21:开发脚本管理服务端LVS

在LVS负载均衡主节点上,开发管理LVS服务的脚本ip_vs

问题分析

利用ipvsadm可以启动并配置好LVS服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#!/bin/bash
# Written by oldboy
# QQ:31333741
# description: Config Director vip and ipvs
. /etc/init.d/functions
VIP=10.0.0.3
INTERFACE=eth0
SubINTERFACE=${INTERFACE}:`echo $VIP|cut -d. -f4`
PORT=80
GW=10.0.0.254
RETVER=0
IP=/sbin/ip
ROUTE=/sbin/route
IPVSADM=/sbin/ipvsadm
ARPING=/sbin/arping
RIPS=( #<==定义realserver节点IP数组
10.0.0.7
10.0.0.8
)
function usage (){
echo "Usgae : $0 {start|stop|restart}"
return 1
}
function ipvsStart(){ #<==配置ipvs
$IP addr add $VIP/24 dev ${INTERFACE} label $SubINTERFACE #<==添加VIP。
$ROUTE add -host $VIP $SubINTERFACE #<==添加VIP对应主机路由
$IPVSADM -C
$IPVSADM -A -t $VIP:$PORT -s wrr -p 60 #<==生成ipvs实例
for ((i=0; i<`echo ${\#RIPS[*]}`;i++))
do
$IPVSADM -a -t $VIP:$PORT -r ${RIPS[$i]}:$PORT -g -w 1
#<==添加节点
done
RETVAR=$?
# update MAC
$ARPING -c 1 -I ${INTERFACE} -s $VIP $GW &>/dev/null
if [ $RETVAR -eq 0 ]
then
action "Ipvsadm started." /bin/true
else
action "Ipvsadm stopped." /bin/false
fi
return $RETVAR
}
main ()
{
#judge argv num
if [ $\# -ne 1 ]; then
usage $0
fi
case "$1" in
start)
ipvsStart
;;
stop)
ipvsStop
;;
restart)
ipvsStop
ipvsStart
;;
*)
usage $0
;;
esac
}
#start operating
main $*

面试题 22:LVS节点健康检查及管理脚本

模拟keepalived健康检查功能管理LVS节点,当节点挂掉时从服务器池中将其剔除,好了后再将其加入到服务器池中来.

问题分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/bin/bash
#created by oldboy 201308
IPVSADM=/sbin/ipvsadm
VIP=10.0.0.3
PORT=80
RIPS=(
10.0.0.7
10.0.0.8
)
while true
do
for((i=0;i<${\#RIPS[*]};i++))
do
PORT_COUNT=`nmap ${RIPS[$i]} -p $PORT|grep open|wc -l`
if [ $PORT_COUNT -ne 1 ];then
if [ `$IPVSADM -Ln|grep ${RIPS[$i]}|wc -l` -ne 0 ];then
$IPVSADM -d -t $VIP:$PORT -r ${RIPS[$i]}:$PORT >/dev/null 2>&1
fi
else
if [ `$IPVSADM -Ln|grep ${RIPS[$i]}|wc -l` -eq 0 ];then
$IPVSADM -a -t $VIP:$PORT -r ${RIPS[$I]}:$PORT >/dev/null 2>&1
fi
fi
done
sleep 5
done

面试题 23: LVS客户端配置脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/bin/bash
# Written by oldboy
# description: Config realserver lo and apply noarp
RETVAR=0
VIP=(
10.0.0.3
10.0.0.4
)
. /etc/init.d/functions
case "$1" in
start)
for ((i=0;i<`echo ${\#VIP[*]}`;i++))
do
interface="lo:`echo ${VIP[$i]}|awk -F . '{print $4}'`"
/sbin/ip addr add ${VIP[$i]}/24 dev lo label $interface
REVTAR=$?
done
echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
if [ $RETVAR -eq 0 ];then
action "Start LVS Config of RearServer." /bin/true
else
action "Start LVS Config of RearServer." /bin/false
fi
;;
stop)
for ((i=0;i<`echo ${\#VIP[*]}`;i++))
do
interface="lo:`echo ${VIP[$i]}|awk -F . '{print $4}'`"
/sbin/ip addr del ${VIP[$i]}/24 dev lo label $interface > /dev/null 2>&1
done
echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce
echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce
if [ $RETVAR -eq 0 ];then
action "Close LVS Config of RearServer." /bin/true
else
action "Close LVS Config of RearServer." /bin/false
fi
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
esac
exit $RETVAR

面试题24 : 模拟Keepalived软件高可用

在LVS服务端备用节点上,模拟keepalived vrrp功能,监听主节点,如果主节点不可访问,则启动备节点并配置LVS服务,接管主节点的资源并对用户提供服务(注意ARP缓存)

问题分析

  1. 监测主节点是否宕机,可以使用ping或nmap命令
  2. 如果主节点宕机,则调用管理LVS的服务脚本,执行LVS配置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #!/bin/bash
    # Author:oldboy training
    # Blog:http://oldboy.blog.51cto.com
    VIP=10.0.0.3
    PORT=80
    ipvs_tools=`rpm -qa ipvsadm|wc -l`
    if [ $ipvs_tools -ne 1 ]
    then
    yum install ipvsadm -y
    fi
    while true
    do
    ping -w2 -c2 ${VIP} >/dev/null 2>&1
    if [ $? -ne 0 ];then
    /bin/sh ./19_21_1.sh start >/dev/null 2>&1
    else
    /bin/sh ./19_21_1.sh stop >/dev/null 2>&1
    fi
    sleep 5
    done

面试题 26:编写等腰三角形图形字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
read -p "Please Enter a number:" Line
for ((i=1;i<=Line;i++))
do
for ((j=$Line-$i;j>0;j--));
do
echo -n ' '
done
for ((h=1;h<=$((2*$i-1));h++))
do
echo -n '*'
done
echo
done

面试题29 Nginx 负载节点状态监测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/bin/bash
RIPS=(
10.0.0.7
10.0.0.8
)
file_location=/var/html/test.html
[ -e "$file_location" ]|| mkdir `dirname $file_location` -p
function web_result {
rs=`curl -I -s $1|awk 'NR==1{print $2}'`
return $rs
}
function new_row {
cat >> $file_location <<eof
<tr>
<td bgcolor="$4">$1</td>
<td bgcolor="$4">$2</td>
<td bgcolor="$4">$3</td>
</tr>
eof
}
function auto_html {
web_result $2
rs=$?
if [ $rs -eq 200 ]
then
new_row $1 $2 up green
else
new_row $1 $2 down red
fi
}
function main(){
while true
do
cat >> $file_location <<eof
<h4>Oldboy Nginx Service Status Of RS :</h4>
<meta http-equiv="refresh" content="1">
<table border="1">
<tr>
<th>NO:</th>
<th>IP:</th>
<th>Status:</th>
</tr>
eof
for ((i=0;i<${\#RIPS[*]};i++));do
auto_html $i ${RIPS[$i]}
done
cat >> $file_location <<eof
</table>
eof
sleep 2
> $file_location
done
}
main $*