とは言っても、頭をフル回転させてコードを書く気力はなく、自宅の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 件のコメント:
コメントを投稿