zoukankan      html  css  js  c++  java
  • Shell脚本1-20例

    1、每天生成一个文件

    描述:请按照这样的日期格式(xxxx-xx-xx)每日生成一个文件,例如今天生成的文件为)2017-07-05.log, 并且把磁盘的使用情况写到到这个文件中,(不用考虑cron,仅仅写脚本即可)

    参考答案

    d=`date +%F`
    logfile=$d.log
    file_path='/data/shell/log/'$logfile
    df -h >$file_path
    

      

    注:1)date  +%F中date与+之间存在空格

    2)其他创建路径/data/shell/log

    2、根据日志统计每个IP的访问量 

    描述: 将下述日志多次复制粘贴至02.log中,编写脚本,统计出每个IP的访问量有多少?

    112.111.12.248 – [25/Sep/2013:16:08:31 +0800]formula-x.haotui.com “/seccode.php?update=0.5593110133088248″ 200″http://formula-x.haotui.com/registerbbs.php” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;)”

    61.147.76.51 – [25/Sep/2013:16:08:31 +0800]xyzdiy.5d6d.com “/attachment.php?aid=4554&k=9ce51e2c376bc861603c7689d97c04a1&t=1334564048&fid=9&sid=zgohwYoLZq2qPW233ZIRsJiUeu22XqE8f49jY9mouRSoE71″ 301″http://xyzdiy.5d6d.com/thread-1435-1-23.html” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)”

    参考答案:

    awk ‘{print $1}’ 1.log |sort -n|uniq -c |sort -n

    3、统计内存

    描述:写一个脚本计算一下linux系统所有进程占用内存大小的和。(提示,使用ps或者top命令)

    上述字段说明:

    USER 进程的属主;
    PID   进程的ID;
    PPID    父进程;
    %CPU   进程占用的CPU百分比;
    %MEM  占用内存的百分比;
    NI        进程的NICE值,数值大,表示较少占用CPU时间;
    VSZ     該进程使用的虚拟內存量(KB);
    RSS     該進程占用的固定內存量(KB)(驻留中页的数量);
    TTY     該進程在那個終端上運行(登陸者的終端位置),若與終端無關,則顯示(?)。若為pts/0等,則表示由網絡連接主機進程
    WCHAN  當前進程是否正在進行,若為-表示正在進行;
    START   該進程被觸發启动时间;
    TIME      該进程實際使用CPU運行的时间;
    COMMAND   命令的名称和参数;


     参考答案:

    #! /bin/bash
    sum=0
    for i in `ps aux|awk '{print $6}'|grep -v RSS`
    do
    sum=$[$sum+$i]
    echo $i
    done
    echo "The total memory is $sum""k" 

    4、设计监控脚本

    描述:

    设计一个脚本,监控远程的一台机器(假设ip为123.23.11.21)的存活状态,当发现宕机时发一封邮件给你自己。

    提示:
    1. 你可以使用ping命令   ping -c10 123.23.11.21
    2. 发邮件脚本可以参考 https://coding.net/u/aminglinux/p/aminglinux-book/git/blob/master/D22Z/mail.py
    3. 脚本可以搞成死循环,每隔30s检测一次

    #!/bin/bash
    ip=10.1.1.1
    ma=xxxx@qq.boe.com.cn
    while ((1))
    do
            ping -c10 $ip >/dev/null 2>/dev/null
            if [ $? -ne 0 ] ;
            then
                    python /data/python/mail.py $ma "$ip is down" "$ip is down"
            fi
            sleep 1
    done

    注:while  ((1))等同于while [ 1 ]等同于 while true

    #!/usr/bin/env python
    #-*- coding: UTF-8 -*-
    import os,sys
    reload(sys)
    sys.setdefaultencoding('utf8')
    import getopt
    import smtplib
    from email.MIMEText import MIMEText
    from email.MIMEMultipart import MIMEMultipart
    from  subprocess import *
    
    def sendqqmail(username,password,mailfrom,mailto,subject,content):
        gserver = 'smtp.qq.com'
        gport = 25
    
        try:
            # msg = MIMEText(unicode(content).encode('utf-8')) //如果发送的邮件有乱码,可以尝试把这行改成如下:
            msg = MIMEText(content,'plan','utf-8') 
            msg['from'] = mailfrom
            msg['to'] = mailto
            msg['Reply-To'] = mailfrom
            msg['Subject'] = subject
    
            smtp = smtplib.SMTP(gserver, gport)
            smtp.set_debuglevel(0)
            smtp.ehlo()
            smtp.login(username,password)
    
            smtp.sendmail(mailfrom, mailto.split(','), msg.as_string())
            smtp.close()
        except Exception,err:
            print "Send mail failed. Error: %s" % err
    
    
    def main():
        to=sys.argv[1]
        subject=sys.argv[2]
        content=sys.argv[3]
    ##定义QQ邮箱的账号和密码,你需要修改成你自己的账号和密码(请不要把真实的用户名和密码放到网上公开,否则你会死的很惨)
        sendqqmail('1234567@qq.com','aaaaaaaaaa','1234567@qq.com',to,subject,content)
    
    if __name__ == "__main__":
        main()
        
        
    #####脚本使用说明######
    #1. 首先定义好脚本中的邮箱账号和密码
    #2. 脚本执行命令为:python mail.py 目标邮箱 "邮件主题" "邮件内容"
    

      

    5、批量更改文件名

     描述:

    1. 找到/123目录下所有后缀名为.txt的文件
    2. 批量修改.txt为.txt.bak
    3. 把所有.bak文件打包压缩为123.tar.gz
    4. 批量还原文件的名字,即把增加的.bak再删除

    参考答案

    #!/bin/bash
    #查找txt文件
    find /data/shell/123 -type f -name "*.txt" >/tmp/txt.list
    #批量修改文件名
    for f in `cat /tmp/txt.list`
    do
            mv $f $f.bak
    done
    #创建一个目录,避免目录存在,所以加了一个时间的后缀名
    d=`date +%Y%m%d%H%M%S`
    mkdir /tmp/123_$d
    pwd
    
    for f in `cat /tmp/txt.list`
    do
            echo "true"
            cp $f.bak /tmp/123_$d/
    done
    #打包压缩
    cd /tmp
    tar czf 123.tar.gz 123_$d/
    
    #还原
    for f in `cat /tmp/txt.list`
    do
    mv $f.bak $f
    done
    

      

    6、监控80端口

    描述:

    写一个脚本,判断本机的80端口(假如服务为httpd)是否开启着,如果开启着什么都不做,如果发现端口不存在,那么重启一下httpd服务,并发邮件通知你自己。脚本写好后,可以每一分钟执行一次,也可以写一个死循环的脚本,30s检测一次。

    #! /bin/bash
    mail=123@123.com
    if netstat -lnp |grep ‘:80’ |grep -q ‘LISTEN’; then
    exit
    else
    /usr/local/apache2/bin/apachectl restart >/dev/null 2> /dev/null
    python mail.py $mail “check_80” “The 80 port is down.”
    n=`ps aux |grep httpd|grep -cv grep`
    if [ $n -eq 0 ]; then
    /usr/local/apache2/bin/apachectl start 2>/tmp/apache_start.err
    fi
    if [ -s /tmp/apache_start.err ]; then
    python mail.py  $mail  ‘apache_start_error’   `cat /tmp/apache_start.err`
    fi
    fi
    

    相关知识:

    1)文件目录判断   [ -s FILE ] 如果 FILE 存在且大小非0时为真则返回为真。

    https://blog.csdn.net/jasonzeng/article/details/53286384 

    2)netstat

    常见参数:命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Memberships) 等等。

    -a (all)显示所有选项,默认不显示LISTEN相关
    -t (tcp)仅显示tcp相关选项
    -u (udp)仅显示udp相关选项
    -n 拒绝显示别名,能显示数字的全部转化成数字。
    -l 仅列出有在 Listen (监听) 的服務状态

    -p 显示建立相关链接的程序名
    -r 显示路由信息,路由表
    -e 显示扩展信息,例如uid等
    -s 按各个协议进行统计
    -c 每隔一个固定时间,执行该netstat命令。

    https://www.cnblogs.com/ggjucheng/archive/2012/01/08/2316661.html

    3)grep -q

    -q 参数,本意是 Quiet; do not write anything to standard output.  Exit immediately with zero status if any match is found, even if an error was detected.   中文意思为,安静模式,不打印任何标准输出。如果有匹配的内容则立即返回状态值0。

    7、备份数据库

    描述:

    设计一个shell脚本来备份数据库,首先在本地服务器上保存一份数据,然后再远程拷贝一份,本地保存一周的数据,远程保存一个月。

    假定,我们知道mysql root账号的密码,要备份的库为discuz,本地备份目录为/bak/mysql, 远程服务器ip为192.168.123.30,远程提供了一个rsync服务,备份的地址是 192.168.123.30::backup  . 写完脚本后,需要加入到cron中,每天凌晨3点执行。

    #! /bin/bash
    
    ### backup mysql data
    
    ### Writen by Aming.
    
    PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/mysql/bin
    
    d1=`data +%w`
    
    d2=`date +%d`
    
    pass=”your_mysql_password”
    
    bakdir=/bak/mysql
    
    r_bakdir=192.168.123.30::backup
    
    exec 1>/var/log/mysqlbak.log 2>/var/log/mysqlbak.log
    
    echo “mysql backup begin at `date +”%F %T”`.”
    
    mysqldump -uroot -p$pass –default-character-set=gbk discuz >$bakdir/$d1.sql
    
    rsync -az $bakdir/$d1.sql $r_bakdir/$d2.sql
    
    echo “mysql backup end at `date +”%F %T”`.”
    

      

    然后加入cron

    0 3 * * * /bin/bash /usr/local/sbin/mysqlbak.sh

    8、自动重启php-fpm服务

    描述:

    服务器上跑的是LNMP环境,近期总是有502现象。502为网站访问的状态码,200正常,502错误是nginx最为普通的错误状态码。由于502只是暂时的,并且只要一重启php-fpm服务则502消失,但不重启的话,则会一直持续很长时间。所以有必要写一个监控脚本,监控访问日志的状态码,一旦发生502,则自动重启一下php-fpm。

    我们设定:
    1. access_log  /data/log/access.log
    2. 脚本死循环,每10s检测一次(假设每10s钟的日志条数为300左右)
    3. 重启php-fpm的方法是  /etc/init.d/php-fpm restart

    参考答案

    #! /bin/bash
    
    log=/data/log/access.log
    
    N=10
    
    while :; do
    
    ##因为10秒钟大概产生300条日志
    
    tail -n 300 $log > /tmp/log
    
    n_502=`grep -c ‘ 502″‘ /tmp/log`
    
    if [ $n_502 -ge $N ]; then
    
    ##记录系统的状态
    
    top -bn1 >/tmp/`date +%H%M%S`-top.log
    
    vmstat 1 5 >/tmp/`date +%H%M%S`-vm.log
    
    /etc/init.d/php-fpm restart 2>/dev/null
    
    ##重启php-fpm服务后,应先暂缓1分钟,而后继续每隔10s检测一次
    
    sleep 60
    
    fi
    
    sleep 10
    
    done
    

      

    9、删除文本中的字母

    描述:

    把一个文本文档的前5行中包含字母的行删除掉,同时把6到10行中的全部字母删除掉。

     参考答案

    假设文本名字叫做1.txt,并且文本行数大于10,脚本如下

    #!/bin/bash
    ##先获取该文本的行数
    nu=`wc -l 1.txt |awk '{print $1}'`
    ##对前5行进程处理
    for i in `seq 1 5`
    do
    ##使用sed把每一行的内容赋值给变量
    l=`sed -n "$ip" 1.txt`
    ##用grep 判定是否匹配字母,-v取反,-q不输出内容
    if echo $l |grep -vq '[a-zA-Z]'
    then
    echo $l
    fi
    done
    
    ##对6-10行做删除字母处理
    for i in `seq 6 10`
    do
    l=`sed -n "$i"p 1.txt`
    echo $l|sed 's/[a-zA-Z]//g'
    done
    
    ##剩余的直接输出
    for i in `seq 11 $nu`
    do
    sed -n "$i"p 1.txt
    done
    ##若想把更改内容写入到1.txt,还需要把以上内容重定向到一个文本中,然后删除1.txt,再把刚刚重定向的文件>更名为1.txt
    

      

    10、查找字母数小于6的单词

    描述:

    用shell打印下面这句话中字母数小于6的单词。
    Bash also interprets a number of multi-character options.

    参考答案

    #!/bin/bash
    for s in Bash also interprets a number of multi-character options
    do
            n=`echo $s|wc -c`
            if [ $n -lt 6 ]
            then
            echo $s
            fi
    done
    

    11、输入数字执行对应命令

    描述:

    写一个脚本实现如下功能:  输入一个数字,然后运行对应的一个命令。

    显示命令如下:*cmd meau**  1—date 2–ls 3–who 4–pwd
    当输入1时,会运行date, 输入2时运行ls, 依此类推。

    参考答案

    #!/bin/bash
    echo "**cmd meau** 1-date  2-ls  3-who 4-pwd"
    read -p "Please input a number 1-4:" n
    echo $n
    
    case $n in
      1)
        date
      ;;
      2)
        ls
      ;;
      3)
        who
      ;;
      4)
        pwd
      ;;
      *)
        echo "Please input a number:1-4"
      ;;
    esac
    

      

    12批量创建用户并设置密码

    描述:

    添加user_00 – user_09 10个用户,并且给他们设置一个随机密码,密码要求10位包含大小写字母以及数字,注意需要把每个用户的密码记录到一个日志文件里。

    提示: 
    1. 随机密码使用命令 mkpasswd
    2. 在脚本中给用户设置密码,可以使用echo 然后管道passwd命令

    #!/bin/bash
    for i in `seq -w 00 09`
      do
        useradd user_$i
    
        #随机生成10位不包含特殊符号的密码
        p=`mkpasswd -s 0 -l 10`
        echo "$p"
        echo "user_$i $p" >>/tmp/user0_9.pass
    
        #修改指定用户的密码
        echo $p|passwd --stdin user_$i
      done
    

    注:1)mkpasswd的命令执行的前提是安装了expect,若是没有安装可执行yum install  expect 进行安装

    usage: mkpasswd [args] [user]
    参数:

    -l # (密码的长度定义, 默认是 9)

    -d # (数字个数, 默认是 2)

    -c # (小写字符个数, 默认是 2)

    -C # (大写字符个数, 默认是 2)

    -s # (特殊字符个数, 默认是 1)

    -v  (详细。。。)

    -p prog (程序设置密码, 默认是 passwd)

    13、监控httpd进程

    描述:

    在服务器上,写一个监控脚本。

    1. 每隔10s去检测一次服务器上的httpd进程数,如果大于等于500的时候,就需要自动重启一下apache服务,并检测启动是否成功?
    2. 若没有正常启动还需再一次启动,最大不成功数超过5次则需要理解发邮件通知管理员,并且以后不需要再检测!
    3. 如果启动成功后,1分钟后再次检测httpd进程数,若正常则重复之前操作(每隔10s检测一次),若还是大于等于500,那放弃重启并需要发邮件给管理员,然后自动退出该脚本。假设其中发邮件脚本为之前咱们使用的mail.py

    参考答案

    #!/bin/bash
    
    check_service()
    {
        n=0
        for i in `seq 1 5`
        do
        /usr/local/apache2/bin/apachectl restart 2>/tmp/apache.err
        if [ $? -ne 0 ]
        then
            n=$[$n+1]
        else
            break
        fi
        done
    
        if [ $n -eq 5 ]
        then
            ##下面的mail.py参考https://coding.net/u/aminglinux/p/aminglinux-book/git/blob/master/D22Z/mail.py
            python mai.py "123@qq.com" "httpd service down" `cat /tmp/apache.err`
            exit
        fi
    }   
    
    
    while :
    do
        t_n=`ps -C httpd --no-heading |wc -l`
        if [ $t_n -ge 500 ]
        then
            /usr/local/apache2/bin/apachectl restart
            if [ $? -ne 0 ]
            then
                check_service
            fi
            sleep 60
            t_n=`ps -C httpd --no-heading |wc -l`
            if [ $t_n -ge 500 ]
            then
                python mai.py "123@qq.com" "httpd service somth wrong" "the httpd process is budy."
                exit
            fi
        fi
        sleep 10
    done
    

    14、封IP

    描述:根据web服务器上的访问日志,把一些请求量非常高的ip给拒绝掉!

    分析: 我们要做的,不仅是要找到哪些ip请求量不合法,并且还要每隔一段时间把之前封掉的ip(若不再继续请求了)给解封。 所以该脚本的关键点在于定一个合适的时间段和阈值。

    比如, 我们可以每一分钟去查看一下日志,把上一分钟的日志给过滤出来分析,并且只要请求的ip数量超过100次那么就直接封掉。 而解封的时间又规定为每半小时分析一次,把几乎没有请求量的ip给解封!

    参考日志文件片段:

    157.55.39.107 [20/Mar/2015:00:01:24 +0800] www.aminglinux.com “/bbs/thread-5622-3-1.html” 200 “-” “Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)”
    61.240.150.37 [20/Mar/2015:00:01:34 +0800] www.aminglinux.com “/bbs/search.php?mod=forum&srchtxt=LNMP&formhash=8f0c7da9&searchsubmit=true&source=hotsearch” 200 “-” “Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)”

    参考答案

    #! /bin/bashlogfile=/home/logs/client/access.log
    d1=`date -d "-1 minute" +%H:%M`
    d2=`date +%M`
    ipt=/sbin/iptables
    ips=/tmp/ips.txt
    
    block(){
        grep "$d1:" $logfile|awk '{print $1}' |sort -n |uniq -c |sort -n >$ips
        for ip in `awk '$1>50 {print $2}' $ips`; do
            $ipt -I INPUT -p tcp --dport 80 -s $ip -j REJECT
            echo "`date +%F-%T` $ip" >> /tmp/badip.txt
        done
    }
    
    unblock(){
        for i in `$ipt -nvL --line-numbers |grep '0.0.0.0/0'|awk '$2<15 {print $1}'|sort -nr`; do
            $ipt -D INPUT $i
        done
        $ipt -Z
    }
    
    if [ $d2 == "00" ] || [ $d2 == "30" ]; then
        unblock
        block
    else
        block
    fi
    

      

    15、找规律打印数字

    请详细查看如下几个数字的规律,并使用shell脚本输出后面的十个数字。
    10 31 53 77  105 141 …….

    试题解析:
    我想大多数人都会去比较这些数字的差值:
    10  31  53  77  105  141
    21   22   24   28   36
    但是这个差值看,并没有什么规律,而我们再仔细看的时候,发现这个差值的差值是有规律的:
    10  31  53  77  105  141
    21   22   24   28   36
    1      2     4     8

    参考答案:

    #!/bin/bash
    x=21
    m=10
    echo $m
    for i in `seq 0 14`;
      do
         j=$[2**$i]
         m=$[$m+$x]
         echo $m
         x=$[$x+$j]
      done

    16、统计普通用户

    描述:写个shell,看看你的Linux系统中是否有自定义用户(普通用户),若是有,一共有几个?

    参考答案:

    假设所有普通用户都是uid大于1000的

    #!/bin/bash
     n=`awk -F ':' '$3>1000' /etc/passwd|wc -l`
     if [ $n -gt 0 ]
     then
         echo "There are $n common users."
     else
         echo "No common users."
     fi
    

      不太理解为甚么uid大于1000的都是普通用户

    17、监控磁盘使用率

    写一个shell脚本,检测所有磁盘分区使用率和inode使用率并记录到以当天日期为命名的日志文件里,当发现某个分区容量或者inode使用量大于85%时,发邮件通知你自己。

    思路:就是先df -h 然后过滤出已使用的那一列,然后再想办法过滤出百分比的整数部分,然后和85去比较,同理,inode也是一样的思路

    参考答案:

    #!/bin/bash
    log=/tmp/log/`date +%F`.log
    date +'%F %T'
    df -h >>$log
    echo >>$log
    df -i >>$log
    ma=xxx@123.com
    for i in `df -h|grep -v 'Use%'|sed 's/%//'|awk '{print $5}'`;do
      if [ $i -gt 85 ];then
         use=`df -h|grep -v 'Use%'|sed 's/%//'|awk '$5=='$i' {print $1,$5}'`
         echo "$use" >>sue
       fi
    done
    
    if [ -e use ]; then
      python  /data/python/mail.py $ma "Filesystem Use% > 85%" "$use"
    fi
    
    
    for j in `df -i|grep -v 'IUse%'|sed 's/%//'|awk '{print $5}'`;do
      if [ $j -gt 85 ]; then
         iuse=`df -i|grep -v 'IUse%'|sed 's/%//'|awk '$5=='$j' {print $1,$5}'`
       fi
    done
    
    if [ -e iuse ]; then
      python  /data/python/mail.py $ma "Filesystem IUse% > 85%" "$iuse"
    fi
    

      

    18、获取文件列表

    描述:

    有一台服务器作为web应用,有一个目录(/data/web/attachment)不定时地会被用户上传新的文件,但是不知道什么时候会上传。所以,需要我们每5分钟做一次检测是否有新文件生成。

    请写一个shell脚本去完成检测。检测完成后若是有新文件,还需要将新文件的列表输出到一个按年、月、日、时、分为名字的日志里。请不要想的太复杂,核心命令只有一个 find /data/web/attachment -mmin -5

    思路: 每5分钟检测一次,那肯定需要有一个计划任务,每5分钟去执行一次。脚本检测的时候,就是使用find命令查找5分钟内有过更新的文件,若是有更新,那这个命令会输出东西,否则是没有输出的。固,我们可以把输出结果的行数作为比较对象,看看它是否大于0。

    参考答案

    #!/bin/bash
    
    d=`date -d "-5 min" +%Y%m%d%H%M`
    echo $d
    basedir=/data/shell/attachment
    find $basedir/ -type f -mmin -5 >/tmp/newf.txt
    n=`wc -l /tmp/newf.txt|awk '{print $1}'`
    echo %n
    if [ $n -gt 0 ]; then
      /bin/mv /tmp/newf.txt /tmp/$d
    fi  

    衍生: ls --full-time|awk '{OFS=" " } {print $6,$9}'>/tmp/filelist.txt

    19、统计常用命令

    描述:写一个shell脚本来看看你使用最多的命令是哪些,列出你最常用的命令top10。

     sort /root/.bash_history|uniq -c|sort -nr|head

    20、统计日志大小

     描述:假如我们需要每小时都去执行你写的脚本。在脚本中实现这样的功能,当时间是0点和12点时,需要将目录/data/log/下的文件全部清空,注意只能清空文件内容而不能删除文件。而其他时间只需要统计一下每个文件的大小,一个文件一行,输出到一个按日期和时间为名字的日志里。 需要考虑/data/log/目录下的二级、三级、…  等子目录里面的文件。

    #!/bin/bash
    logdir='/data/shell/log'
    t=`date +%H`
    d=`date +%T`
    echo $d >/tmp/logsize
    for log in `find $logdir -type f`
    do
         if [ $t == "0" ] || [ $t == "12" ]
            then
            ture >$log
         else
            du -sh $log >>/tmp/logsize
         fi
    done
    

      

    学习网址:http://blog.lishiming.net/?paged=10&cat=2

  • 相关阅读:
    【C#】C#8.0常用新特性
    【Docker】Asp.net core在docker容器中的端口问题
    【gRPC】ProtoBuf 语言快速学习指南
    【日常排雷】 .Net core 生产环境appsetting读取失败
    【gRPC】 在.Net core中使用gRPC
    raspbian buster阿里镜像
    管道通信
    关于utf8mb4的使用
    ef core数据迁移的一点小感悟
    windows 端口转发
  • 原文地址:https://www.cnblogs.com/jzhg/p/8658894.html
Copyright © 2011-2022 走看看