这是我第一次尝试在Perl中内联Java代码。我们无法在我们的系统上使用标准SFTP命令。这是我的力量。我们有一个名为SFTP.jar的jar文件可以使用。在我之前的前一个人能够让Inline :: Perl工作,但他的实现很草率,我想清理它。
我正在H:\svn
目录上的Windows系统上工作。我的模块位于H:\svn\FMS3
目录下,我在SFTP.jar
目录下有一个名为H:\svn\FMS3\Sftp.pm
的jar文件。在Sftp.pm
目录下有一个名为H:\svn\FMS3
的文件,它定义了一个名为FMS3::Sftp
的模块。 (我将所有自定义模块保留在FMS3
父模块下。)
我在FMS3::Sftp
中内联了代码,看起来它编译了。但是,当我尝试执行时,它声称Can't exec JVM: open3: Can't call method "close" on an undefined value at C:/Perl/lib/IPC/Open3.pm line 370
。
究竟我做错了什么?
FMS3::Sftp
模块:
#! /usr/bin/env perl
# Sftp.pm
########################################################################
########################################################################
# PACKAGE FMS3::Sftp
#
package FMS3::Sftp;
#
########################################################################
########################################################################
# PERL PRAGMAS
#
use strict;
use warnings;
use vars qw($PERL_CLASSPATH);
#
########################################################################
########################################################################
# CONSTANTS
#
use constant {
FTP_SERVER => "10.85.10.190",
FTP_USER => "fisaftp",
FTP_PASSWORD => "Fisa123456",
};
#
########################################################################
########################################################################
# INITIALIZE
#
# Set a PERL_CLASSPATH that will include all directories in the
# @INC array. Somewhere in this array will be located our JAR file
# that we need to include, and of course, this classpath.
#
# This will be appended to the standard $CLASSPATH environment variable.
#
BEGIN {
use Config;
my $cpsep;
if ($Config{osname} =~ /^mswin32/i) {
$cpsep = ";";
} else {
$cpsep = ":";
}
$PERL_CLASSPATH = join("/FMS3/Sftp/SFTP.jar$cpsep", @INC);
$PERL_CLASSPATH = "$PERL_CLASSPATH/FMS3/Sftp/SFTP.jar";
}
#
########################################################################
########################################################################
#
# PERL INLINE JAVA CODE:
#
use Inline (
Java => 'DATA',
J2SDK => $ENV{JAVA_HOME},
CLASSPATH => $PERL_CLASSPATH,
STUDY => ["SFTP", "close", "list", "get", "put", "remove"],
DEBUG => 4,
);
#
########################################################################
########################################################################
# CONSTRUCTORS
#
sub new {
my $class = shift;
my $server = shift;
my $user = shift;
my $password = shift;
if (not $server) { $server = FTP_SERVER; }
if (not $user) { $user = FTP_USER; }
if (not $password) { $password = FTP_PASSWORD; }
my $self = {};
bless($self, $class);
eval {$self->{CONNECTION} = new SFTP($server, $user, $password);};
if ($@) {
$self->{ERROR} = $@;
return;
}
return $self;
}
#
########################################################################
########################################################################
# DESTRUCTOR (Automatic close on losing $self)
#
sub DESTROY {
my $self = shift;
$self->{CONNECTION}->close();
return 1;
}
#
########################################################################
########################################################################
# List
#
sub List {
my $self = shift;
my $location = shift;
my @list;
eval {@list = $self->{CONNECTION}->list($location);};
if ($@) {
$self->{ERROR} = $@;
return;
}
return @list;
}
#
########################################################################
########################################################################
# Get
#
sub Get {
my $self = shift;
my $file = shift;
my $location = shift;
eval {$self->{CONNECTION}->get($file, $location);};
if ($@) {
$self->{ERROR} = $@;
return;
}
return 1;
}
#
########################################################################
########################################################################
# Put
#
sub Put {
my $self = shift;
my $file = shift;
my $location = shift;
my $mode = shift;
eval {$self->{CONNECTION}->put($file, $location, $mode);};
if ($@) {
$self->{ERROR} = $@;
return;
}
return 1;
}
#
########################################################################
########################################################################
# Remove
#
sub Remove {
my $self = shift;
my $file = shift;
eval {$self->{CONNECTION}->remove($file);};
if ($@) {
$self->{ERROR} = $@;
return;
}
return 1;
}
#
########################################################################
########################################################################
# Error
#
sub Error {
my $self = shift;
return $self->{ERROR};
}
#
########################################################################
1;
__DATA__
__Java__
import com.trilead.ssh2.*;
import java.io.IOException;
import java.util.*;
public class SFTP {
ConnectionInfo ci;
SCPClient sftp=null;
SFTPv3Client sftpv3=null;
Connection conn=null;
public SFTP(String host, String username, String password) {
boolean b=false;
conn= new Connection(host);
try {
ci=conn.connect();
b=conn.authenticateWithPassword(username,password);
if (!b) {
System.out.println("Invalid login.");
System.exit(0);
}
sftp = new SCPClient( conn );
sftpv3 = new SFTPv3Client (conn);
} catch (IOException e) {
System.out.println("Unable to connect"+": "+e.getMessage());
}
}
public void close()
{
conn.close();
}
public String[] list (String loc)
{
Vector v=null;
SFTPv3DirectoryEntry x=null;
try
{
v = sftpv3.ls(loc);
} catch (IOException e) {
System.out.println("Pickup location does not exist, please check!");
String[] value = new String[1];
return value;
}
String[] s=new String[v.size()];
for (int i=0; i<v.size(); i++) {
x = (SFTPv3DirectoryEntry)v.elementAt(i);
s[i]=x.filename;
}
return s;
}
public void get (String file, String loc)
{
try{
sftp.get(file,loc);
} catch (IOException e) {
System.out.println("Unable to download, please check location or file permissions");
}
}
public void put (String file, String loc, String mode)
{
try{
sftp.put(file,loc,mode);
} catch (IOException e) {
System.out.println("Unable to put"+": "+e.getMessage());
}
}
public void remove (String file)
{
try{
sftpv3.rm(file);
} catch (IOException e) {
System.out.println("Unable to remove"+": "+e.getMessage());
}
}
}
我有一个名为test.pl的测试程序,如下所示:
use FMS3::Sftp;
my $ftp = FMS3::Sftp->new();
print $ftp->List(".");
我要做的就是连接到我们的服务器并执行目录列表。但是,我在尝试运行test.pl
[perl][1] validate done.
[perl][1] Starting build.
[perl][4] portable: ENV_VAR_PATH_SEP_CP for MSWin32 is ';'
[perl][4] portable: SUB_FIX_JAVA_PATH => H:\svn for MSWin32 is default 'H:\svn'
[perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\db2java.zip for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\db2java.zip'
[perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc.jar for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc.jar'
[perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\sqlj.zip for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\sqlj.zip'
[perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc_license_cu.jar for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc_license_cu.jar'
[perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\bin for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\bin'
[perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\common.jar for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\common.jar'
[perl][4] portable: SUB_FIX_JAVA_PATH => D:\Program Files\Rational\ClearQuest\cqjni.jar for MSWin32 is default 'D:\Program Files\Rational\ClearQuest\cqjni.jar'
[perl][4] portable: SUB_FIX_JAVA_PATH => C:\Perl\site\lib\Inline\Java\InlineJavaServer.jar for MSWin32 is default 'C:\Perl\site\lib\Inline\Java\InlineJavaServer.jar'
[perl][2] classpath candidate 'C:/Perl/site/lib/FMS3/Sftp/SFTP.jar' scraped
[perl][2] classpath candidate 'C:/Perl/lib/FMS3/Sftp/SFTP.jar' scraped
[perl][4] portable: SUB_FIX_JAVA_PATH => H:\svn\FMS3\Sftp\SFTP.jar for MSWin32 is default 'H:\svn\FMS3\Sftp\SFTP.jar'
[perl][2] classpath: H:\svn;D:\PROGRA~1\IBM\SQLLIB~1\java\db2java.zip;D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc.jar;D:\PROGRA~1\IBM\SQLLIB~1\java\sqlj.zip;D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc_license_cu.jar;D:\PROGRA~1\IBM\SQLLIB~1\bin;D:\PROGRA~1\IBM\SQLLIB~1\java\common.jar;D:\Program Files\Rational\ClearQuest\cqjni.jar;C:\Perl\site\lib\Inline\Java\InlineJavaServer.jar;H:\svn\FMS3\Sftp\SFTP.jar
[perl][4] portable: J2SDK_BIN for MSWin32 is 'bin'
[perl][4] portable: EXE_EXTENSION for MSWin32 is '.exe'
[perl][4] portable: IO_REDIR for MSWin32 is '2>&1'
[perl][4] portable: SUB_FIX_JAVA_PATH => H:\svn\_Inline\lib\auto\FMS3\Sftp_7ae5 for MSWin32 is default 'H:\svn\_Inline\lib\auto\FMS3\Sftp_7ae5'
[perl][4] portable: SUB_FIX_CMD_QUOTES => "C:\Program Files\Java\jdk1.6.0_17\bin\javac.exe" -deprecation -d "H:\svn\_Inline\lib\auto\FMS3\Sftp_7ae5" SFTP.java > cmd.out 2>&1 for MSWin32 is default '"C:\Program Files\Java\jdk1.6.0_17\bin\javac.exe" -deprecation -d "H:\svn\_Inline\lib\auto\FMS3\Sftp_7ae5" SFTP.java > cmd.out 2>&1'
[perl][2] "C:\Program Files\Java\jdk1.6.0_17\bin\javac.exe" -deprecation -d "H:\svn\_Inline\lib\auto\FMS3\Sftp_7ae5" SFTP.java > cmd.out 2>&1
[perl][4] portable: COMMAND_COM for MSWin32 is '0'
[perl][2] classpath: .;D:\PROGRA~1\IBM\SQLLIB~1\java\db2java.zip;D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc.jar;D:\PROGRA~1\IBM\SQLLIB~1\java\sqlj.zip;D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc_license_cu.jar;D:\PROGRA~1\IBM\SQLLIB~1\bin;D:\PROGRA~1\IBM\SQLLIB~1\java\common.jar;D:\Program Files\Rational\ClearQuest\cqjni.jar
[perl][1] build done.
[perl][1] Starting load.
[perl][4] portable: ENV_VAR_PATH_SEP_CP for MSWin32 is ';'
[perl][4] portable: SUB_FIX_JAVA_PATH => H:\svn for MSWin32 is default 'H:\svn'
[perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\db2java.zip for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\db2java.zip'
[perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc.jar for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc.jar'
[perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\sqlj.zip for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\sqlj.zip'
[perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc_license_cu.jar for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc_license_cu.jar'
[perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\bin for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\bin'
[perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\common.jar for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\common.jar'
[perl][4] portable: SUB_FIX_JAVA_PATH => D:\Program Files\Rational\ClearQuest\cqjni.jar for MSWin32 is default 'D:\Program Files\Rational\ClearQuest\cqjni.jar'
[perl][4] portable: SUB_FIX_JAVA_PATH => C:\Perl\site\lib\Inline\Java\InlineJavaServer.jar for MSWin32 is default 'C:\Perl\site\lib\Inline\Java\InlineJavaServer.jar'
[perl][2] classpath: H:\svn;D:\PROGRA~1\IBM\SQLLIB~1\java\db2java.zip;D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc.jar;D:\PROGRA~1\IBM\SQLLIB~1\java\sqlj.zip;D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc_license_cu.jar;D:\PROGRA~1\IBM\SQLLIB~1\bin;D:\PROGRA~1\IBM\SQLLIB~1\java\common.jar;D:\Program Files\Rational\ClearQuest\cqjni.jar;C:\Perl\site\lib\Inline\Java\InlineJavaServer.jar
[perl][1] starting JVM...
[perl][1] client/server mode
[perl][4] portable: GOT_NEXT_FREE_PORT for MSWin32 is '0'
[perl][4] portable: J2SDK_BIN for MSWin32 is 'bin'
[perl][4] portable: EXE_EXTENSION for MSWin32 is '.exe'
[perl][4] portable: SUB_FIX_CMD_QUOTES => "C:\Program Files\Java\jdk1.6.0_17\bin\java.exe" org.perl.inline.java.InlineJavaServer 4 localhost 7890 false false false for MSWin32 is default '"C:\Program Files\Java\jdk1.6.0_17\bin\java.exe" org.perl.inline.java.InlineJavaServer 4 localhost 7890 false false false'
[perl][2] "C:\Program Files\Java\jdk1.6.0_17\bin\java.exe" org.perl.inline.java.InlineJavaServer 4 localhost 7890 false false false
[perl][4] portable: DEV_NULL for MSWin32 is 'nul'
[perl][1] JVM owner exiting...
Can't exec JVM: open3: Can't call method "close" on an undefined value at C:/Perl/lib/IPC/Open3.pm line 370.
at C:/Perl/site/lib/Inline/Java.pm line 484
INIT failed--call queue aborted.
[perl][1] killed by natural death.
[perl][1] exiting with 22
答案 0 :(得分:3)
好。我想到了。我有几个错误:
use Inline (
Java => 'DATA',
J2SDK => $ENV{JAVA_HOME},
CLASSPATH => $PERL_CLASSPATH,
STUDY => ["SFTP", "close", "list", "get", "put", "remove"],
# DEBUG => 4,
);
use Inline (
Java => 'DATA',
J2SDK => $ENV{JAVA_HOME},
CLASSPATH => $PERL_CLASSPATH,
STUDY => ["SFTP"],
# DEBUG => 4,
);
new
时,我必须为其提供完整的Perl命名空间:eval {$self->{CONNECTION} = new SFTP($server, $user, $password);};
eval {$self->{CONNECTION} = new FMS3::Sftp::SFTP($server, $user, $password);};
你花了几个小时在这样的事情上,放弃,然后突然间,在'尘土飞扬的阁楼里的灯亮了。我是一个相当聪明的人。将螺丝刀插入带电插座,第三次或第四次之后,我会“嘿,也许这不是一个好主意”。
答案 1 :(得分:1)
尝试使用Net :: SFTP :: Foreign,如果将它与plink(PuTTY软件包中的命令行ssh客户端)一起使用,则不需要任何其他模块来使其正常工作。