我正在使用Java中的Ganymed ssh lib连接到Linux计算机并执行一些Unix脚本,并显示其输出。
我正在运行一个父Shell脚本,该脚本反过来又运行其他几个子脚本,最后运行一个Perl脚本。对于shell脚本,所有命令都可以正常工作,但是当它到达perl脚本时,我将停止获取任何输出。
如果我在Linux服务器上手动运行父脚本,我会看到perl的输出没有问题。
这是相关的Java代码,连接到机器并调用Shell脚本,并返回一个BufferedReader,从中可以逐行读取输出:
try {
conn = new Connection(server);
conn.connect();
boolean isAuthenticated = conn.authenticateWithPublicKey(user, keyfile, keyfilePass);
if (isAuthenticated == false) {
throw new IOException("Authentication failed.");
}
sess = conn.openSession();
if (param == null) {
sess.execCommand(". ./.bash_profile; cd $APP_HOME; ./parent_script.sh");
}
else {...}
InputStream stdout = new StreamGobbler(sess.getStdout());
reader = new BufferedReader(new InputStreamReader(stdout));
} catch (IOException e) {
e.printStackTrace();
}
我的父shell脚本如下所示:
./start1 #script1 output OK
./start2 #script2 output OK
./start3 #script3 output OK
/u01/app/perl_script.pl # NO OUTPUT HERE :(
会有人知道为什么会这样吗?
编辑:添加perl脚本
#!/u01/app/repo/code/sh/perl.sh
use FindBin qw/ $Bin /;
use File::Basename qw/ dirname /;
use lib (dirname($Bin). "/pm" );
use Capture::Tiny qw/:all/;
use Data::Dumper;
use Archive::Zip;
use XML::Simple;
use MXA;
my $mx = new MXA;
chdir $mx->config->{$APP_HOME};
warn Dumper { targets => $mx->config->{RTBS} };
foreach my $target (keys %{ $mx->config->{RTBS}->{Targets} }) {
my $cfg = $mx->config->{RTBS}->{Targets}->{$target};
my @commands = (
[
...
],
[
'unzip',
'-o',
"$cfg->{ConfigName}.zip",
'Internal/AdapterConfig/Driver.xml'
],
[
'zip',
"$cfg->{ConfigName}.zip",
'Internal/AdapterConfig/Driver.xml'
],
[
'rm -rf Internal'
],
[
"rm -f $cfg->{ConfigName}.zip"
],
);
foreach my $cmnd (@commands) {
warn Dumper { command => $cmnd };
my ($stdout, $stderr, $status) = capture {
system(@{ $cmnd });
};
warn Dumper { stdout => $stdout,
stderr => $stderr,
status => $status };
}
=pod
warn "runnnig -scriptant /ANT_FILE:mxrt.RT_${target}argets_std.xml /ANT_TARGET:exportConfig -jopt:-DconfigName=Fixing -jopt:-DfileName=Fixing.zip');
($stdout, $stderr, $status) = capture {
system('./command.app', '-scriptant -parameters');
}
($stdout, $stderr, $status) = capture {
system('unzip Real-time.zip Internal/AdapterConfig/Driver.xml');
};
my $xml = XMLin('Internal/AdapterConfig/MDPDriver.xml');
print Dumper { xml => $xml };
[[ ${AREAS} == "pr" ]] && {
${PREFIX}/substitute_mdp_driver_parts Internal/AdapterConfig/Driver.xml 123 controller@mdp-a-n1,controller@mdp-a-n2
} || {
${PREFIX}/substitute_mdp_driver_parts Internal/AdapterConfig/Driver.xml z8pnOYpulGnWrR47y5UH0e96IU0OLadFdW/Bm controller@md-uat-n1,controller@md-uat-n2
}
zip Real-time.zip Internal/AdapterConfig/Driver.xml
rm -rf Internal
rm -f Real-time.zip
print $mx->Dump( stdout => $stdout,
stderr => $stderr,
status => $status );
=cut
}
答案 0 :(得分:2)
Perl代码中产生输出的部分是:
warn Dumper { stdout => $stdout,
stderr => $stderr,
status => $status };
看the documentation for warn()
,我们看到:
发出警告,通常将其打印到
STDERR
但是您的Java程序正在读取STDOUT
。
InputStream stdout = new StreamGobbler(sess.getStdout());
您有两种选择。
STDOUT
而不是STDERR
。将warn()
更改为print()
可能很简单。在shell脚本中调用Perl程序时,redirect STDERR
to STDOUT
。
/u01/app/perl_script.pl 2>&1
我想您也可以将Java程序设置为也可以从STDERR
读取。但是我不是Java程序员,所以我无法为您提供最佳的建议。