ubuntuusers.de

Socket tcp oder udp unter Shell-Programmierung überhaupt möglich?

Status: Gelöst | Ubuntu-Version: Ubuntu 10.04 (Lucid Lynx)
Antworten |

mgolbs

Anmeldungsdatum:
11. Januar 2009

Beiträge: 269

Wohnort: Tirschenreuth - Löbau

Hallo,

ich würde gern per Socket auf einen Mikrocontroller zugreifen und die AD bzw. IO Werte auslesen. (z.B. mit Ethersexprojekt, Pollin AVR-NET-IO und deren Firmware)

Ein Python Skript macht das auch schon gut. Nur würde ich gern dieses in der Shell realisieren, da ich alte Linux Arm Geräte wie Zaurus SL5500 oder Psion Netbook Pro habe, und diese als mobilen Datenspeicher mit vernünftigen Laufzeiten nutzen würde.

Die Shell in irgend einer Form ist da immer drauf. Sich Python drauf zu bringen, wird bei den alten Systemen schwierig. Man könnte es in C, Freepascal... umsetzen, nur dann muss man den richtigen Cross für Arm konfigurieren. Von einer Shellvariante erhoffe ich mir da mehr Unabhängigkeit, flexibler einzusetzen. Über die Suche im Forum habe ich keine Aussagen zu Socket und Shell passend gefunden. Auch www.google.de liefert nur Aussagen wie: sehr bedingt möglich...

Geht Socket in der Shell überhaupt prinzipiell, und wo liegen die Grenzen? Über Tipps und Infos würde ich mich sehr freuen.

Gruß und Dank Markus

theinlein

Anmeldungsdatum:
29. Dezember 2007

Beiträge: 1279

Hi,

die Shell ist keine Programmiersprache/Scriptsprache, wie es z.B. Python ist.

Wenn du direkt mit der Shell arbeiten willst, kannst du nur einfache Datenströme per TCP hin und herschieben.

Dazu nimmt man telnet oder auch netcat in die man Daten z.B. per Pipe übergeben kann.

Wenn du den Onkel Microcontroller gut kennst, und dessen Anfragen mittels Meldungen im ASCII bewerkstelligt werden können, dann mache in einer Shell Commandline

telnet  ipadresse  portnummer

mal eine Verbindung auf und tippe den Request an den Controller per Hand ein (... wie gesagt, falls du das Bauen der Meldung per Zeicheneingabe hinbekommst)

Wenn der MC antwortet, siehst du das in den ausgegebenen Zeilen.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13174

theinlein schrieb:

die Shell ist keine Programmiersprache/Scriptsprache, wie es z.B. Python ist.

Genau. Das wird die Sache etwas schwieriger machen - aber nicht unmöglich.

Wenn du direkt mit der Shell arbeiten willst, kannst du nur einfache Datenströme per TCP hin und herschieben.

Streng genommen kann die Shell selbst gar keine Sockets bedienen außer Unix Domain, die im Dateisystem auftauchen.

Dazu nimmt man telnet oder auch netcat in die man Daten z.B. per Pipe übergeben kann.

Ich würde zu nc ("netcat") greifen. Beide Tools sind allerdings in so einem Szenario nicht ganz einfach, weil man ja normalerweise auf das Ergebnis reagieren will und dann entweder ständig neue Verbindungen aufmachen oder aber eine Instanz über zwei named pipes füttern bzw. auslesen muss. theinlein hast Du noch eine andere Idee?

Wenn du den Onkel Microcontroller gut kennst, und dessen Anfragen mittels Meldungen im ASCII bewerkstelligt werden können, dann mache in einer Shell Commandline

telnet  ipadresse  portnummer

mal eine Verbindung auf und tippe den Request an den Controller per Hand ein (... wie gesagt, falls du das Bauen der Meldung per Zeicheneingabe hinbekommst)

Wenn der MC antwortet, siehst du das in den ausgegebenen Zeilen.

Guter Ansatz!

Bis später

robert

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2505

Ich habe im Hinterkopf, dass Debian das immer deaktiviert hat, aber die Bash kann eigentlich schon rudimentär mit Sockets umgehen:

1
2
3
4
5
6
7
8
#!/bin/bash

exec 3<>/dev/tcp/heise.de/80

echo -ne 'GET / HTTP/1.0\n\n' >&3
cat <&3

exec 3>&-

Wäre das vielleicht eine Idee?

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13174

Vain schrieb:

Ich habe im Hinterkopf, dass Debian das immer deaktiviert hat, aber die Bash kann eigentlich schon rudimentär mit Sockets umgehen:

1
2
3
4
5
6
7
8
#!/bin/bash

exec 3<>/dev/tcp/heise.de/80

echo -ne 'GET / HTTP/1.0\n\n' >&3
cat <&3

exec 3>&-

Wäre das vielleicht eine Idee?

Oh, das kannte ich noch nicht! Danke dafür! Ja, das sieht gut und handlebar aus.

Ciao

robert

mgolbs

(Themenstarter)

Anmeldungsdatum:
11. Januar 2009

Beiträge: 269

Wohnort: Tirschenreuth - Löbau

Hallo,

danke für die vielen Hinweise. Ich werde das mal versuchen an meine Gegebenheiten anzupassen. In Python sieht der Kern eines Tests wie folgt aus:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import socket

ip = raw_input("IP-Adresse: ") 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.connect((ip, 50290))
nachricht = raw_input("getadc 1: ") 
try:
    for i in range(1, 100000, 1): 
        s.send(nachricht) 
        antwort = s.recv(1024) 
finally: 
    s.close()

Wie wird das mit der Performance aussehen? In Python habe ich für AD Abfragen etwa 750Hz geschafft. Wenn ich das Verfahren

telnet  ipadresse  portnummer

nutzen würde und in eine Schleife füge, Daten des Controllers dann in eine Datei schreibe und danach sofort wieder Anfrage sende komme ich dann weit weg von 750Hz?

1
2
3
4
5
#!/bin/bash
exec 3<>/dev/tcp/heise.de/80
echo -ne 'GET / HTTP/1.0\n\n' >&3
cat <&3
exec 3>&-

Muss ich erst mal versuchen zu verstehen, bin leider kein Informatiker.

Gruß und Dank Markus

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2505

mgolbs schrieb:

[bash-snippet]

Muss ich erst mal versuchen zu verstehen, bin leider kein Informatiker.

Okay, sorry, hier nochmal kommentiert:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash

# Öffne als Filedeskriptor Nummer 3 eine TCP-Verbindung zu heise.de auf
# Port 80. Das "<>" heißt, dass dieser Deskriptor zum Lesen und
# Schreiben benutzt werden kann (wie bei einem Socket). 
exec 3<>/dev/tcp/heise.de/80

# Schicke einen einfachen HTTP-Request an heise. Die Umleitung ">&3"
# hinten heißt einfach, dass der String auf den eben geöffneten
# Deskriptor und damit auf das Socket geschrieben wird. Wichtig ist auch
# "-e" beim echo, denn das sorgt dafür, dass "\n" als Zeilenumbruch
# ausgewertet wird.
echo -ne 'GET / HTTP/1.0\n\n' >&3

# Lies von Deskriptor Nummer 3 bis es dort nichts mehr zu lesen gibt.
# Das holt die komplette Antwort vom Server ab.
cat <&3

# Schließt den Deskriptor wieder.
exec 3>&-

Die Bash behandelt Sockets genau wie reguläre Dateiumleitungen. Statt „/dev/tcp/heise.de/80“ hättest du also auch einen normalen Dateinamen hinschreiben können. Wichtig ist aber: Dieses „/dev/tcp“ gibt es im Dateisystem nicht, das ist rein virtuell und nur Bash-intern verfügbar.

Das „echo“ und „cat“ sind also nur soetwas wie:

1
2
echo hi >bla.txt
cat <bla.txt

Mit dem einzigen Unterschied, dass die Deskriptoren direkt über ihre Nummer angesprochen werden. Aber das hast du bestimmt auch schonmal gemacht, nämlich bei Befehlen wie:

1
ls -al 1>/dev/null 2>&1

Die Details des HTTP-Requests musst du nicht verstehen, das war nur ein Beispiel. So könnte man halt mit einem reinen Bash-Skript eine Webseite abrufen.

theinlein

Anmeldungsdatum:
29. Dezember 2007

Beiträge: 1279

...

etwas anderes: du könntest mal schauen, ob auf deinen "alten Teilen" ein tcl drauf ist. tcl ist extrem schlank und für den Zaurus gab's das zumindest mal. Einfach mal

tclsh

aufrufen, ob's drauf ist.

mgolbs

(Themenstarter)

Anmeldungsdatum:
11. Januar 2009

Beiträge: 269

Wohnort: Tirschenreuth - Löbau

Hallo,

danke fuer die Antworten. Bin gerade mit dem alten Psion Netbook Pro und Psion Linux hier im Netz. Mein erster Test bash Datei wie oben angelegt:

#!/bin/bash

# Öffne als Filedeskriptor Nummer 3 eine TCP-Verbindung zu heise.de auf
# Port 80. Das "<>" heißt, dass dieser Deskriptor zum Lesen und
# Schreiben benutzt werden kann (wie bei einem Socket). 
exec 3<>/dev/tcp/heise.de/80

# Schicke einen einfachen HTTP-Request an heise. Die Umleitung ">&3"
# hinten heißt einfach, dass der String auf den eben geöffneten
# Deskriptor und damit auf das Socket geschrieben wird. Wichtig ist auch
# "-e" beim echo, denn das sorgt dafür, dass "\n" als Zeilenumbruch
# ausgewertet wird.
echo -ne 'GET / HTTP/1.0\n\n' >&3

# Lies von Deskriptor Nummer 3 bis es dort nichts mehr zu lesen gibt.
# Das holt die komplette Antwort vom Server ab.
cat <&3

# Schließt den Deskriptor wieder.
exec 3>&-

dabei bekam ich: ... 6: cannot create /dev/tcp/heise.de/80: directory nonexist

tclsh ist auf dem Psionlinux nicht drauf. Ein ipkg install tcl83.ipk brachte zwar bei der Installation einen Fehler, tclsh laesst sich aber starten. Was koennte man da probieren? Ist tclsh sowas wie TCL/TK ohne Grafik?

set server """"""IP-Mikrocontroller z.B. 192.168.0.90"""""""
set sockChan [socket $server """""Port Dienst Mikrocontroller z.B. 80"""""""]
gets $sockChan line
close $sockChan
puts " on $server is $line"

Gruss und Dank Markus

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Wie hast Du das Skript gestartet, und welche Shell hat das Psion-Teil ?

(ich hoffe, Du hast das Skript "ausführbar" gemacht und es dann mit ./meinskript ausgeführt ?
Welche Bash dort läuft, verrät bash --version )

Außerdem: gibt es überhaupt den TCP-Dämon ?   → which tcpd

track

mgolbs

(Themenstarter)

Anmeldungsdatum:
11. Januar 2009

Beiträge: 269

Wohnort: Tirschenreuth - Löbau

Hallo,

danke für die Meldung. Skript ist ausführbar, System hat busybox -damit geht wohl bash --version nicht? which tcpd meldet weder Fehler noch Auskunft.

Das mit tclsh scheint ein guter Ansatz zu sein. Server über IP wird erkannt, Socket über Portnummer aufgebaut. Puts $... geht auch schon nur das gets $...wartet ewig. Eventuell ein \r\n Problem beim puts .... oder ...

Gruß und Dank Markus

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Äh - busybox sagst Du ?

Das ist eine absolut minimale Pseudo-Shell, die "all-in-one" nur das allernötigste an Bord hat.
Also hier definitiv kein Ersatz für eine richtige Shell.

Guckst Du mal bitte, ob nicht vielleicht doch noch eine richtige Shell vorhanden ist: which sh und which bash

Wenn which tcpd   nichts meldet, dann hat es einfach nichts gefunden. MaW: kein TCP-Dämon vorhanden. C'est ça.
Jetzt müsste man nur noch herauskriegen, wie man TCP-Verbindungen unter busybox am geschicktesten öffnet.

(aber das ist eine grundsätzlich andere Frage, als Du sie oben gestellt hattest !)

track

mgolbs

(Themenstarter)

Anmeldungsdatum:
11. Januar 2009

Beiträge: 269

Wohnort: Tirschenreuth - Löbau

Hallo,

danke für die Antwort. Unter which sh kommt /bin/sh und which bash nichts.

Für das Kernanliegen habe ich was auf i386 Debian6/Ubuntu 10.04 prima funktioniert geschrieben:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/usr/bin/tclsh
set line string;
puts "test"
set server 192.168.1.99;
set sockChan [socket $server 50290];
# set bu [fconfigure $sockChan -buffersize]
set x 0
while {$x < 10001} {
    set x [expr {$x + 1}]
    puts $sockChan "getadc 1 \r\n";
    flush $sockChan;
    gets $sockChan line;
    puts $line;
#    if {$x == 100} { set x 0 }
    }
close $sockChan

Noch nicht auf Arm Psion Linux bzw. Sharp Zaurus Linux getestet, wird wohl funktionieren Dank Nachinstallation tclsh.

Kern der Frage war ja ob man in einem Shell Skript Sockets handeln kann. Unter Systemen mit busybox wohl schwierig. Werde es mal auf einem normalen i386 bzw. amd64 Debian6 bzw. Ubuntu 10.04 probieren (wie oben beschrieben).

Gruß und Dank Markus

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

mgolbs schrieb:

danke für die Antwort. Unter which sh kommt /bin/sh ...

Dann könntest Du im Prinzip jederzeit eine "richtige" Posix-Shell starten mit dem Aufruf /bin/sh .

Das Problem ist aber, dass der TCP-Dämon nicht läuft, und dem zufolge das Pseudogerät /dev/tcp/.... nicht existiert.
Das musst Du erstmal klären, vorher wird das auf der Mini-Büchse nicht laufen !

Ob und wie das mit der tclsh geht, davon hab ich keine Ahnung. Das ist ein eigenes Kapitel.

track

theinlein

Anmeldungsdatum:
29. Dezember 2007

Beiträge: 1279

"Was koennte man da probieren? Ist tclsh sowas wie TCL/TK ohne Grafik?"

tclsh ist die "TCL-Shell" - also der reine TCL-Interpreter, der tcl-Programmiersprache spüricht. TK ist die Erweiterung mit grafischen Elementen.

Nun, tcl ist die schlanke Alternive für die Socket-Programmierung.

#! /bin/bash
#  comment  \
exec tclsh "$0" "$@"


set HOST  localhost
set PORT  80

puts  "versuche Verbindung zu $HOST auf Port $PORT aufzubauen"
set sock [socket $HOST $PORT]

puts  "Verbindung steht"

Dieses Shell-Script ruft sofort tclsh auf (die ersten 3 Zeilen, damit ist man unabhängig davon, wo tclsh installiert ist – aber: Bäcksläsch als letztes Zeichen am Zeilenende nicht vergessen).

HOST und PORT sind Variablen, deren Inhalt du anpassen kannst, um deinen MC zu erreichen.

Wenn der 'socket' Aufruf klappt, wird die Zeile "Verbindung steht" ausgegeben, anderenfalls wird mit einer Exception abgebrochen (jetzt mal Quick und Dirty).

Wenn das bei deinen alten Geräten geht, dann können wir aus dem Python-Script einfach ein tcl-Script machen - oder?

Antworten |