• Linux shell脚本



    本文出自 Linux运维日志,转载时请注明出处及相应链接。

    本文永久链接: https://www.centos.bz/2012/07/shell-script-exercises/

    Q1

    分析图片服务日志,把日志(每个图片访问次数*图片大小的总和)排行,也就是计算每个url的总访问大小
    说明:本题生产环境应用:这个功能可以用于IDC网站流量带宽很高,然后通过分析服务器日志哪些元素占用流量过大,进而进行优化或裁剪该图片,压缩js等措施。
    测试数据
    59.33.26.105 – – [08/Dec/2010:15:43:56 +0800] “GET /static/images/photos/2.jpg HTTP/1.1” 200 11299
    本题需要输出三个指标: 【被访问次数】 【访问次数*单个被访问文件大小】 【文件名(带URL)】
    查看答案

    Q2

    计算出1+2+3+..+100的结果。可以使用多种方法解答。
    查看答案

    Q3

    分析网站日志,找出在一分钟内打开网页超过60次的ip(排除图片,js和css等静态元素),并用iptables禁止其访问。加入crontab使脚本每分钟执行一次。
    查看答案

    Q4

    teamlist.txt的内容为:

    1. Name,Team,First Test, Second Test, Third Test
    2. Tom,Red,5,17,22
    3. Joe,Green,3,14,22
    4. Maria,Blue,6,18,21
    5. Fred,Blue,2,15,23
    6. Carlos,Red,-1,15,24
    7. Phuong,Green,7,19,21
    8. Enrique,Green,3,16,20
    9. Nancy,Red,9,12,24

    编写一个awk脚本用来计算每个人的平均成绩,每次测试的平均成绩和每组队的平均成绩。如果某次成绩为负数,则表示此人错过了测试,那计算平均成绩时排除此人再计算。
    输出的结果如下表,在名字的列表中,名字是10个宽度且左对齐(提示printf中使用%-10s格式),而平均值是7个字符宽度,右边两个右对齐的小数。

    1. Name       Average
    2. ----       -------
    3. Tom          14.67
    4. Joe          13.00
    5. Maria        15.00
    6. Fred         13.33
    7. Carlos       19.50
    8. Phuong       15.67
    9. Enrique      13.00
    10. Nancy        15.00
    11. ------------------
    12. Average for Test 1 : 5
    13. Average for Test 2 : 15.75
    14. Average for Test 3 : 22.125
    15. -------------------
    16. Average for Red Team: 16
    17. Average for Blue Team: 14.1667
    18. Average for Green Team: 13.8889

    查看答案

    Q5

    传入至少三个数字参数到脚本file,并计算出最大,最小,平均值。需要判断传入的数字是否足够,否则输出警告信息。平均值保留两位小数。
    如执行./file 3 4 6 5,输出结果如下:
    max number is:6
    min number is:3
    average is:4.50
    查看答案

    Q6

    有一列数字如下:
    第1次:1
    第2次:2
    第3次:3
    第4次:5
    第5次:8
    第6次:13
    第7次:21
    第8次:34
    第9次:55
    第10次:89
    第11次:144
    写出100次的数是什么。
    查看答案

    Q7

    文件内容如下:
    123abc456
    456def123
    567abc789
    789def567
    要求输出:
    456ABC123
    123DEF456
    789ABC567
    567DEF789
    查看答案

    Q1答案

    1. awk '{url[$7]++;size[$7]+=$10}END{for (a in url) {print size[a]/1024"K",url[a],a}}' access.log

    解析:
    这里定义了两个数组url和size,数组url用来计算单个url被访问的次数,数组size则是统计单个url传输的总字节数。之后的for语句则是循环读取数组url的无素,即链接,然后相继打印出单个url传输总字节数,被访问次数及相应的链接。
    数据分析出来后,我们可以使用sort命令进行排序。

    Q2答案

    方法1:for…do…done 的数值处理

    1. sum=0
    2. for ((i=1;i<=100;i++))
    3. do
    4. ((sum+=$i))
    5. done

    方法2:for…do…done (固定回圈)

    1. sum=0
    2. for i in {1..100}
    3. do
    4. ((sum+=$i))
    5. done

    方法3:while do done (不定回圈)

    1. sum=0
    2. i=1
    3. while [[ $i -le 100 ]]
    4. do
    5. ((sum+=i))
    6. ((i++))
    7. done

    方法4:until do done (不定回圈)

    1. sum=0
    2. i=1
    3. until [[ $i -gt 100 ]]
    4. do
    5. ((sum+=i))
    6. ((i++))
    7. done

    方法5:构建1+2+3..再利用bc计算

    1. seq 100 | tr " " "+" | sed 's/+$/ /' | bc

    Q3答案

    1. now=`date +%H%M%S`
    2. ago=`date -d "1 minute ago" +%H%M%S`
    3. badip=`tail -n 10000 access.log | egrep -v ".(gif|jpg|jpeg|png|css|js)" | awk  '
    4. BEGIN{
    5. n='"$now"'
    6. a='"$ago"'
    7. FS="[ :]+"
    8. }
    9. {
    10. t=$5$6$7
    11. if (t>=a && t<=n) {
    12. num[$1]++
    13. }
    14. }
    15. END{
    16. for (ip in num){
    17. if (num[ip]>60){
    18. print ip
    19. }
    20. }
    21. }
    22. '`
    23. if [ ! -z "$badip" ];then
    24. for ip in $badip;
    25. do
    26. if test -z "`/sbin/iptables -nL | grep $ip`";then
    27. /sbin/iptables -I INPUT -s $ip -j DROP
    28. fi
    29. done
    30. fi

    解析:
    1、定义两个变量now和ago,分别为当前时间,一分钟前的时间,格式为%H%M%S。
    2、获取日志最后的一万行(可以根据自己的访问量修改),使用egrep排除图片等文件。
    3、在awk的BEGIN语句中调用第1步设置的两个变量。
    4、使用变量t,a,n判断并获取一分钟内的日志,并使用数组num统计ip出现的次数。
    5、在END语句中判断ip出现的次数是否超过60,如果超过则输出ip地址到变量badip。
    6、for循环获取变量badip中的每个ip,并加入iptables规则禁止访问。

    Q4答案

    1. awk -F, 'BEGIN{
    2. printf "%-10s %s ","Name","Average"
    3. printf "%-10s %s ","----","-------"
    4. }
    5. NR>1{
    6. sum=0
    7. n=0
    8. for (i=3;i<=5;i++){
    9. if ($i>0){
    10. n++
    11. sum=sum+$i
    12. testcount[i-2]++
    13. testtotal[i-2]+=$i
    14. teamcount[$2]++
    15. teamtotal[$2]+=$i
    16. }
    17. }
    18. printf "%-10s %7.2f ",$1,sum/n
    19. }
    20. END{
    21. print "------------------"
    22. for (j=1;j<=3;j++){
    23. print "Average for Test "j" : "testtotal[j]/testcount[j]
    24. }
    25. print "-------------------"
    26. for (t in teamcount){
    27. print "Average for "t" Team: "teamtotal[t]/teamcount[t]
    28. }
    29. }'  teamlist.txt

    解析:
    1、awk的BEGIN语句输出表的两个列名。
    2、NR>1表示只处理从第二行开始的数据
    3、sum=0,n=0,初始化三个测试总成绩和参加的次数。
    4、定义一个for循环,循环处理三次测试数据。
    5、判断成绩大于0才处理此次测试。
    6、为计算每个人的平均成绩,用变量n记录测试次数,变量sum累积三次的成绩,接着下面用printf格式化输出每个人的平均成绩;为计算三个测试中每次的平均成绩,以i-2作为索引(即第i-2次测试),数组testcount记录某次测试参加的人数,数组testtotal记录某次测试的总成绩;为计算每个组的平均成绩,以第二列组名作为索引,数组teamcount记录某组参加测试的人数,数组teamtotal记录某组的总成绩。
    7、在END语句中用两个for循环语句分别输出每次测试及每组测试的平均成绩。

    Q5答案

    方法一:利用awk命令计算

    1. if [ "$#" -lt 2 ];then
    2. echo "parameter must be at least 3."
    3. exit 1
    4. fi
    5. echo "$@" | awk '
    6. BEGIN{
    7. RS=" +"
    8. }
    9. {
    10. sum+=$0
    11. }
    12. NR==1 {
    13. max=$1;min=$1
    14. next
    15. }
    16. $1>max {
    17. max=$1
    18. }
    19. $1<min {
    20. min=$1
    21. }
    22. END{
    23. printf "max number is:%s ",max
    24. printf "min number is:%s ",min
    25. printf "average is:%.2f ",sum/NR
    26. }'

    解析:
    1、判断参数是否大于2个,否则退出脚本。
    2、管道传入所有参数到awk,并设置awk的RS为空格。
    3、sum+=$0,计算和。
    4、NR==1 {}把第一个参数先赋值到max和min,防止所有数字为负数时计算错误。
    5、$1>max{}判断数字是否比变量max目前的数大,如果是,则把$1赋值到max,这样变量就可以时刻保持最大值状态。
    6、$1

    1. n=$#
    2. if [ "$n" -lt 2 ];then
    3. echo "parameter must be at least 3."
    4. exit 1
    5. fi
    6. max=$1
    7. min=$1
    8. sum=$1
    9. shift
    10. while [ $# -gt 0 ]
    11. do
    12. ((sum+=$1))
    13. [ $1 -gt $max ] && max=$1
    14. [ $1 -lt $min ] && min=$1
    15. shift
    16. done
    17. echo "max number is:"$max
    18. echo "min number is:"$min
    19. ave=`echo "scale=2;$sum / $n" | bc`
    20. echo "average is:"$ave

    解析:
    1、把参数个数赋值到变量n
    2、判断参数个数
    3、把第一个数字赋值到max,min,sum变量,并用shift命令使参数向左移,即之前的$2变为$1,且变量$#减1。
    4、while结合shift命令依次读取各参数,并在里面判断最大最小值。
    5、echo输出最大最小值,bc计算平均值,定义scale=2以保留两位小数。

    Q6答案

    1. a[1]=1
    2. a[2]=2
    3. i=3
    4. while [ $i -le 100 ]
    5. do
    6. ((a[$i]=${a[$i-1]}+${a[$i-2]}))
    7. ((i++))
    8. done
    9. echo ${a[100]}

    Q7答案

    1. sed  's/([0-9]*)([a-z]*)([0-9]*)/3U2E1/' file

    解析:
    1、([0-9]*)匹配连续的数字,([a-z]*)匹配连续的小写字母。
    2、123表示引用之前的括号内容,U2E表示把2的字母转换为大写字母。


  • 相关阅读:
    VC++用Recordset MSPersist载入C#DataSet Save出来的xml失败,但载入VC Recordset Save出来的xml则没问题,怎么xml不通用呢?
    观察力、分析问题的能力、与人沟通的能力和资源整合能力
    [导入]有感于神童之神源
    军训系列二:两类人创业不容易成功
    运行微软的SOAP3.0的VC样例Samples30_ADOTM_Client报错,m_pSoapClient>Invoke时直接失败
    About IM software
    [导入][转]好企业是什么样?
    动网论坛v7.0.0SQL版竟然帯病毒!
    CZoneSoft出品: 音频视频在线录制系列之 AV留言本 简介
    递归算法在生成树型结构中,几乎完全属于无稽的算法
  • 原文地址:https://www.cnblogs.com/xmanblue/p/5033478.html
Copyright © 2020-2023  润新知