ssh über IPC::open2
Holger
- perl
Hallo,
ich mochte zwischen 2 Perlscripts auf verschiedenen Rechnern verschlüsselt und komprimiert Daten und Dateien austauschen. Folgendes Minimalbeispiel soll das problem verdetlichen:
server1.pl [wird gestartet]
#!/usr/bin/perl -w
use strict;
use warnings;
use IPC::Open2;
#use diagnostics;
open2(my $pipei, my $pipeo, 'ssh', '172.20.200.21', "/root/server2.pl");
print STDERR "server 1: sending data: 1\n";
print $pipeo "1\n" or die("Cannot send data: 1 $!");
print STDERR "server 1: receiving...\n";
my $data = <$pipei>;
print STDERR "server 1: received ".$data."\n";
print STDERR "server 1: sending data: 3\n";
print $pipeo "3\n" or die("Cannot send data: 3 $!");
print STDERR "server 1: receiving...\n";
$data = <$pipei>;
print STDERR "server 1: received ".$data."\n";
close $pipei;
close $pipeo;
server2.pl [auf anderem Rechner]
#!/usr/bin/perl -w
use strict;
use warnings;
use IPC::Open2;
#use diagnostics;
print STDERR "server 2: receiving...\n";
my $data = <STDIN>;
print STDERR "server 2: received: ".$data."\n";
print STDERR "server 2: sending data: 2\n";
print STDOUT "2\n" or die("Cannot send data: 2 $!");
print STDERR "server 2: receiving...\n";
$data = <STDIN>;
print STDERR "server 2: received: ".$data."\n";
print STDERR "server 2: sending data: 4\n";
print STDOUT "4\n" or die("Cannot send data: 4 $!");
Das Beispiel liefert folgende Ausgabe:
linux:~ # ./server1.pl
server 1: sending data: 1
server 1: receiving...
root@172.20.200.21's password:
server 2: receiving...
server 2: received: 1
server 2: sending data: 2
server 2: receiving...
Danach passiert nichts mehr, manchmal bleibt nur ein zombieprozess übrlig.
Der Child-Prozess bekommt die Daten ordnungsgemäß, aber danach wartet der parent-Prozess immer erst auf die Beendigung des Childprozesses.
Was kann ich tun, damit die Daten sofort ankommen bzw. nicht immer einen neuen Prozess öffnen muss?
Vielen Dank,
Holger
Hallo Holger,
genau das gleiche Problem hatte ich auch mal, nur habe ich die ssh Verbindung nicht über das Modul IPC geöffnet, sondern ganz einfach übers System.
Das Problem bei ssh und rsh ist, dass die Prozesse solange offen bleiben, bis der Remoteprozess geschlossen oder STDOUT umgeleitet wurde, denn wohin soll der Remoteprozess sonst schreiben, wenn der ssh bzw. rsh Prozess plötzlich weg ist?
Nun entweder änderst du STDOUT nach /dev/null oder nutzt die Option ssh -n. Schau mal in der manpage von ssh nach, da ist die Option etwas besser geschildert.
Ich hoffe ich konnte helfen.
Gruß
coolblue
Hallo,
Das Problem bei ssh und rsh ist, dass die Prozesse solange offen bleiben, bis der Remoteprozess geschlossen oder STDOUT umgeleitet wurde, denn wohin soll der Remoteprozess sonst schreiben, wenn der ssh bzw. rsh Prozess plötzlich weg ist?
Ich möchte den ssh-Prozess ja nicht schließen - ich möchte ledeglich noch während der Laufzeit von server2.pl die Datem in server.pl auswerten und eine Antwort zurüksenden.
Nun entweder änderst du STDOUT nach /dev/null oder nutzt die Option ssh -n.
hab ich mal gemacht:
open2(my $pipei, my $pipeo, 'ssh', '-n', '172.20.200.21', "/root/server2.pl");
Durch die Option -n erhält server2.pl aber keine Daten mehr von server1.pl, sodass folgendes passiert:
linux:~ # ./server1.pl
server 1: sending data: 1
server 1: receiving...
root@172.20.200.21's password:
server 1: received 2
server 1: sending data: 3
server 1: receiving...
server 1: received 4
linux:~ # server 2: receiving...
Use of uninitialized value in concatenation (.) or string at /root/server2.pl line 15.
server 2: received:
server 2: sending data: 2
server 2: receiving...
Use of uninitialized value in concatenation (.) or string at /root/server2.pl line 22.
server 2: received:
server 2: sending data: 4
Schau mal in der manpage von ssh nach, da ist die Option etwas besser geschildert.
Ja, aber:
"Redirects stdin from /dev/null (actually, prevents reading from stdin)"
server2.pl muss ja aber noch Daten erhalten...
Ich hoffe ich konnte helfen.
Ja, Danke.
MfG Holger
hallo Holger,
was hälst du hiervon...?
IO::Socket::INET
:-)
obwohl ich jetzt nicht weiß, ob Daten auch verschlüsselt versendet werden können, aber eigentlich müsste es da auch einen Weg geben...
Gruß,
coolblue
Hallo,
was hälst du hiervon...?
IO::Socket::INET
Das habe ich mir auch schon angesehen, aber mir gefalllen 2 Dinge nicht: es ist nicht komprimiert (ich habe relativ große Datenmengen) und es muss immer ein Dämon laufen. Oder habe ich etwas überlesen?
MfG Holger
你好 Holger,
was hälst du hiervon...?
IO::Socket::INETDas habe ich mir auch schon angesehen, aber mir gefalllen 2 Dinge nicht:
es ist nicht komprimiert (ich habe relativ große Datenmengen) [...]
Das kannst du ja mittels Compress::Gzip selber machen.
[...] und es muss immer ein Dämon laufen.
Bei deinem SSH-Ding auch ;-) Aber es gibt ja auch IO::Socket::SSL, damit
kannst du deine Verbindung dann absichern.
再见,
CK
Hallo Christian,
Das kannst du ja mittels Compress::Gzip selber machen.
[...] und es muss immer ein Dämon laufen.
Bei deinem SSH-Ding auch ;-) Aber es gibt ja auch IO::Socket::SSL, damit
das wußte ich auch nocht nicht...
gut, dass es immer Leute gibt, die mehr wissen als andere :-)
Gruß,
coolblue
Das habe ich mir auch schon angesehen, aber mir gefalllen 2 Dinge nicht: es ist nicht komprimiert (ich habe relativ große Datenmengen) und es muss immer ein Dämon laufen. Oder habe ich etwas überlesen?
hmmm... es kommt darauf an, welchen Daemon du meinst!
Für eine Verbindung sind natürlich die Netzwerkdaemons notwendig, aber ohne die wäre kein Netzwerk möglich.
Für die Verbindung über Sockets brauchst du nichts weiter als einen freien Port, einen Server-Prozess, der ständig auf eingehende Verbindungen zum gewählten Port lauscht und natürlich deinen Client.
Den Client und den Server programmierst du selber, so wie du auch in deinem Beispiel einen Server und einen Client programmiert hast.
Wegen der komprimierten Daten wäre es denkbar möglich, die Daten über eine Pipe vorher zu komprimieren und als STDOUT der Pipe die Socketanbindung zu definieren, aber ich glaube, dass wäre dir alles zu kompliziert :-)
Gruß,
coolblue
Hallo,
hmmm... es kommt darauf an, welchen Daemon du meinst!
ich meine den, der den Port aufmacht und ständig wartet, dass jemand etwas will ;-)
Für die Verbindung über Sockets brauchst du nichts weiter als einen freien Port, einen Server-Prozess, der ständig auf eingehende Verbindungen zum gewählten Port lauscht und natürlich deinen Client.
Das war mir alles eigentlich zu aufwändig, aber es wird anscheinend nicht einfacher gehen. Im Programm maildirsync.pl (http://svn.dlux.hu/public/maildirsync/branches/dlux/maildirsync.pl) scheint es auch mit ssh und open2 zu gehen, aber ich werde es jetzt mit IO::Socket::INET versuchen und die großen Daten nochmal mit Compress komprimieren.
Wegen der komprimierten Daten wäre es denkbar möglich, die Daten über eine Pipe vorher zu komprimieren und als STDOUT der Pipe die Socketanbindung zu definieren, aber ich glaube, dass wäre dir alles zu kompliziert :-)
Geht ja nicht anders ;-)
Vielen Dank,
Holger Motzkau
Hallo Holger,
bin mir eigentlich ziemlich sicher, dass du an dieser Variante schnell gefallen finden wirst. Gegebenfalls kann ich dir ein paar Fragen beantworten, wenn welche aufkommen...
Allerdings gäb es noch eine letzte alternative für dich.
--> vsftp <--
Very Secure FTP. vsftp sollte in den Linuxdistributionen mitgeliefert werden.
Gruß,
coolblue
Hallo,
ich habe mittlerweile das Problem auch ohne komplizerte Arbeit mit IO::Socket::INET gelöst: Unter server2.pl muss nur angegeben werden, dass Perl die Daten nicht puffert bevor sie gesendet werden. Das ist mit STDOUT->autoflush(); oder kurz $| möglich.
Vielen Dank an alle,
Holger