📞

telnet 接続中のリターンコードにご注意

2022/10/23に公開

はじめに

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