Question

I am writing a shell script to automate some of the tedious tasks that we perform. I need to ssh to a server and change the PATH variable remotely, have that variable persist for the next commands to be executed. Code below;

sub ab_tier{
 my $ssh=Net::SSH::Perl->new($host);
 $ssh->login($user2,$user2);
 my $PATH;
 my($stdout,$stderr,$exit)=$ssh->cmd("export
 PATH=/usr/bin/sudo:/local/perl-5.6.1/bin:$PATH");
 my($PATH, $stderr, $exit)=$ssh->cmd("echo $PATH");
 print $PATH; # Check the path for correctness : does not change 
}

However the PATH does not change. Is there another way to implement this or am I doing something wrong. I need to automate tasks so dont think $ssh->shell would help here. Please suggest.


I made changes as per suggestions and everything works fine. However I am noticing another issue, which is occurring when trying to display environment variables.

  my $cmd_ref_pri={
    cmd0=>"echo $ENV{'HOME'}",
    cmd1=>"chmod 777 $ENV{'COMMON_TOP'}/temp"
  };

Now I am connecting to a remote server using Net::SSH::Perl and the value returned by $ENV{"HOME"} is the value of the my home directory and not of the remote server. However if I add a command as in :

    my $cmd_ref_pri={
       cmd0=>"whoami ; echo $ENV{'HOME'}",
       cmd1=>"chmod 777 $ENV{'COMMON_TOP'}/temp"
     };

Then the user id displayed is of the user using which I ssh to the remote server. I do not have other modules installed and the only one available is Net:SSh:perl hence I am forced to use this.

routine for executing command

    sub ssh_cmd{
       #$cmd_sub - contains command, $ssh contains object ref
       my ($cmd_sub,$ssh)=@_;
       my($stdout, $stderr, $exit)=$ssh->cmd("bash",$cmd_sub);
       if( $exit !=0){
       print $stdout;
       print  "ERROR-> $stderr";
       exit 1;
     }
    return 0;
   }

Any suggestions as to why this could happen ?

Was it helpful?

Solution

cmd() is not passing your commands into one shell. It executes them in separate shells (or without any shell - manual is not clear about it). As soon as you finish your export PATH the shell exits and the new PATH is lost.

Looks like it is possible to pass all the relevant commands to a single shell process as separate lines of $stdin?

my $stdin='export A=B
echo $A
';
$ssh->cmd("bash",$stdin);

This would work just like on interactive login (but without terminal control, so commands that talk directly to terminal would likely fail).

Anyway Net::SSH::Perl does not look like the best tool for the job. I would rather use expect for automation.

OTHER TIPS

Set PATH on every command call:

$ssh->cmd('PATH=/usr/bin/sudo:/local/perl-5.6.1/bin:$PATH echo $PATH');

And BTW, Net::SSH::Perl is not being maintained anymore, nowadays Net::SSH2 and Net::OpenSSH are better alternatives.

Write commands to a remote temp file, then execute that one. Or, skip the $PATH thing and use the full path for subsequent commands (assuming you know it).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top