mojo_the_helper has asked for the wisdom of the Perl Monks concerning the following question:

why doesnt this work, it seems like it should... to me at least?
#!/usr/bin/perl -w use strict; my $host; my @hosts = ("host1","host2"); foreach $host (@hosts) { if(`ping $host -c 1` == 0) { `ssh $host Start.sh &`; } }

Replies are listed 'Best First'.
Re: shell execution question
by dws (Chancellor) on Jun 07, 2003 at 03:33 UTC
    why doesnt this work, it seems like it should... to me at least?

    For enlightenment on this question, try

    print `ping host1 -c 1`;
    and ponder the result.

Re: shell execution question
by kelan (Deacon) on Jun 07, 2003 at 03:36 UTC

    You probably want to be using the system command instead of using backticks. Backticks capture the output of the command and return it to the Perl program. The system command, however, goes off and executes the program, returning the exit value to the Perl program. That seems to be what you want for the if condition, where you're checking for a return value of 0 (successful exit). For the ssh command inside the if block, maybe take a look at the exec command. It starts the given command, replacing the running Perl program, which it kind of looks like you want to do. Maybe give us a better idea of what the intended operation of your program is and we can help a bit more.

    kelan


    Perl6 Grammar Student

      I've always been a fan of IPC::Open3 for things like this. With it, you can catch and manipulate STDIN, STDOUT, and STDERR, and it makes things like ping, ssh, rsync and rlogin type-tasks very easy.

      You could also look into Net::Ping, Net::SSH, File::Rsync, and File::Remote, depending on exactly what it is you're trying to do on that remote system.

      `Backticks` are almost never what you want to use, the most-obvious reason being the glaring security implications.

(jeffa) Re: shell execution question
by jeffa (Bishop) on Jun 07, 2003 at 05:24 UTC
    Sometimes solving a problem is only fixing a symptom. If you are really wanting to automate some commands via ssh, you really should look into btrott's Net::SSH::Perl. Here's an example:
    use strict; use warnings; use Net::SSH::Perl; my $user = ''; my $pass = ''; my @host = qw(host1 host2); for my $host (@host) { my $ssh = Net::SSH::Perl->new($host, protocol => "2,1"); $ssh->login($user,$pass); my ($stdout, $stderr, $exit) = $ssh->cmd('hostname'); print STDOUT $stdout if $stdout; print STDERR $stderr if $stderr; print "remote command exited with [$exit]\n"; }
    I don't think you need to ping each host first, but should you still want to, check out Net::Ping.

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: shell execution question
by gellyfish (Monsignor) on Jun 07, 2003 at 08:58 UTC
    The SSH part aside you might want to do something like
    #!/usr/bin/perl -w use Net::Ping; use strict; my @hosts = qw(www.gellyfish.com petunia.gellyfish.com); my $ping = Net::Ping->new('icmp'); foreach my $host ( @hosts ) { if ( $ping->ping($host) ) { print "$host OK\n"; } }
    Now the problem with this is that you need root privileges to use the icmp protocol - you could use udp or tcp instead but this is dependent on the echo service being available on the hosts being checked.