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、批量更改文件名
描述:
- 找到/123目錄下所有后綴名為.txt的文件
- 批量修改.txt為.txt.bak
- 把所有.bak文件打包壓縮為123.tar.gz
- 批量還原文件的名字,即把增加的.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