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
