Einloggen unter Telnet nicht möglich

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Auf der Arbeit läuft auf einem Linuxrechner ein kommerzielles Programm, das im weitesten Sinne Datenbankfunktionen ausübt. Zwei weitere Arbeitsplätze sind seriell angeschlossen, an einem ein ANSI-Terminal, am anderen ein Windows-PC mit Terminal-Programm. Um zusätzliche Funktionen zu erhalten, habe ich verschiedene Python-Scripte geschrieben. Eins davon loggt sich automatisch ein, ruft im "Datenbankprogramm" ein Menü auf, das seitenweise eine Statistik auf den Windows-PC ausgibt. Die ANSI-Daten werden abgefangen, nach Übertragung einer Seite eine neue Seite angefordert und schließlich aus den Daten eine für mich nützlichere Statistik erstellt. Das andere Script ist ein komplettes ANSI-Terminal unter Tkinter, das verschiedene Spezialfunktionen bietet, wie z.B. mehrere Datenbanksuchen nacheinander ausführen, deren Ergebnisse zusammenfassen, anzeigen und speichern usw... Dabei werden oft Tastatureingaben nachgeahmt und der Menübaum des "Datenbankprogramms" durchwandert, als wenn das Programm von Hand über den Terminal bedient würde.
Jetzt zum Thema:
Zukünftig sollen die Arbeitsplätze vernetzt werden. Auf den Windows-PC werden die Daten dann wohl über einen X-Server für Windows dargestellt werden (Textdarstellung). Bisher liefen die Ein- und Ausgaben der Scripte ja über die serielle Schnittstelle. Kann ich die Daten im LAN ebenso abfangen und Eingaben machen ähnlich wie über die serielle Schnittstelle? Gibt es hierfür fertige Module ähnlich wie Pyserial? Ich habe leider praktisch keine Ahnung von Netzwerkprogrammierung.
MfG
HWK
Zuletzt geändert von HWK am Freitag 22. Dezember 2006, 12:12, insgesamt 3-mal geändert.
BlackJack

HWK hat geschrieben:Zukünftig sollen die Arbeitsplätze vernetzt werden. Auf den Windows-PC werden die Daten dann wohl über einen PC-X-Server dargestellt werden (Textdarstellung). Bisher liefen die Ein- und Ausgaben der Scripte ja über die serielle Schnittstelle. Kann ich die Daten im LAN ebenso abfangen und Eingaben machen ähnlich wie über die serielle Schnittstelle? Gibt es hierfür fertige Module ähnlich wie Pyserial? Ich habe leider praktisch keine Ahnung von Netzwerkprogrammierung.
Was ist "PC-X-Server"? Ein spezielles Produkt, oder reden wir über einen X-Server für Windows?

Wenn der Linux-Rechner per LAN angebunden ist, kannst Du dann nicht eine Telnet- oder SSH-Verbindung aufbauen und die dann per Skript steuern?
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Ja, wir reden über einen X-Server für Windows.
Wie gesagt, ich habe keine Ahnung über Netzwerkprogrammierung. Wie würde das mit Telnet bzw. SSH zumindest prinzipiell funktionieren?
MfG
HWK
BlackJack

So ganz allgemein und manuell unter Linux: Du hast ein Terminalprogramm, das ein Terminal emuliert (xterm, gterm, konsole, ...) und tippst dort ``ssh user@rechner`` ein. Dann wirst Du nach dem Passwort gefragt und danach startet die Login-Shell auf dem entfernten Rechner und Du kannst Programme in dem Terminal starten als wären sie auf Deinem lokalen Rechner.

Wenn Du allerdings einen X-Server auf dem Windows-PC hast, dann denke ich mal das alles auf dem Linux-Server läuft, also auch das Terminalprogramm in dem die Textanwendung läuft. Der Windows-Rechner ist dann nur für die Darstellung des Fensterrahmens zuständig, alles *darin* kommt vom Linux-Rechner.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Genau. Kann ich dann aber das, was vom Linux-Rechner kommt in einem Script abfangen und selbst verwerten? Wie kann ich die Eingaben in dem X-Server-Fenster, die an den Linux-Rechner gesandt werden, in einem Script emulieren?
Schon mal vielen Dank
HWK
BlackJack

HWK hat geschrieben:Genau. Kann ich dann aber das, was vom Linux-Rechner kommt in einem Script abfangen und selbst verwerten? Wie kann ich die Eingaben in dem X-Server-Fenster, die an den Linux-Rechner gesandt werden, in einem Script emulieren?
Die Eingaben auf der Windows-Seite kannst Du vielleicht noch emulieren, aber was vom Linux-Rechner zurückkommt sind X-Protokoll-Daten, d.h. recht Low-Level "Befehle" in einem Binärformat zum zeichnen von Fensterinhalten.

Kannst Du Dein Programm nicht auf dem Linux-Rechner direkt laufen lassen und dort das "Datenbank"-Programm steuern?
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Vielleicht. Ich kenne mich mit Linux aber nicht gut aus und möchte auch ungern auf dem Server "herumwerkeln", weil dort ja für die Arbeit essentielle Daten gespeichert sind. Nicht auszudenken, wenn diese irgendwie geschädigt würden oder das Programm nicht mehr liefe. Insofern wäre es schöner, wenn ich eine ähnliche Lösung wie bisher für die serielle Schnittstelle finden könnte.
Wie sehr low-level sind die an den X-Server übertragenen Daten denn? Sind denn zumindest die Zeichen noch erkennbar? Dann müßte doch ein Zugriff möglich sein. Beim ANSI-Terminal sind die Daten ja auch mit Escape-Sequenzen durchsetzt und es hat trotzdem funktioniert.
Noch mal auf Telnet, SSH zurückgekommen: Wäre es da möglich, auch vom Windows-Rechner das Programm auf dem Linux-Server zu starten und dessen Ausgaben abzufangen? Oder sind das dann auch wieder X-Ausgaben? Gibt es irgendwo eine Beschreibung über X-Windows?
Danke
HWK
BlackJack

HWK hat geschrieben:Vielleicht. Ich kenne mich mit Linux aber nicht gut aus und möchte auch ungern auf dem Server "herumwerkeln", weil dort ja für die Arbeit essentielle Daten gespeichert sind. Nicht auszudenken, wenn diese irgendwie geschädigt würden oder das Programm nicht mehr liefe. Insofern wäre es schöner, wenn ich eine ähnliche Lösung wie bisher für die serielle Schnittstelle finden könnte.
Naja, die bisherige Lösung ist doch grob gesprochen, dass Du ein Programm hast, das sich mit der Anwendung über `stdin` und `stdout` verbindet und quasi zeichenweise Daten austauscht. Das müsstest Du direkt auf dem Server doch auch machen können, ohne die serielle Verbindung dazwischen. Du müsstest Dich ein wenig mit "Pseudoterminals" (pty) beschäftigen, weil Du die benutzen musst, wenn das Programm denken soll es redet mit einem Terminal und nicht nur mit einer Pipe.
Wie sehr low-level sind die an den X-Server übertragenen Daten denn? Sind denn zumindest die Zeichen noch erkennbar? Dann müßte doch ein Zugriff möglich sein. Beim ANSI-Terminal sind die Daten ja auch mit Escape-Sequenzen durchsetzt und es hat trotzdem funktioniert.
Beim ANSI-Terminal haben die Daten und deren Reihenfolge aber einen direkten Bezug zu der Anwendung. Der X-Server weiss von der Bedeutung des Inhalts von Fenstern nichts. Der schickt nur Graphik-Anweisungen und -Daten über's Netz wie sie vom GUI-Toolkit vorgegeben werden, welches die Anwendung benutzt, die dargestellt werden soll.

Angenommen Du hast im Terminal ein Python-Programm:

Code: Alles auswählen

print 'line one\nline two'
Wenn das ausgeführt wird, landet die Ausgabe beim Terminalprogramm auf dem Linux-Server und das "malt" den Text in sein grafisches Fenster, welches auf dem Windows-Rechner dargestellt wird. Das kann beispielhaft zu folgendem Datenaustausch führen:

Male Zeichenkette "line one" an/ab Pixelposition (5,320)
Male Zeichenkette "line two" an/ab Pixelposition (5,330)

Dummerweise können dazwischen aber auch viele andere Sachen passieren. Zum Beispiel wird der Mauszeiger bewegt, darüber werden auch Daten in beide Richtungen ausgetauscht. Und wenn der Mauszeiger über einem Menüpunkt landet, wird der wahrscheinlich hervorgehoben. Dafür wird auch der Text von dem Menüpunkt übertragen. Und so weiter.
Noch mal auf Telnet, SSH zurückgekommen: Wäre es da möglich, auch vom Windows-Rechner das Programm auf dem Linux-Server zu starten und dessen Ausgaben abzufangen? Oder sind das dann auch wieder X-Ausgaben?
Nein das sind dann wieder nur die Textdaten. Das sollte möglich sein.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Naja, die bisherige Lösung ist doch grob gesprochen, dass Du ein Programm hast, das sich mit der Anwendung über `stdin` und `stdout` verbindet und quasi zeichenweise Daten austauscht. Das müsstest Du direkt auf dem Server doch auch machen können, ohne die serielle Verbindung dazwischen. Du müsstest Dich ein wenig mit "Pseudoterminals" (pty) beschäftigen, weil Du die benutzen musst, wenn das Programm denken soll es redet mit einem Terminal und nicht nur mit einer Pipe.
Ich habe das bisher mit Pyserial gelöst. Das hat ja wohl nichts direkt mit 'stdout' und 'stdin' zu tun. Das Hauptproblem, ein ähnliches Script für den Linuxserver zu entwickeln, sehe ich in meinen mangelnden Linux-Kenntnissen. Möglicherweise wäre deshalb doch die auf den ersten Blick umständlichere Variante auf dem Windows-PC die im Endeffekt für mich einfachere und v.a. sicherere.
Könntest Du mir denn ein Beispiel für die Telnet-/SSH-Variante andeuten, z.B. für den Aufruf eines Standardlinuxprogramms von einem Windows-PC aus?
Übrigens: Wie hätte ich statt 'Zitat:' die Überschrift 'BlackJack hat folgendes geschrieben:' hinbekommen?
Danke
HWK
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

HWK hat geschrieben:Übrigens: Wie hätte ich statt 'Zitat:' die Überschrift 'BlackJack hat folgendes geschrieben:' hinbekommen?
Mit [ quote="BlackJack" ] statt [ quote ], oder mit der Zitieren-Funktion:
Leonidas hat geschrieben:Blödsinn, wie immer ;)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

HWK hat geschrieben:Ich habe das bisher mit Pyserial gelöst. Das hat ja wohl nichts direkt mit 'stdout' und 'stdin' zu tun. Das Hauptproblem, ein ähnliches Script für den Linuxserver zu entwickeln, sehe ich in meinen mangelnden Linux-Kenntnissen. Möglicherweise wäre deshalb doch die auf den ersten Blick umständlichere Variante auf dem Windows-PC die im Endeffekt für mich einfachere und v.a. sicherere.
Hm, wenn Du daran so wenig wie möglich ändern möchtest, dann wär's vielleicht eine Überlegung wert den Linux-Server seriell mit sich selbst zu verbinden und das Python-Programm auf den Server zu packen und sich dort über die serielle Verbindung an das Datenbank-Programm zu wenden. Wenn Du auf dem Linux-Rechner einen VMWare Server installierst, dann könnte es sogar noch unter Windows laufen. :-)
Könntest Du mir denn ein Beispiel für die Telnet-/SSH-Variante andeuten, z.B. für den Aufruf eines Standardlinuxprogramms von einem Windows-PC aus?
So, in der Kommandozeile? Dann logge ich mich mal auf `zoom` ein:

Code: Alles auswählen

marc@s8n:~$ ssh bj@zoom.spline.de
Last login: Fri Nov 10 22:08:48 2006 from p54bff5bd.dip.t-dialin.net
Have a lot of fun...
bj@zoom:~> ls
bin  Desktop  evolution  KDesktop  Mail  public_html
bj@zoom:~> cal
   November 2006
So Mo Di Mi Do Fr Sa
          1  2  3  4
 5  6  7  8  9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30

bj@zoom:~> logout
Connection to zoom.spline.de closed.
marc@s8n:~$
Wie man sieht musste ich kein Passwort eingeben weil ich einen öffentlichen Schlüssel auf dem Rechner hinterlegt habe.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Ich sehe schon: Ich muß wohl erst einmal abwarten, bis das Netzwerk installiert ist, um dann einfach einmal ein paar Dinge auszuprobieren, insbesondere das mit Telnet/SSH. Ich möchte nämlich, falls irgendwie möglich, das Script auf dem Windows-Rechner laufen und den Linux-Server unangetastet lassen. Da würde ich mich als Hobbyprogrammierer auf jeden Fall wohler fühlen.
Danke trotzdem
HWK
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Hallo!
Es geht jetzt endlich weiter. Das Netzwerk ist installiert. Glücklicherweise ist Zugriff über Telnet möglich. Das funktioniert im Telnet-Programm von Windows XP sehr gut. Ich dachte also: Leichtes Spiel und nur geringe Änderungen nötig. Vielleicht sogar leichter durch read_until().
Aber weit gefehlt: Das Script versinkt in einer 'Endlosschleife'. Hier ein gekürztes Beispiel:

Code: Alles auswählen

#!/usr/bin/env python
# File: TelnetRead.py

from telnetlib import Telnet

HOST = 'xyz'

def TelnetOpen():
    try:
        tn = Telnet(HOST)
    except:
        return ErrPrint('Kann nicht mit %s verbinden!' % HOST.upper())
    print 'Mit %s verbunden' % HOST.upper()
    return tn

def TelnetRead(tn):
    tn.write('\r\n')
    tn.read_until('linux login: ')
    print 'Login'
    tn.write('programm\r\n')
    tn.read_until('Was soll ich tun? ')
    print 'Auswahl 1'
    tn.write('1\r\n')
#
# Weiterer Code
#
def ErrPrint(t):
    print t
    raw_input()
    return False

tn = TelnetOpen()
if tn:
    TelnetRead(tn)
Schluss ist bei der Ausgabe 'Login'. Wenn man eine

Code: Alles auswählen

print tn.read_some()
-Anweisung in Zeile 21 einfügt, zeigt die Ausgabe manchmal 'Invalid Login', obwohl dasselbe Login im Telnet-Programm von Windows XP funktioniert.

Variante 2:
Um einzelne Zeichen vom Netzwerk zu lesen, habe ich mir folgendes überlegt:

Code: Alles auswählen

#!/usr/bin/env python
# File: TelnetTest.py

'''Nur zu Testzwecken'''

from binascii import hexlify
from telnetlib import Telnet

HOST = 'xyz'

class MyTelnet(Telnet):
    def read(self):
        while True:
            print '1'
            string = self.read_some()
            print '2'
            for c in string:
                print c, hex(c)
                yield c

def TelnetOpen():
    try:
        tn = MyTelnet(HOST)
    except:
        return ErrPrint('Kann nicht mit %s verbinden!' % HOST.upper())
    print 'Mit %s verbunden' % HOST.upper()
    return tn

def TelnetRead(tn):
    tn.write('\r\n')
    string = tn.read_until('linux login: ')
    print '%s - %s ' % (string, hexlify(string))
    print 'Login'
    tn.write('programm\r\n')
    print 'Programm'
    while True:
        string = tn.read()

tn = TelnetOpen()
TelnetRead(tn)
Die letzte Ausgabe ist 'Programm'. Selbst '1' erscheint nicht mehr. Wahrscheinlich funktioniert auch hier das Einloggen nicht. Um es nochmal zu betonen: Dasselbe Login im Telnet-Programm läuft problemlos. Woran kann es liegen?
Danke
HWK
BlackJack

Hast Du es schon einmal ohne das '\r' versucht? Unter Linux kennzeichnet man nur mit einem '\n' das Zeilenende.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Hallo, BlackJack!
Ja, hatte ich. Funktioniert aber auch nicht. In der seriellen Variante war es sogar zwingend notwendig, immer '\r\n' statt '\n' einzugeben, um die Funktion sicherzustellen.
Danke
HWK
P.S.: Ich habe den Titel einmal etwas geändert.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Das Problem ist zum Teil gelöst. Nach Löschen von Zeile 17 funktioniert das Einloggen. Als Antwort kommt aber

Code: Alles auswählen

tset: unknown terminal type network
Terminal type ?
Kann ich den Terminaltyp gleich beim Öffnen der Verbindung übergeben oder muss ich Ihn explizit auf die Frage eingeben?
Der Typ ist jetzt ANSIX statt ANSI. Wo liegt da der Unterschied? Googlen hat nicht so recht weiter geholfen.
Nebenbei: Der Aufruf der Methode MyTelnet.read() funktioniert nicht als

Code: Alles auswählen

c = tn.read()
sondern nur als

Code: Alles auswählen

for c in tn.read()
MfG
HWK
BlackJack

`tn.read()` funktioniert immer gleich, egal wo es steht. Es liest aber nicht ein einzelnes Zeichen sondern eine Zeichenkette.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Hallo, BlackJack!
Meine read-Methode soll aber nur ein Zeichen mit yield zurückliefern. Das tut sie auch beim Aufruf über for ... in tn.read() oder mit .next(). Beim Aufruf mit c = tn.read() ist c ein Generatorobjekt.
MfG
HWK
Antworten