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

I have a problem running Perl script through ssh. My script is on remote linux machine and I want to execute it from another machine using ssh. When I login with ssh ( ssh root@machine_name and provide root password) and run the perl script, it works. But if I want to run the script through same command.( ssh root@machine_name perl /research-sar/sarexec.pl start /research-sar/param.txt /research-sar/logs/log.txt 2 ) These are all the parameters to the script.The it takes the password of root , after that it doesnt return to command prompt. If I run any linux-command other than perl script it runs properly and return to command line. Please find the solution.

Replies are listed 'Best First'.
Re: Running Perl scripts from ssh
by Corion (Patriarch) on May 08, 2006 at 10:49 UTC

    This is not strictly a Perl question, but your Perl script may play into it. Please reduce your Perl script to a minimal example that produces that behaviour and post that example. If reducing your Perl script is too complicated, first test if the behaviour is linked to Perl at all by launching other commands in the same way.

    As a first step, try launching the following Perl script instead:

    #!/usr/bin/perl -w use strict; print "Hello world\n"; print "I got the following parameters: @ARGV\n";

    As an aside, you likely shouldn't run research scripts as the root user.

Re: Running Perl scripts from ssh
by blazar (Canon) on May 08, 2006 at 10:51 UTC
    Without seeing /research-sar/sarexec.pl it's hard to tell
    $ ssh q cat bin/hw.pl Password: #!/usr/bin/perl -l use strict; use warnings; print "Hello World!" __END__ $ ssh q bin/hw.pl Password: Hello World!
      Here is the whole sarexec.pl for you.. #sarexec.pl code.....
      #!/usr/bin/perl -w #exec /usr/bin/perl /research-sar/sarexec.pl use strict; #starting sar.... if($ARGV[0] eq 'start') { # Checking for correct parameters.. if (exists $ARGV[1] && exists $ARGV[2] && exists $ARGV[3]) { #print "present all things\n"; } else { #print "Missing parameters..cant continue..\n"; exit; } my $file_param; my $file_location; my $interval; $file_param = $ARGV[1]; $file_location = $ARGV[2]; open(FH,"> fileloc") or die"cant open the file"; print FH $file_location or die"cant print to file"; close(FH) or die "cant close the file"; $interval = $ARGV[3]; my $pid = fork(); if($pid==0) { #print "In child"; #print "$file_param"; my $param1; open FH,"< $file_param" or die"cant open the file"; #print "$file_param"; $param1 = <FH>; close FH or die "cant close the file"; chomp($param1); #print $param1; #my $testvar="-wWbB"; system("sar -o logfile $param1 $interval 0 > /dev/null&"); exit 0; } else { #print "In parent"; my $exitstatus = wait(); exit; } } # stopping sar..... elsif($ARGV[0] eq 'stop') { # Checking for correct parameters.. if (exists $ARGV[1]) { print "Bad parameters cant process\n"; exit; } my $loc; open FH, "< fileloc" or die " cant open file"; $loc = <FH> ; #print $loc; chomp($loc); close FH or die "cant close file"; system("kill \$(pidof sadc)"); system("sar -f logfile>>$loc"); } else { print " Wrong parameters"; }

        Part of your script is still running - that's why ssh doesn't terminate the connection:

        ... my $pid = fork(); ...

        You need to detach your child process from the parent process - maybe it's enough to close STDIN and STDOUT, but I'd use Proc::Daemon or what perldoc -q daemon says to start the program detached in the background:

        use POSIX qw(setsid); close STDIN; close STDOUT; close STDERR; # or better, reopen them into some logfile setsid(); fork && exit; # We are now detached from ssh
        A reply falls below the community's threshold of quality. You may see it by logging in.
        #!/usr/bin/perl -w #exec /usr/bin/perl /research-sar/sarexec.pl use strict;

        Good! Just as a suggestion on a minor point, try

        #!/usr/bin/perl use strict; use warnings;

        if($ARGV[0] eq 'start') { # Checking for correct parameters.. if (exists $ARGV[1] && exists $ARGV[2] && exists $ARGV[3]) { #print "present all things\n"; } else { #print "Missing parameters..cant continue..\n"; exit; }
        In Perl you don't need all those nested conditionals and there are alternatives that may increase readability. In this case you may want to create a start() and a stop() sub, then I'd do:
        my %action=(start => \&start, stop => \&stop); my $todo=shift || ''; die "Wrong parameters\n" unless $action{$todo}; goto $action{$todo}; # a "good" goto; # # ... # sub $start () { die "Missing parameters, can't continue!\n" unless @ARGV==3; my ($file_param,$file_location,$interval)=@ARGV; # ... }

        open(FH,"> fileloc") or die"cant open the file";
        open my $fh, '>', 'fileloc' or die "Can't open `fileloc': $!\n";

        my $pid = fork();

        Aha! => fork.