とは言っても、頭をフル回転させてコードを書く気力はなく、自宅のciscoルータに対して、telnet試験をひたすら繰り返していた。
今まであまり気にしていなかったが、pythonにおけるtelnetlibで気づいたことがあったのでメモしておく。
telnetlibではtelnetの戻り値を指定することのできるread_until関数が用意されているが、ciscoルータなどのコマンド入力をシーケンシャルに進めて行く場合、このread_untilで"#"などを待ち、次のステップに進むなどの書き方がスムーズだ。
例えば、先日書き直しをしたLoggetのciscoルータアクセス部分のコードは以下のようなイメージである。
class RemoteAccess:
"remote access class"
def __init__(self,address,login_pass,login_id,en_pass):
self.address = address
self.login_pass = login_pass
self.login_id = login_id
self.en_pass = en_pass
def TnetNoIdCisco(self):
"telnet without login ID"
now = datetime.datetime.now()
nowstr = str(now.strftime("%Y%m%d-%H%M(%S)"))
logname = nowstr + '_' + self.address + '_log.txt'
tn = telnetlib.Telnet(self.address, 23, 5)
log = open(logname, 'wb')
tn.read_until('assword:',2)
tn.write(self.login_pass + '\r\n')
tn.read_until('>',2)
tn.write('en' + '\r\n')
tn.read_until('assword:',2)
tn.write(self.en_pass + '\r\n')
tn.read_until('#',2)
tn.write('ter len 0' + '\r\n')
ccom = open('cisco_show.txt','r')
ccoms = ccom.readline().replace(('\n'or'\r'),'\r\n')
ccli = ccoms.rstrip('\n')
while ccli:
tn.write(ccli.encode('ascii') + '\r\n')
ccoms = ccom.readline().replace(('\n'or'\r'),'\r\n')
ccli = ccoms.rstrip('\r\n')
tn.write('exit' + '\r\n')
output = tn.read_all()
log.write(output)
log.close()
贅肉がつきまくっていてちょっと恥ずかしいコードではあるものの、 ポイントはそこではなく、read_unitl関数の引数であるtimeout値である。
tn.read_until("#",2)
timeout値は必須の引数ではなく、空欄でも動作するため、これまでは特に指定していなかった。
しかし、実験を繰り返して行くうちにtimeoutを指定しないと複雑な処理に分岐させていった時に、処理がハングしてしまって、原因不明のフリーズが起きるときがあった。
色々とデバッグしつつパラメータを入れていったところ、read_until関数にtimeoutの引数を指定すれば、フリーズすることがなくなった。
0 件のコメント:
コメントを投稿