telnet 接続中のリターンコードにご注意
はじめに
telnet を利用してコマンドを送信する場合、使用すべきリターンコードは <CR><LF>
か <CR><NUL>
のどちらかのようです。安直に <LF>
単独で送ってもうまくいきません。
このことは、telnet コマンドのマニュアル にも説明されています(toggle crlf
の説明部分)。
通常、何らかの telnet クライアントを使用して接続している場合、普通に Enter キーを押せば現在のモードに従って適切なリターンコードが送られるので、この点を意識する必要は特に無いのだと思いますが、自作のスクリプトなどから低レイヤの機能を使って telnet に接続する場合は、この点を自分で意識しなければならないことがあります。
Python の telnetlib のサンプルコード
なぜこのような記事を書いたのかというと、Python で telnetlib を利用したときに少しハマってしまったからです。
先日お仕事で初めて telnet 接続する機会があり、公式に紹介されている サンプルコード を流用して試してみたのですが、うまくいかなくて躓きました。
import getpass
import telnetlib
HOST = "localhost"
user = input("Enter your remote account: ")
password = getpass.getpass()
tn = telnetlib.Telnet(HOST)
tn.read_until(b"login: ")
tn.write(user.encode('ascii') + b"\n")
if password:
tn.read_until(b"Password: ")
tn.write(password.encode('ascii') + b"\n")
tn.write(b"ls\n")
tn.write(b"exit\n")
print(tn.read_all().decode('ascii'))
もちろんコードの細部は接続先の機器に合わせて修正していたのですが、このサンプルコードでいうところの tn.read_until(b"Password: ")
の部分で無限待ちになってしまうという現象が発生してしまいました。いろいろ試したところ、直前の tn.write(user.encode('ascii') + b"\n")
の末尾を \n
から \r
に変更したらうまく動作したので、原因に気付くことができました(もちろん、他の write
も修正が必要でした)。
あとがき
試行錯誤しているときに色々とググってみたのですが、同じことで躓いたという記録がヒットしなかったので、この記事を残しておこうと思いました。
サンプルコードを流用してサクッと問題解決しようなどと横着してはダメですね……。きちんと調べないとハマってしまうことがあるのだと、改めて思い知らされました。
Discussion