Shell腳本1-20例

一、天天生成一個文件

描述:請按照這樣的日期格式(xxxx-xx-xx)每日生成一個文件,例現在天生成的文件爲)2017-07-05.log, 而且把磁盤的使用狀況寫到到這個文件中,(不用考慮cron,僅僅寫腳本便可)php

參考答案html

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

  

注:1)date  +%F中date與+之間存在空格node

2)其餘建立路徑/data/shell/logpython

 

二、根據日誌統計每一個IP的訪問量 

描述: 將下述日誌屢次複製粘貼至02.log中,編寫腳本,統計出每一個IP的訪問量有多少?mysql

 

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;)」linux

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)」nginx

 

參考答案:git

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

三、統計內存

描述:寫一個腳本計算一下linux系統全部進程佔用內存大小的和。(提示,使用ps或者top命令)sql

上述字段說明:

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" 

四、設計監控腳本

描述:

設計一個腳本,監控遠程的一臺機器(假設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 目標郵箱 "郵件主題" "郵件內容"

 

  

 

 

 

 

五、批量更改文件名

 描述:

  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

  

六、監控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。

七、備份數據庫

描述:

設計一個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

 

八、自動重啓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

  

九、刪除文本中的字母

描述:

把一個文本文檔的前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

  

十、查找字母數小於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

 

十一、輸入數字執行對應命令

描述:

寫一個腳本實現以下功能:  輸入一個數字,而後運行對應的一個命令。

顯示命令以下:*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)

 

1三、監控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

1四、封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

  

1五、找規律打印數字

請詳細查看以下幾個數字的規律,並使用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

 

1六、統計普通用戶

描述:寫個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的都是普通用戶

1七、監控磁盤使用率

寫一個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

  

1八、獲取文件列表

描述:

有一臺服務器做爲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

1九、統計經常使用命令

描述:寫一個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

相關文章
相關標籤/搜索