Schrift
[thread]9084[/thread]

SSH Script zur Massenabfrage: kein fehler, kein log, na supi...

Leser: 2


<< |< 1 2 3 >| >> 21 Einträge, 3 Seiten
FlorianL
 2007-06-13 13:26
#77477 #77477
User since
2007-05-18
142 Artikel
BenutzerIn
[default_avatar]
Hallo mal wieder...

Heute gehts darum ein cgi zu basteln das eine ssh connection aufbaut, ein kommando absetzt, und den output wieder zurückwirft...

Ich weiss das es so eigendlich funzen sollte weil ichs bei nem "reinen" shell script (ohne den cgi-kram) ausprobiert hab und es ging...

Die übergabe der parameter durchs cgi geht auch, habs mit ein paar print anweisungen getestet...

Ich hab auch mal nachgesehn ob vieleicht usgeführt, aber nichts zurückgegeben wird, im logfile taucht aber nichts auf also geh ich davon aus das der ssh connect garnicht erst initiiert wird?!?!

Code: (dl )
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#!/usr/bin/perl
#
# Remote-Cmd F.Luettgens
########################
use strict;
use warnings;
use CGI;
use CGI::Carp qw(fatalsToBrowser);
use HTML::Template;

chomp(my $sshbin = `which ssh`);
my $cgi       = "/cgi-bin/remotecmd/remotecmd.cgi";
my $goto      = $ENV{PATH_INFO};
my $query = CGI->new;
my @configs   = $query->param;
my %params    = $query->Vars;
$goto =~ s!^/!!;
chomp(my $hostfile = `echo \$WCOLL`);           # hostliste auslesen
open(HOSTS, "$hostfile");
my @hostlist = <HOSTS>;
close(HOSTS);
foreach (@hostlist) {
       s/i$//;                                 # angehaengtes "i" entfernen
}

print $query->header;                           # html header schicken

my %map = (                                     # function-map
   output        => \&output,
   cmd           => \&cmd,
   exec_cmd      => \&exec_cmd,
);

sub cmd {
   my $tmpl = HTML::Template->new( filename =>  'cmd.tmpl' );
   $tmpl->param( SCRIPT => $cgi );
   print $tmpl->output;
}

sub exec_cmd {
       my $server = $params{'hostlist'};
       my $command = $params{'command'};
       my $send2all = $params{'allhosts'};
       if ($send2all eq "send2all") {                          # ssh connect an alle rechner?
               foreach (@hostlist) {
                       sshconnect($_, $command);
                       print ("Output: $_[0]");
               }
       } else {
       ssh_connect($server, $command);                         # ssh connect
       print("Output: $_[0]");
}
}
sub ssh_connect {
       my @output = (system("$sshbin $_[0] $_[1]"));          
       return @output;
}

if( exists $map{$goto} ){
       $map{$goto}->();
}
else{
       my $tmpl = HTML::Template->new( filename => 'default.tmpl' );
       $tmpl->param( SCRIPT => $cgi );
       print $tmpl->output;
}


kurzer nachtrag zum verbindungsaufbau:

wir arbeiten mit hostkeys, es kommt also keine passwortabfrage...\n\n

<!--EDIT|FlorianL|1181727224-->
sid burn
 2007-06-13 14:09
#77478 #77478
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Wie wärs mit Net::SSH anstatt den befehl "ssh" irgendwie versuchen zu Parsen?
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
Dubu
 2007-06-13 14:14
#77479 #77479
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
Du schreibst einmal sshconnect, aber die Funktion heißt ssh_connect.

Du lässt dir "Output: $_[0]" ausgeben, aber $_[0] ist an der Stelle undef. Du müsstest den Rückgabewert von ssh_connect ausgeben.

Du prüfst nicht, ob das open(HOSTS, "$hostfile") erfolgreich ist. Ein open sollte immer eine Fehlerabfrage und informative Fehlermeldung beinhalten, z.B. mit ... or die "could not open $hostfile: $!".

Statt chomp(my $hostfile = `echo \$WCOLL`) tut es sicherlich auch ein my $hostfile = $ENV{WCOLL}.

Hast du ins Fehlerlog des Webservers geschaut? Gab es Fehlermeldungen?

Noch etwas: Die Struktur des Programms finde ich sehr unübersichtlich: Erst kommt Code, dann kommen Subroutinen-Definitionen, dann kommt nochmal Code. Schreib doch allen Code des "Hauptprogramms" hintereinander, beendet mit einem exit 0, dann weiß man, wo's zuende ist. Dahinter können dann die Subroutinen stehen.
Wenn Programme größer werden, sollte man sich überlegen, die gesamte Funktion in Module auszulagern.
Ein Lob für die Verwendung von strict und warnings sowie CGI.pm.
docsnyder
 2007-06-13 15:55
#77480 #77480
User since
2005-09-08
300 Artikel
BenutzerIn
[Homepage] [default_avatar]
Ich mache sowas immer mit Expect ...
FlorianL
 2007-06-13 16:21
#77481 #77481
User since
2007-05-18
142 Artikel
BenutzerIn
[default_avatar]
ich hab schon von expect und dem ssh modul gelesen, aber ich darfs nicht nutzen, infact: ich darf für dieses script kein einziges externes modul verwenden, nicht einmal das html template modul...

mit Net::SSH wär das sicherlich extrem viel einfacher gewesen, allein das beispiel auf der cpanseite macht im prinzip schon fast alles was ich brauch... :(

@dudu:

1. danke für den hinweis auf den tippfehler
2. ich dachte @output wär der rückgabewert der funktion?

sub ssh_connect {
my @output = (system("$sshbin $_[0] $_[1]"));
return @output;
}

ssh_connect($server, $command);
print("Output: $_[0]");

für mich sah das ganz okay aus.. :rock:

3. die "die" anweisung vergess ich öfters mal ganz gern, wird aber eigendlich immer nachgezogen falls ich auf fehlersuche geh ;)

4. $ENV{WCOLL} funktioniert beim aufruf auf der shell, aber nicht per cgi obwohl die variable definitiv deklariert ist, habs eben noch mit dem webserver-user getestet, jemand ne idee?

ansonsten wie immer: vielen dank an euch alle!
renee
 2007-06-13 16:30
#77482 #77482
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Mit system bekommst Du nicht die Ausgabe des Programms. Dafür musst Du Backticks, qx{} oder CPAN:IPC::Open2 nehmen...

z.B. mit Backticks
Code (perl): (dl )
my $output = `befehl`;


mit qx{}
Code (perl): (dl )
my $output = qx{befehl};



mit CPAN:IPC::Open2 (aus: http://www.unix.org.ua/orelly/perl/prog3/ch32_30.htm
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
use IPC::Open2;

local(*HIS_OUT, *HIS_IN);  # Create local handles if needed.

$childpid = open2(*HIS_OUT, *HIS_IN, $program, @args)
    or die "can't open pipe to $program: $!";
print HIS_IN "here's your input\n";
$his_output = <HIS_IN>;
close(HIS_OUT);
close(README);
waitpid($childpid, 0);


IPC::Open2 ist schon Ewigkeiten ein CORE-Modul.
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
FlorianL
 2007-06-13 16:58
#77483 #77483
User since
2007-05-18
142 Artikel
BenutzerIn
[default_avatar]
Code: (dl )
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#!/usr/bin/perl
#
# Remote-Cmd F.Luettgens
########################
use strict;
use warnings;
use CGI;
use CGI::Carp qw(fatalsToBrowser);

chomp(my $sshbin = `which ssh`);
my $cgi = "/cgi-bin/remotecmd/remotecmd.cgi";
my $query = CGI->new;
my @configs = $query->param;
my %params = $query->Vars;
my $hostfile = "/usr/local/etc/rup";
#my $hostfile = ($ENV{WCOLL});
open(HOSTS, "$hostfile") || die "Couldnt open $hostfile: $!";
my @hostlist = <HOSTS>;
close(HOSTS);
foreach (@hostlist) {
s/i$//; # angehaengtes "i" entfernen
}

my $goto = $ENV{PATH_INFO};
$goto =~ s!^/!!;
my %map = (
exec_cmd => \&exec_cmd,
);
if( exists $map{$goto} ){
$map{$goto}->();
}

sub exec_cmd {
my $server = $params{'hostlist'};
my $command = $params{'command'};
my $send2all = $params{'allhosts'};
if ($send2all eq "send2all") { # ssh connect an alle rechner?
foreach (@hostlist) {
ssh_connect($_, $command);
print ("Output: $_[0]");
}
} else {
ssh_connect($server, $command); # ssh connect
print("Output: $_[0]");
}
}
sub ssh_connect {
my @output = qx {$sshbin $_[0] $_[1]};
return @output;
}

print <<EOT; # Start des ekligen dreamweaver codes
Content-Type: text/html

<html>
<body>
<form name="remotecmd" method="post" action="./remotecmd.cgi?goto=exec_cmd">
<table width="812" border="0" align="center">
<tr>
<td width="94">Hostname</td>
<td width="86">&nbsp;</td>
<td width="610">Command:</td>
</tr>
<tr>
<td><select name="hostlist" id="hostlist">
EOT
foreach (@hostlist) {
chomp;
print (" <option value=\"$_\">$_</option>\n");
}
print <<EOT;
</select></td>
<td>&nbsp;</td>
<td><input name="command" type="text" id="command" value="uname -a" size="70"></td>
</tr>
<tr>
<td><input type="radio" name="allhosts" value="send2all">Alle Hosts </td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td><input type="submit" name="Submit" value="Absenden"></td>
<td><input name="cancel" type="reset" id="cancel" value="Zur&uuml;cksetzen"></td>
<td>&nbsp;</td>
</tr>
</table>
<p>&nbsp;</p>
</form>
</body>
</html>
EOT


ich weiss das das so nicht funktioniert, hast du mir ja letztes mal schon erklärt und dann auf html::template hingewiesen.. wie das modul funktioniert hab ich soweit halbwegs verstanden und konnte auch damit arbeiten...

jetzt haben die mich hier beschnitten und es mir wieder entrissen :(

ich glaube ich hätte es einfacher wenn ich das script zweiteile und vom forumlar aus aufs "save-script" linke, aber dann müsst ich wiederrum die vars die von beiden scripts benutzt werden in eine 3. datei schreiben und includen.. das erscheint bei näherer betrachtung doch nicht mehr so sinnvoll...

hint anyone? :)
renee
 2007-06-13 17:37
#77484 #77484
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Das ist jetzt ungetestet:
Code (perl): (dl )
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/perl
#
# Remote-Cmd F.Luettgens
########################
use strict;
use warnings;
use CGI;
use CGI::Carp qw(fatalsToBrowser);

my $cgi       = "/cgi-bin/remotecmd/remotecmd.cgi";
my $query     = CGI->new;
my @configs   = $query->param;
my %params    = $query->Vars;
my $hostfile  = "/usr/local/etc/rup";

print $query->header();

chomp(my $sshbin = `which ssh`);

open my $hosts, '<', $hostfile or die "Couldnt open $hostfile: $!";
my @hostlist = <$hosts>;
close($hosts);

foreach (@hostlist) {
       s/i$//;              &nbsp
;              &nbsp
;   # angehaengtes "i" entfernen
}

my %map = (
       exec_cmd        => \&exec_cmd,
);

my $output  = '';
my $options = join "\n", map{ qq~  <option value="$_">$_</option>~ }@hostlist;
my $goto    = $ENV{PATH_INFO};
   $goto    =~ s!^/!!;

if( exists $map{$goto} ){
    $output = $map{$goto}->(\%params);
    print_output( $output );
}
else{
    print_html( $options );
}

sub exec_cmd {
    my ($paramref) = @_;
    
    my %params   = %$paramref;
    my $server   = $params{'hostlist'};
    my $command  = $params{'command'};
    my $send2all = $params{'allhosts'};
    
    my $output   = ''
    if ($send2all eq "send2all") {               
           # ssh connect an alle rechner?
        foreach (@hostlist) {
               $output .= ssh_connect($_, $command);
        }
    } else {
        $output = ssh_connect($server, $command);              &nbs
p;          # ssh connect
    }

    return $output;
}

sub ssh_connect {
    my ($server,$command) = @_;
    my $output = qx{$sshbin $server $command};
    return $output;
}

sub print_html{
    my ($options) = @_;
}
print <<EOT;
<html>
<body>
 <form name="remotecmd" method="post" action="./remotecmd.cgi/exec_cmd">
 <table width="812" border="0" align="center">
 <tr>
 <td width="94">Hostname</td>
 <td width="86"> </td>
 <td width="610">Command:</td>
 </tr>
 <tr>
 <td><select name="hostlist" id="hostlist">
 $options
 </select></td>
 <td> </td>
 <td><input name="command" type="text" id="command" value="uname -a" size="70"></td>
 </tr>
 <tr>
 <td><input type="radio" name="allhosts" value="send2all">Alle Hosts </td>
 <td> </td>
 <td> </td>
 </tr>
 <tr>
 <td><input type="submit" name="Submit" value="Absenden"></td>
 <td><input name="cancel" type="reset" id="cancel" value="Zur&uuml;cksetzen"></td>
 <td> </td>
 </tr>
 </table>
 <p> </p>
 </form>
</body>
</html>
EOT
}

sub print_output{
    my ($out) = @_;
    print $out;
}


Du solltest aber sehr vorsichtig damit sein, dass man die Befehle übermittelt, die auf dem Server abgesetzt werden. Stell Dir vor, einer übermittelt "rm -rf /"
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
FlorianL
 2007-06-13 17:44
#77485 #77485
User since
2007-05-18
142 Artikel
BenutzerIn
[default_avatar]
...und das auch noch an alle rechner gleichzeitig :D

naja.. ich wär nich auf die idee gekommen sowas zu basteln aus dem genannten grund, aber wenn der herr das will, dann bekommt er es auch ;)

zum glück sind die server allesamt nicht von aussen zu erreichen, und auch das script wird später nur maximal einer hand voll zur verfügung stehen, die gefahr bleibt natürlich, haste recht :)

Quote
[Wed Jun 13 15:40:23 2007] remotecmd.cgi: syntax error at /usr/local/apache/xadmweb/cgi-bin/remote/remotecmd.cgi line 56, near ") {"
[Wed Jun 13 15:40:23 2007] remotecmd.cgi: syntax error at /usr/local/apache/xadmweb/cgi-bin/remote/remotecmd.cgi line 61, near "}"
[Wed Jun 13 15:40:23 2007] remotecmd.cgi: Execution of /usr/local/apache/xadmweb/cgi-bin/remote/remotecmd.cgi aborted due to compilation errors.
[Wed Jun 13 15:40:23 2007] [error] [client 10.43.26.23] malformed header from script. Bad header=<pre>syntax error at /usr/loca: /usr/local/apache/xadmweb/cgi-bin/remote/remotecmd.cgi


ich schau morgen mal ob ich weiter komm, aber heut nich mehr... in 10 minuten geht die bahn nach hause... schönen tag noch!
renee
 2007-06-13 17:59
#77486 #77486
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Hier sind die Syntax-Fehler beseitigt:
Code (perl): (dl )
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/perl
#
# Remote-Cmd F.Luettgens
########################
use strict;
use warnings;
use CGI;
use CGI::Carp qw(fatalsToBrowser);

my $cgi       = "/cgi-bin/remotecmd/remotecmd.cgi";
my $query     = CGI->new;
my @configs   = $query->param;
my %params    = $query->Vars;
my $hostfile  = "/usr/local/etc/rup";

print $query->header();

chomp(my $sshbin = `which ssh`);

open my $hosts, '<', $hostfile or die "Couldnt open $hostfile: $!";
my @hostlist = <$hosts>;
close($hosts);

foreach (@hostlist) {
       s/i$//;              &nbsp
;              &nbsp
;   # angehaengtes "i" entfernen
}

my %map = (
       exec_cmd        => \&exec_cmd,
);

my $output  = '';
my $options = join "\n", map{ qq~  <option value="$_">$_</option>~ }@hostlist;
my $goto    = $ENV{PATH_INFO};
   $goto    =~ s!^/!!;

if( exists $map{$goto} ){
    $output = $map{$goto}->(\%params);
    print_output( $output );
}
else{
    print_html( $options );
}

sub exec_cmd {
    my ($paramref) = @_;
    
    my %params   = %$paramref;
    my $server   = $params{'hostlist'};
    my $command  = $params{'command'};
    my $send2all = $params{'allhosts'};
    
    my $output   = '';
    if ($send2all eq "send2all") {               
           # ssh connect an alle rechner?
        foreach (@hostlist) {
               $output .= ssh_connect($_, $command);
        }
    } else {
        $output = ssh_connect($server, $command);              &nbs
p;          # ssh connect
    }

    return $output;
}

sub ssh_connect {
    my ($server,$command) = @_;
    my $output = qx{$sshbin $server $command};
    return $output;
}

sub print_html{
    my ($options) = @_;
    print <<EOT;
<html>
<body>
 <form name="remotecmd" method="post" action="./remotecmd.cgi/exec_cmd">
 <table width="812" border="0" align="center">
 <tr>
 <td width="94">Hostname</td>
 <td width="86"> </td>
 <td width="610">Command:</td>
 </tr>
 <tr>
 <td><select name="hostlist" id="hostlist">
 $options
 </select></td>
 <td> </td>
 <td><input name="command" type="text" id="command" value="uname -a" size="70"></td>
 </tr>
 <tr>
 <td><input type="radio" name="allhosts" value="send2all">Alle Hosts </td>
 <td> </td>
 <td> </td>
 </tr>
 <tr>
 <td><input type="submit" name="Submit" value="Absenden"></td>
 <td><input name="cancel" type="reset" id="cancel" value="Zur&uuml;cksetzen"></td>
 <td> </td>
 </tr>
 </table>
 <p> </p>
 </form>
</body>
</html>
EOT
}

sub print_output{
    my ($out) = @_;
    print $out;
}
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
<< |< 1 2 3 >| >> 21 Einträge, 3 Seiten



View all threads created 2007-06-13 13:26.