文件操作 - pcp-tapestat
返回文件管理
返回主菜单
删除本文件
文件: /usr/libexec/pcp/bin/pcp-tapestat
编辑文件内容
#!/usr/bin/env pmpython # Copyright (C) 2014-2016 Red Hat. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # tapestat Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # pylint: disable=C0103,R0914,R0902 """ Display tape I/O statistics """ import re import sys import signal from pcp import pmapi, pmcc from cpmapi import PM_TYPE_U64, PM_CONTEXT_ARCHIVE, PM_SPACE_KBYTE, PM_MODE_FORW # use default SIGPIPE handler to avoid broken pipe exceptions signal.signal(signal.SIGPIPE, signal.SIG_DFL) # Tape: r/s w/s kB_read/s kB_wrtn/s %Rd %Wr %Oa Rs/s Ot/s # These are the metrics tapestat (sysstat) shows and we will do the same # for starters # [root@nkshirsa sysstat]# ls /sys/class/scsi_tape/st0/stats/ -l # total 0 # in_flight # io_ns # other_cnt # read_byte_cnt # read_cnt # read_ns # resid_cnt # write_byte_cnt # write_cnt # write_ns TAPESTAT_METRICS = [ 'tape.dev.in_flight', 'tape.dev.io_ns', 'tape.dev.other_cnt', 'tape.dev.read_byte_cnt', 'tape.dev.read_cnt', 'tape.dev.read_ns', 'tape.dev.resid_cnt', 'tape.dev.write_byte_cnt', 'tape.dev.write_cnt', 'tape.dev.write_ns'] def aggregate(method, aggr_value, value): if method == 'sum': aggr_value += value elif method == 'avg': aggr_value += value elif method == 'min': if aggr_value > value: aggr_value = value elif method == 'max': if aggr_value < value: aggr_value = value else: raise pmapi.pmUsageErr return aggr_value class TapestatReport(pmcc.MetricGroupPrinter): Hcount = 0 def timeStampDelta(self, group): s = group.timestamp.tv_sec - group.prevTimestamp.tv_sec u = group.timestamp.tv_usec - group.prevTimestamp.tv_usec # u may be negative here, calculation is still correct. return (s + u / 1000000.0) def instlist(self, group, name): return dict(map(lambda x: (x[1], x[2]), group[name].netValues)).keys() def curVals(self, group, name): return dict(map(lambda x: (x[1], x[2]), group[name].netValues)) def prevVals(self, group, name): return dict(map(lambda x: (x[1], x[2]), group[name].netPrevValues)) def report(self, manager): regex = TapestatOptions.Rflag if regex == '': regex = '.*' aggr = TapestatOptions.Gflag if aggr and aggr not in ('sum', 'avg', 'min', 'max'): print("Error, -G aggregation method must be one of 'sum', 'avg', 'min' or 'max'") raise pmapi.pmUsageErr precision = TapestatOptions.Pflag if precision < 0 or precision > 10 : print("Precision value must be between 0 and 10") raise pmapi.pmUsageErr subtree = 'tape.dev' group = manager["tapestat"] if group[subtree + '.read_cnt'].netPrevValues == None: # need two fetches to report rate converted counter metrics #print "found none, returning" return instlist = self.instlist(group, subtree + '.read_cnt') dt = self.timeStampDelta(group) timestamp = group.contextCache.pmCtime(int(group.timestamp)).rstrip() c_r = self.curVals(group, subtree + '.read_cnt') p_r = self.prevVals(group, subtree + '.read_cnt') c_w = self.curVals(group, subtree + '.write_cnt') p_w = self.prevVals(group, subtree + '.write_cnt') c_rkb = self.curVals(group, subtree + '.read_byte_cnt') p_rkb = self.prevVals(group, subtree + '.read_byte_cnt') c_wkb = self.curVals(group, subtree + '.write_byte_cnt') p_wkb = self.prevVals(group, subtree + '.write_byte_cnt') # calculate the percentage waits c_rpw = self.curVals(group, subtree + '.read_ns') p_rpw = self.prevVals(group, subtree + '.read_ns') c_wpw = self.curVals(group, subtree + '.write_ns') p_wpw = self.prevVals(group, subtree + '.write_ns') c_opw = self.curVals(group, subtree + '.io_ns') p_opw = self.prevVals(group, subtree + '.io_ns') p_resid = self.prevVals(group, subtree + '.resid_cnt') c_resid = self.curVals(group, subtree + '.resid_cnt') p_other = self.prevVals(group, subtree + '.other_cnt') c_other = self.curVals(group, subtree + '.other_cnt') if precision == 1: utilspace=precision+5 avgrqszspace=precision+7 awaitspace=precision+6 rrqmspace=precision+5 wrqmspace=precision+5 headfmtavgspace=precision+7 headfmtquspace=precision+7 elif precision == 0: utilspace=precision+5 avgrqszspace=precision+8 awaitspace=precision+7 rrqmspace=precision+6 wrqmspace=precision+6 headfmtavgspace=avgrqszspace headfmtquspace=precision+8 else: utilspace=precision+5 avgrqszspace=precision+6 awaitspace=precision+5 rrqmspace=precision+5 wrqmspace=precision+5 headfmtavgspace=avgrqszspace headfmtquspace=precision+6 if "t" in TapestatOptions.xflag: headfmt = "%-24s %-12s %*s %*s %*s %*s %*s %*s %*s %*s %*s" valfmt = "%-24s %-12s %*.*f %*.*f %*d %*d %*.*f %*.*f %*.*f %*.*f %*.*f" else: headfmt = "%-12s %*s %*s %*s %*s %*s %*s %*s %*s %*s" valfmt = "%-12s %*.*f %*.*f %*d %*d %*.*f %*.*f %*.*f %*.*f %*.*f" tmpspace = precision+5 if precision == 0 : tmpspace = tmpspace +1 if "h" not in TapestatOptions.xflag: self.Hcount += 1 if self.Hcount == 24: self.Hcount = 1 if self.Hcount == 1: if "t" in TapestatOptions.xflag: heading = ('# Timestamp', 'Device',tmpspace - 1, 'r/s',tmpspace, 'w/s',tmpspace, 'kb_r/s',tmpspace, 'kb_w/s', tmpspace, 'r_pct',tmpspace,'w_pct',tmpspace, 'o_pct',tmpspace,'Rs/s',tmpspace,'o_cnt') else: heading = ('# Device',tmpspace, 'r/s',tmpspace, 'w/s',tmpspace, 'kb_r/s',tmpspace, 'kb_w/s', tmpspace, 'r_pct',tmpspace,'w_pct',tmpspace, 'o_pct',tmpspace,'Rs/s',tmpspace,'o_cnt') print(headfmt % heading) if p_r == {} or p_w == {} or p_rkb == {} or p_wkb == {} or \ p_rpw == {} or p_wpw == {} or p_opw == {} or \ p_resid == {} or p_other == {}: # no values for some metric (e.g. near start of archive) if "t" in TapestatOptions.xflag: print(headfmt % (timestamp, 'NODATA',rrqmspace -1, '?',wrqmspace, '?',precision+5, '?',precision+5, '?',precision+5,\ '?',precision+5, '?',headfmtavgspace -1 , '?',headfmtquspace -1, '?', precision+5, '?')) return #don't we need an else here to print ?'s for non timestamp flag too ? try: if TapestatOptions.Gflag: aggr_r = aggr_w = aggr_rkb = aggr_wkb = aggr_actual_rpw = aggr_actual_wpw = 0.0 aggr_actual_opw = aggr_resid_cnt = aggr_o_cnt = 0.0 aggr_count = 0 for inst in sorted(instlist): # basic stats r = (c_r[inst] - p_r[inst]) / dt w = (c_w[inst] - p_w[inst]) / dt rkb = (c_rkb[inst] - p_rkb[inst]) / dt / 1000.0 # bytes to kb wkb = (c_wkb[inst] - p_wkb[inst]) / dt / 1000.0 #calculate and convert from nano seconds rpw = 100 * (c_rpw[inst] - p_rpw[inst])/ 10.0**9 / dt wpw = 100 * (c_wpw[inst] - p_wpw[inst]) / 10.0**9 / dt actual_rpw = rpw actual_wpw = wpw opw = 100 * (c_opw[inst] - p_opw[inst]) / 10.0**9 / dt actual_opw = opw resid_cnt = (c_resid[inst] - p_resid[inst]) / dt / 1000.0 #The number of I/Os, expressed as the number per second averaged over the interval, that were included as "other" is o_cnt o_cnt = (c_other[inst] - p_other[inst]) / dt / 1000.0 device = inst # prepare name for printing badcounters = r < 0 or w < 0 or rkb < 0 or wkb < 0 or rpw < 0 or wpw < 0 or opw < 0 or resid_cnt < 0 or o_cnt < 0 if "t" in TapestatOptions.xflag: if badcounters: print(headfmt % (timestamp, device,rrqmspace, '?',wrqmspace, '?',precision+5, '?',precision+4, '?',precision+6,\ '?',precision+6, '?',headfmtavgspace, '?',headfmtquspace, '?', precision+5, '?')) else: if TapestatOptions.Rflag and re.search(regex,device) == None: continue if TapestatOptions.Gflag: aggr_count += 1 if "noidle" in TapestatOptions.xflag: if rkb == 0 and wkb == 0 and r == 0 and w == 0 : continue if not TapestatOptions.Gflag: print(valfmt % (timestamp, device,tmpspace,precision,r,tmpspace, precision, w,tmpspace,rkb,tmpspace, wkb, tmpspace,precision,actual_rpw,tmpspace,precision,actual_wpw, tmpspace,precision,actual_opw,tmpspace,precision,resid_cnt,tmpspace,precision,o_cnt)) else: if badcounters: print(headfmt % (device,rrqmspace, '?',wrqmspace, '?',precision+5, '?',precision+4, '?',precision+6,\ '?',precision+6, '?',headfmtavgspace, '?',headfmtquspace, '?', precision+5, '?',awaitspace, '?',\ awaitspace, '?',utilspace, '?')) else: if TapestatOptions.Rflag and re.search(regex,device) == None: continue if TapestatOptions.Gflag: aggr_count += 1 if "noidle" in TapestatOptions.xflag: if rkb == 0 and wkb == 0 and r == 0 and w == 0 : continue if not TapestatOptions.Gflag: # print(valfmt % (device,tmpspace, precision, aggr_r,tmpspace,precision, aggr_w,tmpspace, aggr_rkb,tmpspace, aggr_wkb, tmpspace,precision,actual_rpw,tmpspace,precision,actual_wpw)) print(valfmt % (device,tmpspace,precision,r,tmpspace, precision, w,tmpspace,rkb,tmpspace, wkb, tmpspace,precision,actual_rpw,tmpspace,precision,actual_wpw, tmpspace,precision,actual_opw,tmpspace,precision,resid_cnt,tmpspace,precision,o_cnt)) if TapestatOptions.Gflag and not badcounters: aggr_r = aggregate(aggr, aggr_r, r) aggr_w = aggregate(aggr, aggr_w, w) aggr_rkb = aggregate(aggr, aggr_rkb, rkb) aggr_wkb = aggregate(aggr, aggr_wkb, wkb) aggr_actual_rpw = aggregate(aggr, aggr_actual_rpw, actual_rpw) aggr_actual_wpw = aggregate(aggr, aggr_actual_wpw, actual_wpw) aggr_actual_opw = aggregate(aggr, aggr_actual_opw, actual_opw) aggr_resid_cnt = aggregate(aggr, aggr_resid_cnt, resid_cnt) aggr_o_cnt = aggregate(aggr, aggr_o_cnt, o_cnt) # end of loop if TapestatOptions.Gflag: if TapestatOptions.Gflag == 'avg' and aggr_count > 0: aggr_r /= aggr_count aggr_w /= aggr_count aggr_rkb /= aggr_count aggr_wkb /= aggr_count aggr_actual_rpw /= aggr_count aggr_actual_wpw /= aggr_count aggr_actual_opw /= aggr_count aggr_resid_cnt /= aggr_count aggr_o_cnt /= aggr_count # report aggregate values - the 'device' here is reported as the regex used for the aggregation device = '%s(%s)' % (aggr, regex) if "t" in TapestatOptions.xflag: print(valfmt % (timestamp, device,tmpspace, precision, aggr_r,tmpspace,precision, aggr_w,tmpspace, aggr_rkb,tmpspace, aggr_wkb, tmpspace,precision,aggr_actual_rpw,tmpspace,precision,aggr_actual_wpw,tmpspace,precision,aggr_actual_opw , tmpspace,precision,aggr_resid_cnt,tmpspace,precision,aggr_o_cnt)) else: print(valfmt % (device,tmpspace, precision, aggr_r,tmpspace,precision, aggr_w,tmpspace, aggr_rkb,tmpspace, aggr_wkb, tmpspace,precision,aggr_actual_rpw,tmpspace,precision,aggr_actual_wpw,tmpspace,precision,aggr_actual_opw , tmpspace,precision,aggr_resid_cnt,tmpspace,precision,aggr_o_cnt)) except KeyError: # instance missing from previous sample pass class TapestatOptions(pmapi.pmOptions): # class attributes xflag = [] uflag = None Pflag = 2 Rflag = "" Gflag = "" def checkOptions(self, manager): if TapestatOptions.uflag: if manager._options.pmGetOptionInterval(): print("Error: -t incompatible with -u") return False if manager.type != PM_CONTEXT_ARCHIVE: print("Error: -u can only be specified with -a archive") return False return True def extraOptions(self, opt, optarg, index): if opt == "x": TapestatOptions.xflag += optarg.replace(',', ' ').split(' ') elif opt == "u": TapestatOptions.uflag = True elif opt == "P": TapestatOptions.Pflag = int(optarg) elif opt == "R": TapestatOptions.Rflag = optarg elif opt == "G": TapestatOptions.Gflag = optarg # all this stuff needs changes but leaving it as it is for now, anyway we will first get # it working without any arguments def __init__(self): pmapi.pmOptions.__init__(self, "A:a:D:G:h:O:P:R:S:s:T:t:uVZ:z?x:") self.pmSetOptionCallback(self.extraOptions) self.pmSetLongOptionHeader("General options") self.pmSetLongOptionAlign() self.pmSetLongOptionArchive() self.pmSetLongOptionDebug() self.pmSetLongOption("aggregate", 1, "G", "method", "aggregate values for devices matching -R regex using 'method' (sum, avg, min or max)") self.pmSetLongOptionHost() self.pmSetLongOptionOrigin() self.pmSetLongOption("precision", 1, "P", "N", "N digits after the decimal separator") self.pmSetLongOption("regex", 1, "R", "pattern", "only report for devices names matching pattern, e.g. 'sd[a-zA-Z]+'. See also -G.") self.pmSetLongOptionStart() self.pmSetLongOptionSamples() self.pmSetLongOptionFinish() self.pmSetLongOptionInterval() self.pmSetLongOption("no-interpolation", 0, "u", "", "disable interpolation mode with archives") self.pmSetLongOptionVersion() self.pmSetLongOptionTimeZone() self.pmSetLongOptionHostZone() self.pmSetLongOptionHelp() self.pmSetLongOptionHeader("Extended options") self.pmSetLongOption("", 1, 'x', "LIST", "comma separated extended options: [[t],[h],[noidle]]") self.pmSetLongOptionText("\t\tt\tprecede every line with a timestamp in ctime format"); self.pmSetLongOptionText("\t\th\tsuppress headings"); self.pmSetLongOptionText("\t\tnoidle\tdo not display idle devices"); if __name__ == '__main__': try: opts = TapestatOptions() manager = pmcc.MetricGroupManager.builder(opts, sys.argv) if not opts.checkOptions(manager): raise pmapi.pmUsageErr if TapestatOptions.uflag: # -u turns off interpolation manager.pmSetMode(PM_MODE_FORW, manager._options.pmGetOptionOrigin(), 0) missing = manager.checkMissingMetrics(TAPESTAT_METRICS) if missing != None: sys.stderr.write('Error: not all required metrics are available\nMissing: %s\n' % (missing)) sys.exit(1) manager["tapestat"] = TAPESTAT_METRICS #print "calling TapestatReport()" manager.printer = TapestatReport() sts = manager.run() sys.exit(sts) except pmapi.pmErr as error: sys.stderr.write('%s: %s\n' % (error.progname(), error.message())) except pmapi.pmUsageErr as usage: usage.message() sys.exit(1) except KeyboardInterrupt: pass
修改文件时间
将文件时间修改为当前时间的前一年
删除文件