はじめに
Cisco機器のshow interfaceを定期的に採取して調査する必要があったので、
Pythonで試行錯誤してみたアウトプットです。
目的
show interfaceを定期的に出力したテキストファイルから
各種カウンターを取り出して表形式で出力する。
showコマンド採取時のclockも一緒に取得したい。
Pythonスクリプトの作成
メイン処理
main.py
# !/usr/bin/env python
if __name__ == '__main__': # スクリプトを直接実行時は__name__に__main__が自動で入る
os.chdir(os.path.dirname(os.path.abspath(__file__))) #カレントを実行ファイルのフォルダに移動
hdr_list = ['Time' , 'CPU(5sec)' , 'Port' , 'In-Traffic(bps)' , 'Out-Traffic(bps)' , 'In-Packets' , 'Out-Packets' , 'Out-Drop' ,
'In Error' , 'CRC(In)' , 'Frame(In)' , 'Over(In)' , 'Ignor(In)' ,
'Out Error' , 'Collisions(Out)' , 'IF-Reset(Out)' , '']
counter_list = ['-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-']
rows_txt = ''
file_paths = files_select()
try:
for file_path in file_paths:
with open(file_path , 'r') as f:
show_flag = False # show intを見つけた時True
port_flag = False # Port情報を収集するときTrue
row_count = 1
file_name = os.path.basename(file_path)
# 1行づつ読込
for line in f:
# show intを見つけたらホスト名をピックアップ
if ( re.match(r'(\S+)#sho?w? (int|interfaces?)$' , line) ):
hostname = re.match(r'(\S+)#sho?w? (int|interfaces?)$' , line)
h_name = hostname.group(1)
show_flag = True
# show intを見つけたらxlsxファイルを作成
if ( row_count == 1 ):
xlsx_temp_create(file_name)
wb = OPP.load_workbook('{0}.xlsx'.format(file_name))
sheet = wb['show interface']
continue
elif ( show_flag and re.search(r'Load for five secs: (\S+)\/(\S+);' , line) ):
cpu = re.search(r'Load for five secs: (\S+)\/(\S+);' , line)
cpu5sec = '{0}/{1}'.format(cpu.group(1) , cpu.group(2))
continue
elif ( show_flag and re.search(r'Time source is NTP, (\S+) ' , line) ):
ntp = re.search(r'Time source is NTP, (\S+) ' , line)
continue
elif ( show_flag and re.match(r'(\S+) is ' , line) ):
# 1ポート目
if ( row_count == 1 ):
interface = re.match(r'(\S+) is ' , line)
port_flag = True
row_count += 1
counter_list[0] = ntp.group(1)
counter_list[1] = cpu5sec
counter_list[2] = interface.group(1)
continue
# 2ポート目以降
else:
counter_list.append('')
# ワークシート、データのリスト、入力行数
xlsx_write(sheet , counter_list , row_count)
# 初期化して再度カウント
counter_list = ['-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-']
interface = re.match(r'(\S+) is ' , line)
port_flag = True
row_count += 1
counter_list[0] = ntp.group(1)
counter_list[1] = cpu5sec
counter_list[2] = interface.group(1)
continue
elif ( port_flag and re.search(r'5 minute input rate (\S+) bits/sec, (\S+) packets/sec' , line) ):
in_count = re.search(r'5 minute input rate (\S+) bits/sec, (\S+) packets/sec' , line)
counter_list[3] = in_count.group(1)
continue
elif ( port_flag and re.search(r'5 minute output rate (\S+) bits/sec, (\S+) packets/sec' , line) ):
out_count = re.search(r'5 minute output rate (\S+) bits/sec, (\S+) packets/sec' , line)
counter_list[4] = out_count.group(1)
continue
elif ( port_flag and re.search(r' (\S+) packets input, (\S+) bytes' , line) ):
in_total = re.search(r' (\S+) packets input, (\S+) bytes' , line)
counter_list[5] = in_total.group(1)
continue
elif ( port_flag and re.search(r' (\S+) packets output, (\S+) bytes' , line) ):
out_total = re.search(r' (\S+) packets output, (\S+) bytes' , line)
counter_list[6] = out_total.group(1)
continue
elif ( port_flag and re.search(r'Total output drops: (\S+)' , line) ):
out_drop = re.search(r'Total output drops: (\S+)' , line)
counter_list[7] = out_drop.group(1)
continue
elif ( port_flag and re.search(r' (\S+) input errors, (\S+) CRC, (\S+) frame, (\S+) overrun, (\S+) ignored' , line) ):
in_errors = re.search(r' (\S+) input errors, (\S+) CRC, (\S+) frame, (\S+) overrun, (\S+) ignored' , line)
counter_list[8] = in_errors.group(1)
counter_list[9] = in_errors.group(2)
counter_list[10] = in_errors.group(3)
counter_list[11] = in_errors.group(4) # 処理能力超過によりバッファに送れなかったパケット
counter_list[12] = in_errors.group(5) # バッファ不足による破棄
continue
elif ( port_flag and re.search(r' (\S+) output errors, (\S+) interface resets' , line) ):
out_errors_svi = re.search(r' (\S+) output errors, (\S+) interface resets' , line)
counter_list[13] = out_errors_svi.group(1)
counter_list[15] = out_errors_svi.group(2)
continue
elif ( port_flag and re.search(r' (\S+) output errors, (\S+) collisions, (\S+) interface resets' , line) ):
out_errors = re.search(r' (\S+) output errors, (\S+) collisions, (\S+) interface resets' , line)
counter_list[13] = out_errors.group(1)
counter_list[14] = out_errors.group(2)
counter_list[15] = out_errors.group(3)
continue
elif ( show_flag and re.match(r'(\S+)#' , line) ):
#最終行の書き込み後フラグクリア
counter_list.append('')
# ワークシート、データのリスト、入力行数
xlsx_write(sheet , counter_list , row_count)
counter_list = ['-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-']
show_flag = False
port_flag = False
continue
else:
pass
# 保存
wb.save('{0}.xlsx'.format(file_name))
rows_txt += '{0}の出力行は{1}\n'.format(h_name , row_count - 1 )
except FileNotFoundError:
sys.exit()
TKM.showinfo('パース終了' , rows_txt)
ファイルのパスを取得
files_select.py
def files_select():
try:
fTyp = [('' , '.txt') , ('' , '.log')]
current = os.path.abspath(os.path.dirname(__file__))
TKM.showinfo('ログ選択' , 'show interfaceのログファイルを選択')
file_path = TKF.askopenfilenames(filetypes = fTyp , initialdir = current) # 複数時はaskopenfilenames
file_paths = list(file_path)
return file_paths
except FileNotFoundError:
pass
xlsxへの書き込み
xlsx_temp_create.py
# xlsxのテンプレート作成
def xlsx_temp_create(file_name):
wb = OPP.Workbook()
wb.create_sheet(index = 0 , title = 'show interface')
sheet = wb['show interface']
# 網掛け指定
blue = PatternFill(patternType = 'solid' ,
fgColor='0066FF' ,
bgColor='0066FF')
for col_ptn in ['A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'I' ,
'J' , 'K' , 'L' , 'M' , 'N' , 'O' , 'P']:
sheet.column_dimensions[col_ptn].width = 16 # セル幅
sheet[col_ptn + '1'].fill = blue # 網掛け
sheet.freeze_panes = 'A2' # セル固定
# ワークシート、データのリスト、入力行数
xlsx_write(sheet , hdr_list , 1)
# 保存
save = True
while ( save == True ):
try:
wb.save('{0}.xlsx'.format(file_name))
save = False
except PermissionError:
TKM.showinfo('Error' , 'xlsxファイルを閉じてください')
xlsx_write.py
# xlsx書込み
def xlsx_write(sheet , col_list , r):
font = Font(name = 'メイリオ' ,
size = 9 ,
bold = False ,
italic = False ,
underline = 'none',
strike = False,
color = 'FF000000')
for col in range(1 , len(col_list)): # 1から入力カラム値まで記載
c = col - 1 # リストインデックスは-1する(0開始)
sheet.cell(row = r , column = col).value = col_list[c] # 行row_count 列1からcol_maxまで
sheet.cell(row = r , column = col).font = font # フォント合わせ
xlsx_temp_create.py
# xlsx書込み
def xlsx_write(sheet , col_list , r):
font = Font(name = 'メイリオ' ,
size = 9 ,
bold = False ,
italic = False ,
underline = 'none',
strike = False,
color = 'FF000000')
for col in range(1 , len(col_list)): # 1から入力カラム値まで記載
c = col - 1 # リストインデックスは-1する(0開始)
sheet.cell(row = r , column = col).value = col_list[c] # 行row_count 列1からcol_maxまで
sheet.cell(row = r , column = col).font = font # フォント合わせ
~~~
# 更新履歴
2020/3/5
matchからsearchに変更、複数ファイルを選択できるように変更