shell實例100例《一》

一、【題目要求】每日一文件php

請按照這樣的日期格式(xxxx-xx-xx)每日生成一個文件, 例如生成的文件名爲2017-12-20.log, 而且把磁盤的使用狀況寫到到這個文件中, 不用考慮cron,僅僅寫腳本便可html

【習題答案】python

本題答案:mysql

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

需求升級:刪除一年之前的文件linux

#!/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

 

二、根據日誌統計訪問量nginx

題目要求 統計I訪問量

有日誌1.log,部份內容以下git

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訪問量有多少github

核心要點

awk、sort、uniq命令sql

參考答案

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

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

sort     #排序

uniq -c    #去重複

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

 

三、題目要求 : 統計內存佔用之和

寫一個腳本計算一下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系統全部進程佔用內存大小的和。

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

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

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

 

grep -v 'TIME COMMAND'         #是過過濾掉TIME COMMAND的行

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

 

四、題目要求 : 檢測機器存活

設計一個腳本,監控遠程的一臺機器(假設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])

 

五、題目要求

找到/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

 

六、題目要求    :檢測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的鏈接數

 

七、題目要求 :備份數據庫

設計一個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             #正確的文件輸出日誌

 

八、題目要求 :檢測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文件中去

 

九、題目要求 :刪除字母和行

把一個文本文檔的前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行中的所有字母刪除掉。

 

 

十、題目要求 : 找單詞

用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

相關文章
相關標籤/搜索