shell实例100例《一》

1、【题目要求】每日一文件

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

【习题答案】

本题答案:

#! /bin/bash
d=`date +%F`
logfile=$d.log
df -h > $logfile

需求升级:删除一年以前的文件

#!/bin/bash
d=`date +%F`
dir=/data/logs/disklog
if [ ! -d $dir ]
then
    mkdir -p $dir
fi
df -h > $dir/$d.log
find $dir/ -mtime +365 |xargs rm

 

2、根据日志统计访问量

题目要求 统计I访问量

有日志1.log,部分内容如下

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)”

统计出每个IP访问量有多少

核心要点

awk、sort、uniq命令

参考答案
awk '{print $1}' 1.log|sort |uniq -c |sort -n -r

注意  :print $1 表示第一列;

sort     #排序

uniq -c    #去重复

第二个sort是去重复再一次排序  ,-r    #反序

 

3、题目要求 : 统计内存占用之和

写一个脚本计算一下linux系统所有进程占用内存大小的和。

核心要点
  • ps命令用法
  • for循环
  • 加法运算
参考答案
#!/bin/bash
sum=0
for n in `ps aux |grep -v 'TIME COMMAND'|awk '{print $6}'`
do
    sum=$[$sum+$n]
done
echo $sum

注意  :

计算一下linux系统所有进程占用内存大小的和。

1、ps aux |grep -v 'TIME COMMAND'|awk '{print $6}'

2、ps aux --no-headers | awk '{sum+=$6} END {print sum}'

3、ps aux |awk '{if(NR>1){print $6}}'

 

grep -v 'TIME COMMAND'         #是过过滤掉TIME COMMAND的行

awk '{print $6}'       #打印第六行的值

 

4、题目要求 : 检测机器存活

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

核心要点

ping -c10 180.163.26.39      通过ping来判定对方是否在线

发邮件脚本 https://coding.net/u/aminglinux/p/aminglinux-book/git/blob/master/D22Z/mail.py

参考答案
#!/bin/bash
n=`ping -c5 180.163.26.39|grep 'packet' |awk -F '%' '{print $1}' |awk '{print $NF}'`
if [ -z "$n" ]
then
    echo "脚本有问题。"
    python mail.py  $m "检测机器存活脚本$0有问题" "获取变量的值为空"
    exit
else
    n1=`echo $n|sed 's/[0-9]//g'`
    if [ -n "$n" ]
    then
        echo "脚本有问题。"
        python mail.py  $m "检测机器存活脚本$0有问题" "获取变量的值不是纯数字"
        exit 
    fi
fi

if 
m=123@qq.com
while :
do
    if [ $n -ge 50 ]
    then
    	python mail.py $m "机器宕机" "丢包率是$n%"
    fi
    sleep 30
done

注意 :

s/[0-9]//g           #删除所有的数字

 -z "$n"              #返回的丢包率为0

 -n "$n"              #返回的丢包率不为0

$n -ge 50           #表示丢包率大于等于50%

如果丢包率100%,说明机器已经宕机了

过滤丢包的百分率  : ping -c2 180.163.26.39|grep 'packet' | awk -F '%' '{print $1}' | awk '{print $NF}'

ping -c2    #只显示两个包,

 

让python邮件脚本,邮件内容为附件显示格式为utf-8

#!/usr/bin/python

#coding:utf-8

 

import smtplib 

from email.mime.text import MIMEText

import sys

 

mail_user = '111@163.com'

mail_pass = 'xxxxxxxxxx'

 

def send_mail(to_list,subject,content):

    me = "zabbix 监控告警平台"+"<"+mail_user+">"

    msg = MIMEText(content, 'plain', 'utf-8')

    msg['Subject'] = subject

    msg['From'] = me

    msg['to'] = to_list

 

    try:

        s = smtplib.SMTP("smtp.163.com", 25)

        s.login(mail_user,mail_pass)

        s.sendmail(me,to_list,msg.as_string())

        s.close()

        return True

    except Exception,e:

        print str(e)

        return False

 

if __name__ == "__main__":

    send_mail(sys.argv[1], sys.argv[2], sys.argv[3])

 

5、题目要求

找到/123目录下所有后缀名为.txt的文件

  1. 批量修改.txt为.txt.bak
  2. 把所有.bak文件打包压缩为123.tar.gz
  3. 批量还原文件的名字,即把增加的.bak再删除
核心要点
  • find用来查找所有.txt文件
  • tar打包一堆文件
  • 还原文件名用for循环
参考答案
#!/bin/bash
find /123/ -type f -name "*.txt" > /tmp/txt.list 
for f in `cat /tmp/txt.list`
do
    mv $f  $f.bak
done

#find /123/ -type f -name *.txt |xargs -i mv {} {}.bak 
#find /123/ -type f -name *.txt -exec mv {} {}.bak \;

for f in `cat /tmp/txt.list`
do
    echo $f.bak
done > /tmp/txt.bak.list 

tar -czvf 123.tar.gz `cat /tmp/txt.bak.list |xargs `

for f in `cat /tmp/txt.list`
do 
    mv $f.bak $f
done 

注意 :记得创建123目录

mkdir  /123/

touch /123/1.txt

touch /123/2.txt

mkdir /123/2xd/

touch !$3.txt

cp -r /123/ /123.bak

 

6、题目要求    :检测80端口是否存在

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

核心要点
  • 检测80端口使用nmap -p 80 127.0.0.1或者netstat -lntp|grep -w 80
  • 重启httpd服务的命令要知道
  • 发邮件脚本依然使用mail.py
参考答案
#!/bin/bash
m=123@123.com
while :
do
    n=`netstat -lntp |grep ':80 '|wc -l`
    if [ $n -eq 0 ]
    then
        /usr/local/apache2/bin/apachectl -k restart 2>/tmp/apache.err
        python mail.py $m "80端口关闭" "已经重启httpd服务"
        pn=`pgrep -l httpd|wc -l`
	if [ $pn -eq 0 ]
	then
	    python mail.py $m "httpd重启失败" "`head -1 /tmp/apache.err`"
	fi
    fi
    
    sleep 30
done

注意 : netstat -lntp |grep ':80 ' = nmap -p 80 127.0.0.1 |grep '80/tcp'   #查看80端口的状态和占用情况

80/tcp closed http

nmap -p 80 127.0.0.1 |grep '80/tcp' | awk '{print $2}'  #查看80端口的状态

closed

pgrep -l httpd|wc -l                     #统计HTTP的连接数

 

7、题目要求 :备份数据库

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

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

核心要点
  • 备份数据库的命令
  • 同步到远程去的命令
  • 本地一周,可以用date +%w做为后缀,远程一个月可以用date +%d做为后缀
参考答案
#!/bin/bash
d1=`date +%w`
d2=`date +%d`
local_bakdir=/bak/mysql
remote_bakdir=192.168.123.30::backup

exec 1> /tmp/mysqlbak.log  2>/tmp/mysqlbak.err
echo "mysql bakcup begin at `date`"
mysqldump -uroot -pxxxx discz > $local_bakdir/discuz.sql.$d1
rsync -az $local_bakdir/discuz.sql.$d1 $remote_bakdir/discuz.sql.$d2
echo "mysql backup end at `date`"

注意 :
mysqldump -uroot -pxxxx discz > $local_bakdir/discuz.sql.$d1       #备份到本地

rsync -az $local_bakdir/discuz.sql.$d1 $remote_bakdir/discuz.sql.$d2   #压缩上传到远程的库

-az      #压缩

/tmp/mysqlbak.err            #错误的文件输出日志

/tmp/mysqlbak.log             #正确的文件输出日志

 

8、题目要求 :检测502

服务器上跑的是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

核心要点
  • 用curl检测状态码是否是502或者通过分析访问日志判断状态码的比率
  • 重启php-fpm服务的命令
参考答案
#!/bin/bash
log=/data/log/access.log
while :
do
502_n=`tail -n 300 $log |grep -c ' 502 '`
if [ -z "$502_n" ]
then
    exit
fi

if [ $502_n -gt 100 ]
then
    /etc/init.d/php-fpm restart >/dev/null 2>/tmp/php-fpm.err
    fpm_p_n=`pgrep -l php-fpm|wc -l`
    if [ $fpm_p_n -eq 0 ]
    then
        python mail.py xxx@xx.com "php-fpm重启失败" "`head -1 /tmp/php-fpm.err`"
        exit
    fi
fi
sleep 10
done

注意 : log=/data/log/access.log                #定义日志的文件名

tail -n 300 $log | grep -c ' 502 '             #截取日志条数为300,统计含有502的行出现的次数

 

/etc/init.d/php-fpm restart >/dev/null 2>/tmp/php-fpm.err       #正确的输出到/dev/null  ;如果报错了,输出到/tmp/php-fpm.err日志中。

pgrep -l php-fpm|wc -l                  #统计进程的个数,

fpm_p_n -eq 0              #如果为0,说明重启失败了。退出来,然后发一封邮件

python mail.py xxx@xx.com "php-fpm重启失败" "`head -1 /tmp/php-fpm.err`"           #把重启的错误,输入到 /tmp/php-fpm.err文件中去

 

9、题目要求 :删除字母和行

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

核心要点

sed命令

参考答案
#!/bin/bash
sed -n '1,5'p 1.txt |sed '/[a-zA-Z]/d'
sed '1,5d' 1.txt |sed '1,5s/[a-zA-Z]//g'

示例文件1.txt内容
1111111111111111111
121212aaasdasdf
asdfasdfasdfasdfasdf
12121212aklsdfjaklsdfkjk
*****#)#((@#*@)1121212
root@gitlba-aming shell100
12aaasdas23asdfasdf
asdf;lkjas;lkdjfkl;ajsdf
asl;dkfjalskdjflkj2elkjwlkej23kijlkjasdf
laksjdflkjslkdjfslkdjflksjdf
21l3k2l3k2l3kjl2k3jl2k3j
askdjfklasjdflklkajlksdjfkl12323232323
asdklfjalksdf
asldkfjalksdjfalksdjfklasjdf2323
aslkdjflk2k3j2lk3jl2k3j
asdklfjalksjdflkj132
asdfkjalksdjf121adfavasdfads asldkfjalksdjf
lkjlkjlwkerlk2j3lk21j3lkjflkasjdlkj23lkj klaj d

注意  :

sed -n '1,5'p 1.txt |sed '/[a-zA-Z]/d'         等于  sed -n5 1.txt |sed '/[a-zA-Z]/d'                  #把一个文本文档的前5行中包含字母的行删除掉

sed '1,5d' 1.txt |sed '1,5s/[a-zA-Z]//g'                    #同时把6到10行中的全部字母删除掉。

 

 

10、题目要求 : 找单词

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

核心要点
  • for循环遍历所有单词
  • wc -L获取字符串长度
参考答案
#!/bin/bash
c="Bash also interprets a number of multi-character options."
n=`echo $c|awk -F '[ +-.]' '{print NF}'`
for ((i=1;i<$n;i++))
do
    l=`echo $c|awk -F '[ +-.]' -v j=$i '{print $j}'|wc -L`
    if [ $l -lt 6 ]
    then
        echo $c|awk -F '[ +-.]' -v j=$i '{print $j}'
    fi
done

注意 :

Bash also interprets a number of multi-character options."
n=`echo $c|awk -F '[ +-.]' '{print NF}'              #打印下面这句话中字母数小于6的单词,并打印段数。

 

echo $c|awk -F '[ +-.]' -v j=$i '{print $j}'|wc -L                   #截选单词的长度

$l -lt 6                     #限定单词的长度小于6

 

 

来源 :https://github.com/aminglinux/shell100/blob/master/1.md

转载于:https://my.oschina.net/u/3803405/blog/3001117

  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值