shell脚本案例(一):常见运维面试题

shell是运维人员应该具备的基本技能一,熟练掌握及运用shell,对提升运维作业效率与质量有很大帮助。在这里,将会结合工作中各种场景,利用shell脚本解决问题,完成目标。


  1. 监控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
  2. 使用for循环在目录下通过随机小写10个字母加固定字符串file批量创建10个。

    
    #!/bin/bash
    
    
    gen_num() {
    local n
    min=$1
    max=$(($2-$min+1))
    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
  3. 用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
  4. 写一个脚本,实现判断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
  5. 写一个脚本解决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
  6. 请用至少两种方法实现: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
  7. 开发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 $@
  8. 打印选择菜单,一键安装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
  9. 已知下面的字符串是通过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
  10. 抓阄题目:某企业提供外出项目实践机会来了(本月中旬),但是,名额有限,队员限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

你可能感兴趣的:(shell)