shell是运维人员应该具备的基本技能一,熟练掌握及运用shell,对提升运维作业效率与质量有很大帮助。在这里,将会结合工作中各种场景,利用shell脚本解决问题,完成目标。
实用案例(一)
监控MySQL主从同步是否异常,如果异常,则发送短信或者邮件给管理员。
a. 开发一个守护进程脚本每30秒实现检测一次。
b. 如果同步出现如下错误号(1158,1159,1008,1007,1062),则跳过错误。
c. 请使用数组技术实现上述脚本(获取主从判断及错误号部分)。#!/bin/bash mysqlbin=/usr/bin/mysql mysqlhost=127.0.0.1 mysqluser=root mysqlpwd=root skiperrors=(1158 1159 1008 1007 1062) admin='[email protected]' check() { LASTNO=$($mysqlbin -h$mysqluser -u$mysqluser -p$mysqlpwd -e "show slave status\G"|grep Last_Errno|awk -F: '{print $2}') } skip() { for errorno in ${skiperrors[@]};do if [ $errorno == $LASTNO ];then notify $errorno break fi done } notify() { text="mysql slave monitor error: $1" echo $text|mail -s 'mysql error' } main() { while :;do check && skip || notify "mysql connected failed!" sleep 30 done } main
使用for循环在目录下通过随机小写10个字母加固定字符串file批量创建10个。
#!/bin/bash gen_num() { local n min=$1 max=$2 n=$(($RANDOM+1000000000)) echo $(($n%$max+$min)) } gen_randletters() { local l local n #raw=(a b c d e f g h i g k l m n o p q r s t u v w x y z) raw=({a..z}) l=$1 for ((i=1;i<=$l;i++));do n=$(gen_num 0 26) letters+=${raw[$n]} done echo $letters } gen_randnames() { suffix=_file local l local n n=$1 l=$2 for ((i=1;i<=$n;i++));do touch $(gen_randletters $l)$suffix done } gen_randnames $1 $2
用for循环将以上文件名中的file批量改为files。
#!/bin/bash # 方法一 example_1() { for file in `ls *_file`;do newfile=$(echo $file|sed "s/\(.*_\)file/\1FILES/") mv $file $newfile done } example_1 # 方法二 example_2() { for file in `ls *_file`;do rename file FILES *_file done } example_2
写一个脚本,实现判断10.0.0.0/24网络里,当前在线用户的IP有哪些(方法有很多)。
#!/bin/bash subnet=10.0.0.0/24 # 方法一 netaddr=`echo $subnet|cut -d. -f1-3` for i in {1..254};do { ping -c 1 -t 1 $netaddr.$i > /dev/null if [ $? == 0 ];then echo $netaddr.$i fi } & done wait # 方法二 nmap -sP $subnet
写一个脚本解决DOS攻击生产案例。根据web日志或者或者网络连接数,监控当某个IP并发连接数或者短时内PV达到100,即调用防火墙命令封掉对应的IP,监控频率每隔3分钟。
#!/bin/bash ips_file=/tmp/pv_ge_100 n=1 netstat -an| \ awk '/tcp|udp/{print $4}'| \ awk -F: '{print $1}'| \ awk '{s[$1]++} END {for (i in s) if (s[i]>'"$n"') print i}' | \ grep -Ev '127.0.0.1|0.0.0.0' \ > $ips_file cat $ips_file | while read LINE;do iptables -A INPUT -s $LINE -j drop done
请用至少两种方法实现:bash for循环打印下面这句话中字母数不大于6的单词。
I am oldboy teacher welcome to oldboy training class.#!/bin/bash len=6 words='I am oldboy teacher welcome to oldboy training class.' # 方法一 for word in ${words[@]};do l=$(echo $word|wc -c) if [ $l -gt $len ];then echo $word;fi done # 方法二 for word in ${words[@]};do l=$(echo $word|awk '{print length($0)}') if [ $l -gt $len ];then echo $word;fi done
开发shell脚本分别实现以脚本传参以及read读入的方式比较2个整数大小。以屏幕输出的方式提醒用户比较结果。需要对变量是否为数字、并且传参个数做判断。
#!/bin/bash # read读参 IFS=',' compare() { n1=$1 n2=$2 if [ $n1 -ge $n2 ];then [ $n1 -eq $n2 ] && echo "$n1 = $n2" || echo "$n1 > $n2" else echo "$n1 < $n2" fi } isnum() { num=$1 for n in ${num[@]};do if [[ ! $n =~ ^[0-9]+$ ]];then echo 'WARNING: 必须输入整数!' return 1 fi done } while :;do read -a num -p "请输入2个整数(逗号分隔): " if [ ${#num[@]} -ne 2 ];then echo 'WARNING: 必须输入2个整数!' continue fi isnum $num && compare ${num[@]} done #!/bin/bash # 脚本传参 compare() { n1=$1 n2=$2 if [ $n1 -ge $n2 ];then [ $n1 -eq $n2 ] && echo "$n1 = $n2" || echo "$n1 > $n2" else echo "$n1 < $n2" fi } isnum() { num=$1 for n in ${num[@]};do if [[ ! $n =~ ^[0-9]+$ ]];then echo 'WARNING: 必须输入整数!' exit 2 fi done } if [ $# -ne 2 ];then echo 'WARNING: 必须输入2个整数!' exit 1 fi isnum "$*" && compare $@
打印选择菜单,一键安装Web服务:
[root@scripts]# sh menu.sh
1.[install lamp]
2.[install lnmp]
3.[exit]pls input the num you want:
要求:
a. 当用户输入1时,输出“startinstalling lamp.”然后执行/server/scripts/lamp.sh,脚本内容输出”lamp is installed”后退出脚本;
b. 当用户输入2时,输出“startinstalling lnmp.” 然后执行/server/scripts/lnmp.sh输出”lnmp is installed”后退出脚本;
c. 当输入3时,退出当前菜单及脚本;
d. 当输入任何其它字符,给出提示“Input error”后退出脚本。
e. 要对执行的脚本进行相关条件判断,例如:脚本是否存在,是否可执行等。#!/bin/bash lamp_script=/server/scripts/lamp.sh lnmp_script=/server/scripts/lnmp.sh check_script() { if [ ! -f $1 ];then echo 'script file is not found.' exit 1 fi if [ ! -x $1 ];then echo 'script file is not executable.' exit 2 fi } lamp() { check_script $lamp_script echo 'startinstalling lamp' $lamp_script echo 'lamp is installed' } lnmp() { check_script $lnmp_script echo 'startinstalling lnmp' $lnmp_script echo 'lnmp is installed' } IFS=',' PS3='pls input the num you want:' options=("[install lamp]","[install lnmp]","[exit]") select opt in ${options[@]} do case $opt in *lamp*) lamp ;; *lnmp*) lanmp ;; *exit*) exit 0 ;; *) echo 'Input error';exit 3 ;; esac done
已知下面的字符串是通过RANDOM随机数变量md5sum|cut -c 1-8截取后的结果,请破解这些字符串对应的md5sum前的RANDOM对应数字?
21029299
00205d1c
a3da1677
1f6d12dd
890684b#!/bin/bash md5prefix="21029299|00205d1c|a3da1677|1f6d12dd|890684b" output=/tmp/md5sum for ((i=0;i<=32767;i++));do res=$(echo $i|md5sum|awk '{print $1}'|cut -c1-8) echo $i $res >>$output done grep -E $md5prefix $output
抓阄题目:某企业提供外出项目实践机会来了(本月中旬),但是,名额有限,队员限3人(班长带队)。
因此需要挑选学生,因此需要一个抓阄的程序,要求:
a. 执行脚本后,想去的同学输入英文名字全拼,产生随机数01-99之间的数字,数字越大就去参加项目实践,前面已经抓到的数字,下次不能在出现相同数字。
b. 第一个输入名字后,屏幕输出信息,并将名字和数字记录到文件里,程序不能退出继续等待别的学生输入。#!/bin/bash output=/tmp/result rand_num() { min=$1 max=$2 echo $(($RANDOM%$max+$min)) } touch $output while :;do read -p '输出名字全拼: ' name while :;do r=$(rand_num 1 99) count=$(grep -w -c $r $output) if [ $count -eq 0 ];then echo $name:$r|tee -a $output break fi done done