兄弟连 企业shell笔试题 16-31
企业实践题16:
企业案例:写网络服务独立进程模式下rsync的系统启动脚本
例如:/etc/init.d/rsyncd{start|stop|restart} 。
要求:
1.要使用系统函数库技巧。
2.要用函数,不能一坨SHI的方式。
3.可被chkconfig管理。
脚本1:自己写的
#!/bin/bash
pidfile="/var/run/rsyncd.pid"
result=`ps aux|grep 'rsync --daemon --config=*'|grep -v grep`
Rstatus(){
if [ "$result"X = X ];then
echo "rsyncd is not running !"
else
echo "rsyncd is running"
fi
}
Rstart(){
if [ "$result"X == X ];then
/usr/bin/rsync --daemon --config=/etc/rsyncd/rsyncd.conf
echo "rsync service start.......OK"
else
echo "rsyncd is running"
fi
}
Rstop(){
if [ "$result"X == X ];then
echo "rsync service is down !"
exit 1
else
kill -9 $(cat $pidfile)
Rstatus2=`ps aux|grep 'rsync --daemon --config=*'|grep -v grep`
if [ "$Rstatus2"X = X ];then
rm -f $pidfile
echo "rsync service stop.......OK"
fi
fi
}
Rrestart(){
if [ "$result"X != X ];then
Rstop
/usr/bin/rsync --daemon --config=/etc/rsyncd/rsyncd.conf
echo "rsync service start.......OK"
else
echo "rsync service is down !"
fi
}
case $1 in
"start" )
Rstart
;;
"stop" )
Rstop
;;
"restart" )
Rrestart
;;
"status" )
Rstatus
;;
* )
echo "argument is start|stop|status|restart"
;;
esac
脚本2:网上找的
#!/bin/bash #this script for start|stop rsync daemon service status1=$(ps -ef | egrep "rsync --daemon.*rsyncd.conf" | grep -v 'grep') pidfile="/var/run/rsyncd.pid" start_rsync="rsync --daemon --config=/etc/rsyncd/rsyncd.conf" #start rsync function rsyncstart() { if [ "${status1}X" == "X" ];then rm -f $pidfile ${start_rsync} status2=$(ps -ef | egrep "rsync --daemon.*rsyncd.conf" | grep -v 'grep') if [ "${status2}X" != "X" ];then echo "rsync service start.......OK" fi else echo "rsync service is running !" fi } #stop rsync function rsyncstop() { if [ "${status1}X" != "X" ];then kill -9 $(cat $pidfile) #读取并结束 进程 pid号 status2=$(ps -ef | egrep "rsync --daemon.*rsyncd.conf" | grep -v 'grep') if [ "${statusw2}X" == "X" ];then echo "rsync service stop.......OK" fi else echo "rsync service is not running !" fi } #status function rsyncstatus() { if [ "${status1}X" != "X" ];then echo "rsync service is running !" else echo "rsync service is not running !" fi } #restart function rsyncrestart() { if [ "${status1}X" == "X" ];then echo "rsync service is not running..." rsyncstart else rsyncstop rsyncstart fi } case $1 in "start") rsyncstart ;; "stop") rsyncstop ;; "status") rsyncstatus ;; "restart") rsyncrestart ;; *) echo echo "Usage: $0 start|stop|restart|status" echo esac
企业实践题17:
需要一个抓阄的程序:
要求:
1、执行脚本后,想去的同学输入英文名字全拼,产生随机数01-99之间的数字,数字越大就去参加项目实践,前面已经抓到的数字,下次不能在出现相同数字。
2、第一个输入名字后,屏幕输出信息,并将名字和数字记录到文件里,程序不能退出继续等待别的学生输入。
重点语句分析:
产生01-99随机数
我开始使用的是 echo $RANDOM | head -c 2 这个语句只能产生 10-99
修改后为 echo $(($RANDOM%100))
用嵌套的两个while 来完成接收用户名和 生成数字-判断数字重重功能
#!/bin/bash
namelist=/tmp/name.txt
#判断数字是否重复
judgeNum(){
grep -w $1 $namelist
if [ "$?" -eq 0 ];then
a=1
else
a=0
fi
}
while read -p "please input your name:" name
do
a=1
while [ $a -eq 1 ] #数字不重复就跳出第二个while ,重复就再生成一个
do
num=`echo $(($RANDOM%100+1))`
judgeNum $num
done
echo "$name:$num" | tee -a $namelist #结果显示到屏幕 并 追加到文件中
done
企业实践题18:
已知下面的字符串是通过RANDOM随机数变量md5sum|cut-c 1-8截取后的结果,请破解这些字符串对应的md5sum前的RANDOM对应数字?
21029299
00205d1c
a3da1677
1f6d12dd
890684b
重点语句分析:
我直接用 爆破法了
查看一个变量是否包含在 数组内两个方法
1. if [[ ${array[*]} =~ $variable ]]
2. echo ${array[*]} | grep -w "xxx"
#!/bin/bash array=(21029299 00205d1c a3da1677 1f6d12dd 890684ba) count=0 for i in `seq 0 32767` do variable=`echo $i | md5sum | cut -c 1-8` if [[ ${array[*]} =~ $variable ]];then let count++ echo "$count: $i ==>> $variable" fi [ $count -eq 5 ] && exit done
运行结果
# bash 18old.sh
1: 1346 ==>> 00205d1c
2: 7041 ==>> 1f6d12dd
3: 10082 ==>> 890684ba
4: 25345 ==>> a3da1677
5: 25667 ==>> 21029299
企业实践题19:
批量检查多个网站地址是否正常
要求:shell数组方法实现,检测策略尽量模拟用户访问思路
http://www.etiantian.org
http://www.taobao.com
http://oldboy.blog.51cto.com
http://10.0.0.7
重点语句分析:
验证网站的可行性两种方法
wget -T 5 -t 2 --spider
http_code=`curl -m 5 -s -o /dev/null -w %{http_code}
#!/bin/bash
[ -f /etc/init.d/functions ] && source /etc/init.d/functions
array=(
http://www.163.com
http://www.taobao.com
http://oldboy.blog.51cto.com
http://10.0.0.7
)
wait(){
echo -n "wait"
for((a=1;a<=3;a++))
do
echo -n "."
sleep 1
done
}
check_url(){
wget -T 5 -t 2 --spider $1 &>/dev/null
RETVAL=$?
if [ $RETVAL -eq 0 ];then
action "check $1" /bin/true
else
action "check $1" /bin/false
fi
return $RETVAL
}
main(){
for((i=0;i< ${#array[*]};i++))
do
wait
check_url ${array[i]}
done
}
main
运行结果:
# bash 19old.sh
wait...check http://www.163.com [ OK ]
wait...check http://www.taobao.com [FAILED]
wait...check http://oldboy.blog.51cto.com [ OK ]
wait...check http://10.0.0.7
淘宝访问失败是因为 ssl 验证
企业实践题20:
1、按单词出现频率降序排序!
2、按字母出现频率降序排序!
the squid project provides a number of resources toassist users design,implement and support squid installations. Please browsethe documentation and support sections for more infomation
重点语句分析:
单词排序 先把这一句话 按空格符 生成一个单词一行,然后再排序
1.使用for循环将这一变量(句话) 再用 sort uniq sort 排序
2.使用 sed 's/ /\n/g' | sort | uniq -c | sort -r
3.使用 tr ' ' '\n'|sort|uniq -c |sort -r
字母排序
将字符串变量while read 按行输入,然后截取cut -c 每一个字符 存入文件(一行一个字符)
sort进行排序统计
#!/bin/bash
a="the squid project provides a number of resources toassist users design,implement and support squid installations. Please browsethe documentation and support sections for more infomation"
word=/tmp/word.txt
word_sort(){
for i in `echo $a`
do
echo $i >> $word
done
cat $word|sort|uniq -c|sort -rn
}
letter_sort(){
echo $a |
while read line
do
for i in `seq 1 ${#line}`
do
echo $line |cut -c "$i" >> $word
done
done
cat $word |sort|uniq -c|sort -rn
}
main(){
[ -f $word ] && rm -f $word
echo "word sort input 1"
echo "letter sort input 2"
read num
case $num in
"1")
word_sort
;;
"2")
letter_sort
;;
*)
echo "please input 1 or 2"
esac
}
main
企业实践题21:
输出正方形、等腰三角形、直角梯形
1.输出正方形
这里使用+ 或者 ■ 这两种符号实现
加号的宽度应该乘以2 长宽才相等
#!/bin/bash
echo -n "please input a number:"
read a
let b=a*2
for((i=1;i<=$a;i++))
do
printf "%-"$b"s\n" "+"|sed 's/ /+/g'
done
其次使用两个for循环嵌套 来实现
#!/bin/bash
echo "input a number"
read num
let num2=num*2
for((a=1;a<="$num";a++))
do
echo -e "\n"
for((b=1;b<="$num2";b++))
do
echo -n +
done
done
2.输出直角梯形
#!/bin/bash
echo -n "please input a number:"
read a
for((i=1;i<=$a;i++))
do
printf "%-"$i"s\n" "+"|sed 's/ /+/g'
done
#!/bin/bash
echo "input a number"
read num
#let num2=num*2
for((a=1;a<="$num";a++))
do
echo -e "\n"
for((b=1;b<=a;b++))
do
echo -n "+"
done
done
3.输出等腰梯形
用四个for循环来构造,第一个for确定每一行,第二个for 打印每行前段空格,第三个for输出+,第四个for打印每行末尾空格
#!/bin/bash
echo "please a number"
read num
let sum=num*2+1
for((a=1;a<=num;a++))
do
for((b=1;b<=$[(sum-2*a-1)/2];b++))
do
echo -n " "
done
for((b=1;b<=$[2*a-1];b++))
do
echo -n "+"
done
for((b=1;b<=$[(sum-2*a-1)/2];b++))
do
echo -n " "
done
echo -e "\n"
done
企业实践题22:
开发通过web界面展示监控Nginx代理节点状态,效果图如下。
思路:
首先新建一个html页面(如上图),然后编写shell脚本检测机器状态,
检测结果直接修改html文件,up-》down。
我这里简单写了一个脚本:
#!/bin/bash
html_file=/var/www/html/status.html
array=(
192.168.0.104
)
check(){
array[0]=`netstat -anptl | grep "httpd"|wc -l`
}
output(){
if [ ${array[0]} -eq 0 ];then
echo '<td align="center" bgcolor="green"><font size="15">OK!</font></td>' > $html_file
elif [ ${array[0]} -eq 1 ];then
echo '<td align="center" bgcolor="green"><font size="15">OK!</font></td>' > $html_file
fi
}
while true
do
check
output
sleep 20
done
网上找到一个比较好的脚本
#!/bin/bash #Author: Stanley Wang #mail: #Version: 1.0 #Description: This is a script for nginx proxy health check. # ###def vars########## RS=( 172.16.1.191 172.16.1.192 ) PORT=80 html_file="/var/html/www/index.html" declare -a RSTATUS ###main############## function checkrs(){ local I=0 for ((I=0;I<${#RS[*]};I++)) do RSTATUS[$I]=`nmap ${RS[$I]} -p $PORT|grep "open"|wc -l` done } function output(){ if [ ${RSTATUS[0]} -eq 0 ];then #echo "${RS[$i]} is down!" sed -i '22 s/.*/<td align="center" bgcolor="red"><font size="15">Down!<\/font><\/td>/g' $html_file elif [ ${RSTATUS[0]} -eq 1 ];then #echo "${RS[$i]} is OK!" sed -i '22 s/.*/<td align="center" bgcolor="green"><font size="15">OK!<\/font><\/td>/g' $html_file fi if [ ${RSTATUS[1]} -eq 0 ];then #echo "${RS[$i]} is down!" sed -i '28 s/.*/<td align="center" bgcolor="red"><font size="15">Down!<\/font><\/td>/g' $html_file elif [ ${RSTATUS[1]} -eq 1 ];then #echo "${RS[$i]} is OK!" sed -i '28 s/.*/<td align="center" bgcolor="green"><font size="15">OK!<\/font><\/td>/g' $html_file fi } while true do checkrs output sleep 2 done
企业实践题23:
【LVS主节点】手工开发ipvsadm管理lvs的脚本ip_vs
实现:/etc/init.d/lvs {start|stop|restart}
说明为了简化脚本便于理解,这里使用LVS 中的 DR工作模式 + rr轮询模式 ,不使用keepalive
机器ip如下:
vip 10.0.0.90
Director server ip 10.0.0.54
Real server 10.0.0.56 10.0.0.57
#/bin/bash
[ $UID -ne 0 ] && echo "please use root run" && exit 22
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
vip=10.0.0.90
vip_netmask=10.0.0.90/24
RealServer=(
10.0.0.56
10.0.0.57
)
start(){
ip addr show|grep "$vip" &>/dev/null
#判断网卡上 vip 是否存在,不存在添加
if [ "$?" -ne 0 ];then
ip addr add "$vip_netmask" dev ens32
action "ip address add vip "$vip_netmask"" /bin/true
else
echo "ip address vip $vip_netmask already exists"
fi
#判断ipvsadm中 vip是否存在,不存在则添加
lvs_table=`ipvsadm -ln|grep "$vip"|wc -l`
if [ "$lvs_table" -eq 1 ];then
echo "ipvsadm vip already exist"
else
ipvsadm -A -t "$vip":80 -s rr
action "ipvsadm add vip $vip" /bin/true
fi
#判断ipvsadm中 real server是否存在,不存在则添加
for ip in ${RealServer[*]}
do
rs_num=`ipvsadm -ln | grep "$ip"|wc -l`
if [ $rs_num -eq 1 ];then
echo "real server $ip already exists"
else
ipvsadm -a -t "$vip":80 -r $ip -g
action "ipvsadm add real server $ip" /bin/true
fi
done
}
stop(){
ip addr show|grep $vip &>/dev/null
if [ "$?" -ne 0 ];then
echo "ip address vip $vip is not exist"
else
ip addr del $vip_netmask dev ens32
action "ip address delete vip $vip" /bin/true
fi
ipvsadm -C && action "clear all lvs table." /bin/true
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
sleep 2
start
;;
*)
echo "please input {start|stop|restart}"
esac
企业实践题24:
【LVS主节点】模拟keepalived健康检查功能管理LVS节点,
当节点挂掉(检测2次,间隔2秒)从服务器池中剔除,好了(检测2次,间隔2秒)加进来
提示:利用ipvsadm命令实现添加和减少LVS节点。
机器ip如下:
vip 10.0.0.90
Director server ip 10.0.0.54
Real server 10.0.0.56 10.0.0.57
说明:这道题目是 编写脚本 检查 Real server 服务器的状态,失效的则使用命令ipvsadm 踢出 ,状态恢复则用 ipvsadm 重新加入
使用两个函数 ,函数判断如下
status_del()函数
ipvsadm中是否存在 | 两次检测状态 | 操作 |
在 | ×× | 从ipvsadm中删除 |
在 | √× 或 √√ | echo running |
不在 | ×× | echo down |
status_add() 函数
ipvsadm 中不存在 两次检测状态√√ 向ipvsadm中添加这个real server ip
#!/bin/bash
[ $UID -ne 0 ] && echo "please use root run" && exit 22
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
#定义 vip 和real server ip
vip=10.0.0.90
vip_netmask=10.0.0.90/24
RealServer=(
10.0.0.56
10.0.0.57
)
status_del(){
for Rs_ip in ${RealServer[*]}
do
error=0 #定义检测失败次数
#进行两次检测
for((i=1;i<=2;i++))
do
x=` nmap -p 80 $Rs_ip | grep 'open' | wc -l`
if [ "$x" -eq 0 ];then
let error+=1
fi
sleep 2
done
#检查real主机ip 是否在 ipvsadm列表中
vs_ip=`ipvsadm -ln|grep $Rs_ip | wc -l`
#两次检测失败,而且real ip存在ipvsadm列表中,执行向ipvsadm中添加命令
if [ $error -eq 2 -a $vs_ip -ne 0 ];then
ipvsadm -d -t "$vip":80 -r "$Rs_ip":80
echo "Real server $Rs_ip is down,delete it"
#两次检测失败,而且不存在ipvsadm列表中,输出 down
elif [ $error -eq 2 -a $vs_ip -eq 0 ];then
echo "Real server $Rs_ip is down"
#检测失败次数为0或者1,列表中存在,输出 running
elif [ $error -ne 2 -a $vs_ip -ne 0 ];then
echo "Real server $Rs_ip is running"
fi
done
}
status_add(){
for Rs_ip in ${RealServer[*]}
do
bingo=0
for((i=1;i<=2;i++))
do
x=` nmap -p 80 $Rs_ip | grep 'open' | wc -l`
if [ "$x" -eq 1 ];then
let bingo+=1
fi
sleep 2
done
vs_ip=`ipvsadm -ln|grep $Rs_ip | wc -l`
#两次检测成功,real ip不在ipvsadm中,执行向ipvsadm 添加ip 命令
if [ $bingo -eq 2 -a $vs_ip -eq 0 ];then
ipvsadm -a -t "$vip":80 -r "$Rs_ip":80
echo "Real server $Rs_ip is recover,add it"
fi
done
}
main(){
while true
do
status_del
sleep 10
status_add
sleep 10
done
}
main
企业实践题25:
【LVS客户端节点】开发LVS客户端设置VIP以及抑制ARP的管理脚本
实现:/etc/init.d/lvsclient {start|stop|restart}
说明:在real server 上 实现脚本开关命令
机器ip如下:
vip 10.0.0.90
Director server ip 10.0.0.54
Real server 10.0.0.56 10.0.0.57
#!/bin/bash
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
vip=10.0.0.90
vip_netmask=10.0.0.90/32
RealServer=10.0.0.56
start(){
# lo网卡上没有vip 则添加
ip addr show|grep "$vip" &>/dev/null
if [ "$?" -ne 0 ];then
ip addr add "$vip_netmask" dev lo
fi
echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce
#检测lo是否添加上vip
ip addr show|grep "$vip" &>/dev/null
if [ "$?" -eq 0 ];then
action "ip address add vip $vip_netmask ,lvs_client start" /bin/true
else
action "can't add vip $vip_netmask " /bin/false
fi
}
stop(){
#lo网卡上有 vip 则删掉
ip addr show|grep "$vip" &>/dev/null
if [ "$?" -eq 0 ];then
ip addr del "$vip_netmask" dev lo
fi
echo "0" > /proc/sys/net/ipv4/conf/all/arp_ignore
echo "0" > /proc/sys/net/ipv4/conf/all/arp_announce
#检测删除结果
ip addr show|grep "$vip" &>/dev/null
if [ "$?" -ne 0 ];then
action "ip address del vip $vip_netmask ,lvs_client stop" /bin/true
else
action "can't del vip $vip_netmask " /bin/false
fi
}
case $1 in
start)
start
;;
stop)
stop
;;
restart)
stop
sleep 1
start
;;
*)
echo "USAGE: $0 {start|stop|restart|status}"
esac
企业实践题26:
【LVS备节点】模拟keepalved vrrp功能,监听主节点,如果主节点不可访问则备节点启动并配置LVS实现接管主节点的资源提供服务(提醒:注意ARP缓存)
说明:编写的这个脚本运行在LVS的 备用DS上,监听主节点 ,一旦主节点发生故障,立即接管(这里不考虑,主节点恢复后 主备的抢占问题),并退出监控
这里用到了 脚本23的 start() 函数
机器ip如下:
vip 10.0.0.90
Director server ip 10.0.0.54(主) 10.0.0.55(备)
Real server 10.0.0.56 10.0.0.57
#!/bin/bash
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
vip=10.0.0.90
RealServer=(10.0.0.56 10.0.0.57)
gateway=10.0.0.254
dev=ens32
start(){
ip addr show|grep "$vip" &>/dev/null
if [ "$?" -ne 0 ];then
ip addr add "$vip"/24 dev $dev
arping -I $dev -c 3 -s $vip $gateway &>/dev/null
action "ip address add vip "$vip"" /bin/true
else
echo "ip address vip $vip already exists"
fi
lvs_table=`ipvsadm -ln|grep "$vip"|wc -l`
if [ "$lvs_table" -eq 1 ];then
echo "ipvsadm vip already exist"
else
ipvsadm -A -t "$vip":80 -s rr
action "ipvsadm add vip $vip" /bin/true
fi
for ip in ${RealServer[*]}
do
rs_num=`ipvsadm -ln | grep "$ip"|wc -l`
if [ $rs_num -eq 1 ];then
echo "real server $ip already exists"
else
ipvsadm -a -t "$vip":80 -r $ip -g
action "ipvsadm add real server $ip" /bin/true
fi
done
echo "master is stop ,slave have running"
exit 10
}
check_lvs(){
ping -c 2 $vip &>/dev/null
RETVAL=$?
if [ $RETVAL -ne 0 ];then
start
else
echo 'lvs master is good'
fi
}
main(){
while true
do
check_lvs
sleep 10
done
}
main
企业实践题27:
请用shell或Python编写一个正方形(oldboy_square.sh),接收用户输入的数字。
此题与脚本21题 相同,略过
企业实践题28:
请用shell或Python编写一个等腰三角形(oldboy2_triangle.sh),接收用户输入的数字
此题与脚本21题 相同,略过
企业实践题29:
请用shell或Python编写一个等腰三角形(oldboy2_triangle.sh),接收用户输入的数字
此题与脚本21题 相同,略过