我正在编写一个shell脚本来自动执行我们执行的一些繁琐的任务。我需要ssh到服务器并远程更改PATH变量,让该变量持续存在以执行下一个命令。代码如下;
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
}
然而,PATH不会改变。有没有其他方法来实现这个或我做错了什么。我需要自动执行任务,所以不要认为$ ssh-> shell会对此有所帮助。请建议。
我根据建议进行了更改,一切正常。但是我注意到另一个问题,即在尝试显示环境变量时发生的问题。
my $cmd_ref_pri={
cmd0=>"echo $ENV{'HOME'}",
cmd1=>"chmod 777 $ENV{'COMMON_TOP'}/temp"
};
现在我使用Net :: SSH :: Perl连接到远程服务器,$ ENV {“HOME”}返回的值是my主目录的值,而不是远程服务器的值。但是,如果我添加命令:
my $cmd_ref_pri={
cmd0=>"whoami ; echo $ENV{'HOME'}",
cmd1=>"chmod 777 $ENV{'COMMON_TOP'}/temp"
};
然后显示的用户ID是我用来远程服务器的用户。我没有安装其他模块,唯一可用的是Net:SSh:perl,因此我不得不使用它。
执行命令的例程
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;
}
有关为何会发生这种情况的任何建议?
答案 0 :(得分:1)
cmd()
未将您的命令传递到一个shell中。它在单独的shell中执行它们(或者没有任何shell - 手册并不清楚它)。一旦你完成export PATH
shell退出并且新的PATH丢失。
看起来可以将所有相关命令作为单独的$ stdin行传递给单个shell进程?
my $stdin='export A=B
echo $A
';
$ssh->cmd("bash",$stdin);
这就像在交互式登录上一样(但没有终端控制,因此直接与终端对话的命令可能会失败)。
无论如何Net :: SSH :: Perl看起来不是最好的工具。我宁愿使用expect
进行自动化。
答案 1 :(得分:1)
在每个命令调用上设置PATH:
$ssh->cmd('PATH=/usr/bin/sudo:/local/perl-5.6.1/bin:$PATH echo $PATH');
BTW,Net :: SSH :: Perl不再被维护,现在Net::SSH2和Net::OpenSSH是更好的选择。
答案 2 :(得分:0)
将命令写入远程临时文件,然后执行该文件。或者,跳过$ PATH并使用后续命令的完整路径(假设您知道它)。