telnetlib 経由の AS400 システムへの Telnet 接続 (Python)

telnetlib 経由の AS400 システムへの Telnet 接続 (Python)

私は、telnetlib (Python) を使用して、AS/400 サーバーと通信するための telnet クライアント (ポート 23) を作成します。telnet コマンドを使用した通信は問題ありませんが、telnetlib を使用するとメッセージが表示されません。

これが私のコードです:

import getpass
import sys
import telnetlib

HOST = raw_input("HOST : ")
user = raw_input("Enter your remote account: ")
password = getpass.getpass()


try:
    tn = telnetlib.Telnet(HOST)
    tn.read_until("User..... ")
    tn.write(user + "\r")
    tn.read_until("Password..... ")
    tn.write(password + "\r")
    print tn.read_all()
except:
    print "Error"

ありがとう。

答え1

IBM は名前を変更する習慣があります。おそらく、あなたが話しているマシンは、OS/400 を実行する AS/400 ではないでしょう。IBM は 2000 年以降、AS/400 を出荷していません。製品ラインは iSeries システムに置き換えられ (または、見方によっては名前が変更されました)、その後 System i、i5 になりましたが、OS は OS/400 のままでした。ハードウェア製品ラインは pSeries システムと統合され、Power Systems になりました。OS は i5/OS になり、最新のリリース 7.1 では正式に「IBM i」となっています。次のハードウェア世代である Pure Systems でも、IBM i OS を実行できます。したがって、サーバーは実際には System i または Power System である可能性がありますが、IT スタッフはそれらを AS/400 と呼び続け、AS/400 であると考えている場合さえあります。グループとして、この製品ラインの系統は、IBM のミッドレンジ システムと呼ばれることがよくあります。

IBM ミッドレンジ システムは、当初 IBM モデル 5250 端末を採用していました。その後のモデルでも、5250 プロトコルと呼ばれるプロトコルが使用されていました。これは、IBM メインフレームで使用されている 3270 プロトコルといくつかの点で似ています。これはブロック指向のプロトコルで、通常は一度に画面全体を送信し、文字の元の色に基づいて口語的に「グリーン スクリーン」と呼ばれることがよくあります。サーバーが VTxxx telnet を使用するように構成されている可能性はありますが、おそらく可能性は低いでしょう。ただし、TN5250 はほぼ確実にサポートされています。代わりに、それを使用して接続してみてください。

答え2

AS/400 接続を *nix telnet 接続のように扱うことはできません。read_until() を使用する代わりに、read_very_eager() を使用して画面全体 (カーソルを "User...." フィールドの先頭に配置する ANSI エスケープ シーケンスを含む) を取得し、次に手動でログインする場合に入力する内容を正確に write() してください。また、接続後にログイン画面を表示するには、最初に改行文字を入力する必要があることもわかりました。なぜそうなるのかはわかりませんが、私の場合はこれでうまくいきました。

import getpass
import sys
import telnetlib

HOST = raw_input("HOST : ")
user = raw_input("Enter your remote account: ")
password = getpass.getpass()


try:
    tn = telnetlib.Telnet(HOST)
    tn.write('\n')
    tn.read_very_eager()
    tn.write(user)
    tn.write('\t')  # tab into the next field
    tn.write(password)
    tn.write('\r')  # 'enter' key
except:
    print "Error"

最後にもう 1 つ: AS/400 は画面の最後に EOF 文字を送信しないので、read_all() はハングして戻らなくなることに注意してください。read_until() を使用することもできますが、サーバーから返されるデータは分割され、ANSI エスケープ シーケンスが満載である可能性があるため、必要なデータが見つかる保証はありません。明らかな解決策は、read_very_eager() を while ループに配置し、read_very_eager() が空の文字列を返したときに終了するようにすることです。ただし、これには独自の問題があり、サーバーは、次のフル スクリーンに移動する前に、さまざまなステータス メッセージやその他の部分的なスクリーンを返す可能性があります。唯一の完全な解決策は、サーバーから返されるデータを継続的に解析し、現在のスクリーンがどのようになっているかを追跡するか (つまり、ターミナル エミュレーションとスクリーン スクレイピング)、書き込みと読み取りの間に time.sleep() コマンドを追加することです。

答え3

以下は、あなたの質問にコメントで私が尋ねようとしていた質問です。そして、あなたがクロスポスト質問は Stack Overflow へ。クロスポストしないでください。

そこであなたが投稿したペーストビンコメントで。それが私のコメントを回答に変更するきっかけとなりました。

貼り付けボックスでは、AS/400 のプロンプトにピリオドの間にスペースが表示されます。質問のコードでは、ドットの間にスペースがありません。そこにスペースを入れると、コードが機能する可能性があります。


後世のために(この種の情報を事前に提供することで、適切な回答をより早く得られる可能性が高くなります):

AS/400 に正しい行末を送信していますか?

AS/400 はどの OS を実行していますか?

AS/400 の Telnet ログイン プロンプトには、本当にすべてのドットとその後にスペースが続くのでしょうか?

ウェルカムバナーなどが表示されることを期待していますか?

の前にコマンドを送信するとどうなりますかread_all?

AS/400 のログには何が記録されていますか?

答え4

Python Expect(pexpect)モジュールを試してください。パスマス.pyスクリプトを例として示します。これは pexpect モジュールにも含まれている必要があります。

これは未テストスクリプトの修正:

import getpass
import pexpect
import sys

HOST = raw_input("HOST : ")
user = raw_input("Enter your remote account: ")
password = getpass.getpass()


try:
    tn = pexpect.spawn('telnet %s'%(HOST))

    tn.logfile = file ("LOG.TXT","wb")

    i = tn.expect([pexpect.TIMEOUT, '[Uu]ser..... '])
    if i == 0: # Timeout
        print 'ERROR!'
        print 'telnet could not login. Here is what telnet said:'
        print tn.before, tn.after
        sys.exit (1)
    tn.sendline(user)
    tn.expect (['[Pp]assword..... '])
    tn.sendline(password)

except:
    print "Error"

関連情報