咱們服務器搭建了cacti進行監控,一次經過查看磁盤IO圖像的時候,發現天天凌晨3:20-3:35的時候磁盤IO一下飆的很高,而後想知道究竟是哪一個進程佔用那麼高的IO,下面是解決方法:python
寫個檢測腳本check_io_process.sh,當磁盤IO佔用高的時候進行磁盤IO讀寫進程次數的檢測:ios
#!/bin/bash
# Date: 2013/8/20
# Author: zhangkai
# Description: This script is used to check IO higher process.
# History:
iostat_log=/data/logs/iostat/iostat.log
dmesg_log=/data/logs/iostat/dmesg.log
dstat_log=/data/logs/iostat/dstat.logshell
if [ ! -d /data/logs/iostat ];then
mkdir -p /data/logs/iostat
fi數據庫
add(){
str=$@
sum=`echo ${str// /+}|bc -l`
}vim
iostat -x 1 5 > $iostat_log
idle_percent=`cat $iostat_log | awk 'BEGIN{flag=0} {if(flag ==1){print $12; flag=0;} if (index($0, "%util" )) {flag = 1;}}'`bash
add $idle_percent服務器
#求5次查詢IO佔用率的平均值app
avg=`echo $sum/5|bc`ide
if [[ $avg -ge 70 ]];then
echo 1 > /proc/sys/vm/block_dump
echo "-----------------------------------------------" >> $dmesg_log
echo `date "+%Y-%m-%d %H:%M:%S"` >> $dmesg_log
python /data/dmesg_io.py >> $dmesg_log
echo "-----------------------------------------------" >> $dstat_log
echo `date "+%Y-%m-%d %H:%M:%S"` >> $dstat_log
dstat -d --top-bio 1 10 >> $dstat_log
echo 0 > /proc/sys/vm/block_dump
fi優化
其中該shell腳本調用了檢測磁盤IO讀寫進程次數的python腳本,下面是dmesg_io.py的代碼:
#!/usr/bin/python
# Monitoring per-process disk I/O activity
# written by http://www.vpsee.com
import sys, os, time, signal, re
class DiskIO:
def __init__(self, pname=None, pid=None, reads=0, writes=0):
self.pname = pname
self.pid = pid
self.reads = 0
self.writes = 0
def main():
argc = len(sys.argv)
if argc != 1:
print "usage: ./iotop"
sys.exit(0)
if os.getuid() != 0:
print "must be run as root"
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
os.system('echo 1 > /proc/sys/vm/block_dump')
print "TASK PID READ WRITE"
# while True:
os.system('dmesg -c > /tmp/diskio.log')
l = []
f = open('/tmp/diskio.log', 'r')
line = f.readline()
while line:
m = re.match(\
'^(\S+)\((\d+)\): (READ|WRITE) block (\d+) on (\S+)', line)
if m != None:
if not l:
l.append(DiskIO(m.group(1), m.group(2)))
line = f.readline()
continue
found = False
for item in l:
if item.pid == m.group(2):
found = True
if m.group(3) == "READ":
item.reads = item.reads + 1
elif m.group(3) == "WRITE":
item.writes = item.writes + 1
if not found:
l.append(DiskIO(m.group(1), m.group(2)))
line = f.readline()
time.sleep(1)
for item in l:
print "%-10s s d d" % \
(item.pname, item.pid, item.reads, item.writes)
def signal_handler(signal, frame):
os.system('echo 0 > /proc/sys/vm/block_dump')
sys.exit(0)
if __name__=="__main__":
main()
發如今3:20-3:35的日誌以下(僅列出部分):
[root@localhost iostat]# cat dmesg.log
-----------------------------------------------
2013-08-22 03:23:06
TASK PID READ WRITE
updatedb 18661 2951 0
kjournald 804 0 525
kjournald 1826 0 576
-----------------------------------------------
2013-08-22 03:24:05
TASK PID READ WRITE
updatedb 18661 3007 0
kjournald 804 0 238
kjournald 1826 0 112
flush-8:0 11687 0 18
-----------------------------------------------
2013-08-22 03:25:05
TASK PID READ WRITE
updatedb 18661 2689 0
kjournald 804 0 229
kjournald 1826 0 44
說明是updatedb這進程惹的禍,google查之,這個是由[cron]自動運行的更新系統數據的腳本。
其做用是爲你係統裏面的文件創建索引,以便於locate和whereis等查詢命令的可以快速執行
而咱們服務器/data/目錄天天會產生大量的小文件,致使創建索引的時候佔用很高的磁盤IO
服務器天天定時對硬盤上的文件進行索引,簡單的說就是創建一個數據庫,把全部文件目錄信息存放到這個庫裏面,當使用whereis和locate命令搜索文件時,它直接到這個數據庫中讀取數據。而不是像find同樣在硬盤上找文件。Whereis搜索一個文件幾乎只要幾秒鐘就能夠搞定,而find須要花費幾分鐘或者更長時間。updatedb.Conf使搜索的效率提升了不少倍。可是有缺點,它天天都須要索引更新,這會致使IO負載太高,由於不是時時更新,因此會出現搜索到已經刪除的文件,搜不出新添加的文件,平時管理中咱們不多用到。若是文件數量多並且更新平凡,咱們大可把這個功能關閉
優化方法:
1.中止對/data目錄進行創建索引操做
vim /etc/updatedb.conf
找到PRUNEPATHS,在後面添加上你不想讓這個updatedb創建索引的目錄
2.設置定時更新的工做頻率從天天一次下降到每週執行一次,命令以下:
mv /etc/cron.daily/mlocate.cron /etc/cron.weekly/ 固然若是你服務器用不着創建索引,也能夠直接移除