Tronde
Anmeldungsdatum: 23. November 2006
Beiträge: 1640
|
Hallo. Ich bin ein Perl-Neuling und benötigte eure Hilfe. Ich pflege auf einem UNIX-System eine Textdatei. In dieser steht pro Zeile ein Hostname. Das folgende Perl-Script liest diese Datei ein und gibt den Inhalt in sortierter Reihenfolge auf dem Bildschrim aus. Anschließend kann durch Eingabe des Kommandos mit einer Nummer des Listeneintrags eine RDP-Verbindung zu einem Host hergestellt werden. Mit dem Kommando "V0" verbindet man sich z.B. zum ersten Eintrag in der sortierten Liste. 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 | #!/usr/bin/perl
# rdp_connect.pl is a small program to connect to windows hosts via rdesktop.
use strict; # Hilft Tippfehler zu finden. ;-)
use warnings; # Gibt ausfuehrlichere Fehlermeldungen aus.
# use diagnostics; # Gibt noch ausfuehrliche Meldungen aus.
use FindBin;
use File::Slurp;
chdir $FindBin::Bin;
my $datei = 'hosts.txt';
my %kommando = ( verbinden => 'v', eintragen => 'n', bewege => 'm', loesche => 'd', beenden => 'e' );
my $domain = 'DOMAIN';
my $keyboard_layout = 'de';
append_file($datei) unless -e $datei;
my @hosts = read_file($datei);
my @sorted_hosts = sort @hosts;
for my $nr (0 .. $#sorted_hosts)
{ print "[$nr] ", $sorted_hosts[$nr] }
print "Was moechtest du tun? ($kommando{'eintragen'} Neuer Eintrag; $kommando{'verbinden'} Verbindung zu Host; $kommando{'loesche'} loescht Eintrag; $kommando{'bewege'} verschiebt Eintrag); $kommando{'beenden'} Exit: ";
my $input = <STDIN>;
if ( lc substr($input, 0, 1) eq $kommando{'verbinden'}) {
my $host = @sorted_hosts[int substr($input, 1)];
print "rdesktop -d $domain -k $keyboard_layout -0 $host";
exec "rdesktop -d $domain -k $keyboard_layout -g 1880x1000 -0 $host ";
}
elsif (lc substr($input, 0, 1) eq $kommando{'beenden'}) { }
elsif (lc substr($input, 0, 1) eq $kommando{'eintragen'}) {
print "Gib den FQDN ein: ";
$input = <STDIN>;
append_file($datei, $input);
}
elsif (lc substr($input, 0, 1) eq $kommando{'loesche'}) {
my $nr = int substr($input, 1);
splice(@sorted_hosts, $nr, 1) if $nr >= 0 and $nr <= $#sorted_hosts;
write_file($datei, @sorted_hosts);
}
elsif (lc substr($input, 0, 1) eq kommando{'bewege'}) {
my($von, $zu) = split ':',
substr($input, length($kommando{'bewege'}));
$von = int $von;
$zu = int $zu;
splice(@sorted_hosts, $zu, 0, splice(@sorted_hosts, $von, 1));
write_file($datei, @sorted_hosts);
}
else {
my $text="Hier wird mal ein Hilfe-Text stehen.";
say $text;
}
|
Führe ich das Script in einer Bash aus, bleibt der Perl-Prozess so lange aktiv, bis ich die rdesktop-Sitzung beendet habe. Erst anschließend kehrt die Bash zum Prompt zurück. Nun würde ich gern folgendes Verhalten erreichen. Ich möchte das Perl-Script ausführen und eine Verbindung zu einem Host aufbauen. Rdesktop soll im Hintergrund gestartet werden und das Perl-Script soll sich nach dem erfolgreichen Start von rdesktop beenden. So dass ich in meinem Terminal wieder einen Prompt bekomme und weitere Befehle darin ausführen kann. Ich habe vermutet, dass ich dies bereits erreiche, wenn ich exec() verwende:
| exec "rdesktop -d $domain -k $keyboard_layout -g 1880x1000 -0 $host ";
|
Um rdesktop im Hintergrund laufen zu lassen, müsste ich dem Befehl noch ein "&" anfügen. Füge ich dieses ein, bekomme ich jedoch die Fehlermeldung:
| sh: syntax error: `&' unexpected
|
Kann mir jemand helfen, den Aufruf so anzupassen, dass oben beschriebenes Ziel erreicht werden kann? Viele Grüße Tronde
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12844
|
Tronde schrieb:
Kann mir jemand helfen, den Aufruf so anzupassen, dass oben beschriebenes Ziel erreicht werden kann?
Dafür brauchst Du system(), und zwar die Version mit einem Argument. Da kannst Du dann den "&" am Ende verwenden. Alternativ machst Du selbst einen fork() und nutzt dann exec() - allerdings ohne "&". Dann kannst Du aber die Version mit Parameterliste nutzen, was robuster ist.
|
Tronde
(Themenstarter)
Anmeldungsdatum: 23. November 2006
Beiträge: 1640
|
Hallo rklm, den Aufruf mit system() verstehe ich noch nicht so ganz. In der Dokumentation dazu steht: Does exactly the same thing as exec LIST , except that a fork is done first and the parent process waits for the child process to exit.
Das ist aber genau das Verhalten, dass ich nicht wünsche. Der Eltern-Prozess soll nicht auf das Ende des Kind-Prozesses warten. Oder verstehe ich das falsch? Gruß Tronde
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12844
|
Tronde schrieb:
den Aufruf mit system() verstehe ich noch nicht so ganz. In der Dokumentation dazu steht: Does exactly the same thing as exec LIST , except that a fork is done first and the parent process waits for the child process to exit.
Das ist aber genau das Verhalten, dass ich nicht wünsche. Der Eltern-Prozess soll nicht auf das Ende des Kind-Prozesses warten. Oder verstehe ich das falsch?
Deswegen ja auch die Form mit einem String und dem Und-Zeichen: $ perl -e '$t=time();print("Start\n");system("sleep 5");printf("Stop\n%ds\n", time()-$t)'
Start
Stop
5s
$ perl -e '$t=time();print("Start\n");system("sleep 5&");printf("Stop\n%ds\n", time()-$t)'
Start
Stop
0s Oder halt die Version mit fork() und exec(): $ perl -e '$t=time();print("Start\n");if (fork() == 0){exec("sleep", "5")} else {printf("Stop\n%ds\n", time()-$t)};'
Start
Stop
0s
|
Tronde
(Themenstarter)
Anmeldungsdatum: 23. November 2006
Beiträge: 1640
|
Guten Morgen. Ich habe die Zeile
| exec "rdesktop -d $domain -k $keyboard_layout -g 1880x1000 -0 $host ";
|
nun mit dieser Zeile ersetzt:
| system("rdesktop -d $domain -k $keyboard_layout -g 1880x1000 -0 $host &");
|
Bei Ausführung des Programms erhalte ich jedoch wieder die Fehlermeldung:
| sh: syntax error: `&' unexpected
|
Dabei ist es egal, ob ich das "&" mit oder ohne führedes Leerzeichen in den String einfüge. Viele Grüße Tronde
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12844
|
Tronde schrieb:
| system("rdesktop -d $domain -k $keyboard_layout -g 1880x1000 -0 $host &");
|
Bei Ausführung des Programms erhalte ich jedoch wieder die Fehlermeldung:
| sh: syntax error: `&' unexpected
|
Dabei ist es egal, ob ich das "&" mit oder ohne führedes Leerzeichen in den String einfüge.
Seltsam. Du könntest mal diese Zeile versuchen, dann siehst Du ggf. schon, wo es hakt: | system("set -x; rdesktop -d $domain -k $keyboard_layout -g 1880x1000 -0 $host &");
|
Was genau ist denn in den Variablen $domain, $keyboard_layout und $host?
|
Tronde
(Themenstarter)
Anmeldungsdatum: 23. November 2006
Beiträge: 1640
|
Hi. Auch mit der von dir geschilderten Variante bekomme ich die gleiche Fehlermeldung.
Was genau ist denn in den Variablen $domain, $keyboard_layout und $host?
| my $domain = 'AD';
my $keyboard_layout = 'de';
my $host = @sorted_hosts[int substr($input, 1)];
|
$host enthält den FQDN eines Hosts. Dieser entspricht dem Muster <Prefix-HOSTNAME.foo.example.com>.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12844
|
Und, hast Du die Zeile mit "set -x" ausgeführt und Dir die Ausgabe angeschaut?
|
Tronde
(Themenstarter)
Anmeldungsdatum: 23. November 2006
Beiträge: 1640
|
Ja, ich habe die Zeile mit der Funktion "set -x" ausgeführt. Die Ausgabe war jedoch schlicht die folgende Fehlermeldung:
| sh: syntax error: `&' unexpected
|
Mehr Ausgabe gibt es nicht. MfG Tronde
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12844
|
Tronde schrieb: Ja, ich habe die Zeile mit der Funktion "set -x" ausgeführt. Die Ausgabe war jedoch schlicht die folgende Fehlermeldung:
| sh: syntax error: `&' unexpected
|
Mehr Ausgabe gibt es nicht.
☹ Dann probiere es doch mal mit dem "set -x" aber ohne "&".
|
Tronde
(Themenstarter)
Anmeldungsdatum: 23. November 2006
Beiträge: 1640
|
Guten Morgen. Mit "set -x" und ohne "&" kommt die RDP-Sitzung zu Stande und ich erhalte im Terminal die folgende Ausgabe:
| + rdesktop -d AD -k de -g 1880x1000 -0 prefix-hostname.bar.example.com
WARNING: Remote desktop does not support colour depth 24; falling back to 16
|
MfG
Tronde
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12844
|
Sieht eigentlich OK aus. Seltsam. Dann kann es nur irgendwas mit dem anderen Betriebssystem zu tun haben. Ich habe im Moment nur Ubuntus zum Testen. Was hast Du denn? Ich sehe es gerade nicht. Ggf. musst Du Dich dann mal in einem Forum desjenigen OS schlau machen.
|
Tronde
(Themenstarter)
Anmeldungsdatum: 23. November 2006
Beiträge: 1640
|
Ich habe:
| 520 : uname -a
SunOS rayadm 5.10 Generic_150401-20 i86pc i386 i86pc
521 : /usr/pkgsrc/current/bin/perl -v
This is perl 5, version 14, subversion 2 (v5.14.2) built for i386-solaris-thread-multi
525 : bash --version
GNU bash, version 3.2.57(1)-release (i386-pc-solaris2.10)
|
Danke für deine Unterstützung. Ich werde mich mal nach einem Forum oder einer Mailinglist umschauen, wo ich weitere Informationen einholen kann. Falls ich eine Lösung finde, gebe ich hier ebenfalls eine Rückmeldung. Viele Grüße Tronde
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12844
|
Tronde schrieb: Ich habe:
| 520 : uname -a
SunOS rayadm 5.10 Generic_150401-20 i86pc i386 i86pc
521 : /usr/pkgsrc/current/bin/perl -v
This is perl 5, version 14, subversion 2 (v5.14.2) built for i386-solaris-thread-multi
525 : bash --version
GNU bash, version 3.2.57(1)-release (i386-pc-solaris2.10)
|
Aaaargh, Du hast SunOS!! Die /bin/sh ist dafür bekannt, alles mögliche, aber nicht POSIX-kompatibel und fehlerarm zu sein.
Danke für deine Unterstützung. Ich werde mich mal nach einem Forum oder einer Mailinglist umschauen, wo ich weitere Informationen einholen kann. Falls ich eine Lösung finde, gebe ich hier ebenfalls eine Rückmeldung.
Ggf. kannst Du es noch retten, indem Du einen andere Shell benutzt. Du kannst die Variable SHELL so umsetzen, dass die bash , die ksh oder eine andere vernünftige Bourne-Shell verwendet wird. Ich hoffe, das funktioniert in Perl. Es gibt verschiedene Wege: | # im Perl-Programm
$ENV{'SHELL'} = '/bin/bash'
|
oder | # in der Shell
SHELL=/bin/bash perl ...
# das sollte auf jeden Fall gehen
env SHELL=/bin/bash perl ...
# oder eine modifizierte Shebang, da bin ich aber nicht so optimistisch:
#!/bin/env SHELL=/bin/bash perl
|
(Den Pfad zur entsprechenden Shell musst Du natürlich so wählen, dass er auf Deinem System passt.)
|
Tronde
(Themenstarter)
Anmeldungsdatum: 23. November 2006
Beiträge: 1640
|
Hey, dann probiere ich deinen Tipp morgen auf der Arbeit gleich mal aus. Vielleicht klappt es ja dann. ☺
|