系统信息收集脚本

使用topiostatvmstatdstatblktracepidstat监控系统状态信息

执行方式:

text
1
2
3
4
5
# 开启统计
./script_name start [output_filename_prefix]

# 关闭统计
./script_name stop

脚本内容:

text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
######## 性能数据收集脚本 ########
# 开始/停止
SWITCH=${1}
# 输出文件前缀
OUTPUT_PREFIX=${2}

CURRENT_TIME=`date "+%Y%m%d_%H%M%S"`
SCRIPT_ABS_PATH=$(cd `dirname $0`; pwd)
# 临时存储进程pid
STAT_PID_FILE=${SCRIPT_ABS_PATH}/.stat_perf_pid
ARG_IOSTAT_DISK=/dev/sdc
BLKTRACE_SWITCH=1
PIDSTAT_PROCESS_NAME=""

function program_exists() {
  local ret='0'
  command -v $1 >/dev/null 2>&1 || { local ret='1'; }
   # 不存在返回0
   if [ "$ret" -ne 0 ]; then
      return 0
   fi
  return 1
}

# iostat 信息收集
function iostat_info() {
   iostat_info_filename=${SCRIPT_ABS_PATH}/${OUTPUT_PREFIX}_iostat_${CURRENT_TIME}.log

   # 清空文件
   echo "" > ${iostat_info_filename}
   # 收集数据添加时间戳并写入文件
   IOSTAT_ARGS="-x 3"
   if [ ${ARG_IOSTAT_DISK} ];then
       IOSTAT_ARGS="${IOSTAT_ARGS} -d ${ARG_IOSTAT_DISK}"
   fi
  iostat ${IOSTAT_ARGS} | stdbuf -oL awk '{print strftime("[%Y-%m-%d %H:%M:%S]"),$0}' >> ${iostat_info_filename}
}

function top_info() {
   top_info_filename=${SCRIPT_ABS_PATH}/${OUTPUT_PREFIX}_top_${CURRENT_TIME}.log

   # 清空文件
   echo "" > ${top_info_filename}
   # 收集数据并写入文件 5 s 一次,top取前30行数据
   while : ; do
       sleep 5
       top -b -n 1 | stdbuf -oL awk 'BEGIN{ i=0 } { if(i++<30) print strftime("[%Y-%m-%d %H:%M:%S]"),$0}' >> ${top_info_filename}
   done
}

# vmstat 信息收集
function vmstat_info() {
   vmstat_info_filename=${SCRIPT_ABS_PATH}/${OUTPUT_PREFIX}_vmstat_${CURRENT_TIME}.log

   # 清空文件
   echo "" > ${vmstat_info_filename}
   # 收集数据并写入文件
  vmstat -w 3 | stdbuf -oL awk '{print strftime("[%Y-%m-%d %H:%M:%S]"),$0}' >> ${vmstat_info_filename}
}

# dstat 信息收集
function dstat_info() {
   dstat_info_filename=${SCRIPT_ABS_PATH}/${OUTPUT_PREFIX}_dstat_${CURRENT_TIME}.log

   # 清空文件
   echo "" > ${dstat_info_filename}
   # 收集数据并写入文件
  dstat | stdbuf -oL awk '{print strftime("[%Y-%m-%d %H:%M:%S]"),$0}' >> ${dstat_info_filename}
}

# blktrace 设备层 IO信息收集
function blktrace_info() {
   # blktrace 会输出多个文件,所以创建文件夹
   blktrace_info_dir=${SCRIPT_ABS_PATH}/$(basename ${ARG_IOSTAT_DISK})_blktrace_${OUTPUT_PREFIX}_${CURRENT_TIME}
   mkdir -p ${blktrace_info_dir}

   # 执行blktrace 等待Ctrl+C退出
   cd ${blktrace_info_dir}
   # echo "blktrace dir ${blktrace_info_dir} cmd:blktrace -d ${ARG_IOSTAT_DISK}"
  blktrace -d ${ARG_IOSTAT_DISK}
}

function pidstat_info() {
   pidstat_info_filename=${SCRIPT_ABS_PATH}/${OUTPUT_PREFIX}_pidstat_${CURRENT_TIME}.log
   # 清空文件
   echo "" > ${pidstat_info_filename}
   # 收集数据并写入文件
  pidstat -G ${PIDSTAT_PROCESS_NAME} -u 1 | stdbuf -oL awk '{print strftime("[%Y-%m-%d %H:%M:%S]"),$0}' >> ${pidstat_info_filename}
}

# 输出文件前缀
if [ -z "${OUTPUT_PREFIX}" ];then
   OUTPUT_PREFIX="default"
fi

# 开始或停止性能监测脚本
if [ "${SWITCH}" = "start" ];then
   if [ -e ${STAT_PID_FILE} ];then
       echo "请勿重复运行,若想开启多个监测,将脚本拷贝到新的目录执行"
       exit -1
   fi
   echo "start stat perf"
  iostat_info &
   iostat_pid=$!
   echo "iostat_pid="$iostat_pid

  vmstat_info &
   vmstat_pid=$!
   echo "vmstat_pid="$vmstat_pid

  top_info &
   top_pid=$!
   echo "top_pid="$top_pid

   # 如果dstat存在则开启dstat统计
   dstat_pid=""
  program_exists dstat
   dstat_exist=$?
   if [ ${dstat_exist} -eq 1 ];then
      dstat_info &
       dstat_pid=$!
       echo "dstat_pid="$dstat_pid
   fi

   blktrace_pid=""
   if [ ${BLKTRACE_SWITCH} -eq 1 ];then
       # blktrace 一定要指定磁盘
       if [ ${ARG_IOSTAT_DISK} ];then
          blktrace_info &
           blktrace_pid=$!
           echo "blktrace_pid="$blktrace_pid
       else
           echo "blktrace need specific device"
       fi
   fi

   pidstat_pid=""
   if [ ${PIDSTAT_PROCESS_NAME} ];then
      pidstat_info &
       pidstat_pid=$!
       echo "pidstat_pid="$pidstat_pid
   fi

   echo "iostat_pid:${iostat_pid} vmstat_pid:${vmstat_pid} top_pid:${top_pid} dstat_pid:${dstat_pid} blktrace_pid:${blktrace_pid} pidstat_pid:${pidstat_pid}" > ${STAT_PID_FILE}
   echo "start stat perf success"
elif [ "${SWITCH}" = "stop" ];then
   echo "stop stat perf"
   # 判断pid文件是否存在
   if [ -e ${STAT_PID_FILE} ];then
       for pidname_pid in `cat ${STAT_PID_FILE}`
       do
           pid=${pidname_pid#*:}
           pidname=${pidname_pid%:*}
           echo "stop pid:${pid} pidname:${pidname}"
           if [ -z ${pid} ];then
               # 如果这种情况不过滤掉,空的pid值会kill掉整个系统的进程
              continue
           fi
          pstree -p ${pid}
           if [ ${pidname} = "blktrace_pid" ];then
              pstree -p ${pid} | awk -F"[()]" '{for(i=0;i<=NF;i++)if($i~/([0-9])$/)print $i}' | xargs kill -2 2>/dev/null
           else
              pstree -p ${pid} | awk -F"[()]" '{for(i=0;i<=NF;i++)if($i~/([0-9])$/)print $i}' | xargs kill -9 2>/dev/null
           fi
       done
       rm -f ${STAT_PID_FILE}
   fi
   echo "stop stat perf success"
else
   echo "sh stat_perf.sh [start|stop] [output_file_prefix] &"
fi

文章目录