2013-02-07 49 views
2

我使用JSch库开发SFTP客户端。JSch ChannelSftp退出状态总是-1

问题是getput方法的状态是-1。

这里是我的代码:

class SftpClient { 
    private static final Logger LOG = Logger.getLogger(SftpClient.class); 

    /** Connection port number */ 
    public static final int PORT = 22; 

    /** SECURED protocol name */ 
    private static final String PROTOCOL = "sftp"; 

    /** Connection time out in milliseconds */ 
    public static final int TIME_OUT = 5000; 

    /** This class serves as a central configuration point, and as a factory for Session objects configured with these settings */ 
    private JSch _client; 
    /** A session represents a connection to a SSH server */ 
    private Session _session; 
    /** Channel connected to a SECURED server (as a subsystem of the SSH server) */ 
    private ChannelSftp _channelSftp; 

    /** 
    * Value returned by the last executed command. 
    */ 
    private int _exitValue; 

    /** 
    * Computer contains the url, the login and the password to connect. 
    */ 
    private Computer _computer; 

    /** 
    * Initialize a SECURED client 
    * @param target - Machine we want to connect to 
    */ 
    public SftpClient(Computer target) { 
     _client = new JSch(); 
     _computer = target; 
    } 

    protected void connect() throws Exception { 
     try { 
      if (_client == null) { 
       _client = new JSch(); 
      } 
      if (_session == null) { 
       _session = _client.getSession(_computer.getLogin(), _computer.getUrl(), PORT); 
       Properties props = new Properties(); 
       props.put("StrictHostKeyChecking", "no"); 
       props.put("compression.s2c", "zlib,none"); 
       props.put("compression.c2s", "zlib,none"); 
       _session.setConfig(props); 
       _session.setPassword(_computer.getPassword()); 
       if (LOG.isDebugEnabled()) { 
        LOG.debug("Connecting to "+_computer.getUrl()+" with login "+_computer.getLogin()+"..."); 
       } 
      } 
      if (!_session.isConnected()) { 
       _session.connect(TIME_OUT); 
      } 
      // disconnect previous channel if it has not been killed properly 
      if (_channelSftp != null && _channelSftp.isConnected()) { 
       _channelSftp.disconnect(); 
      } 
      _channelSftp = (ChannelSftp) _session.openChannel(PROTOCOL); 
      _channelSftp.connect(); 
      if (LOG.isInfoEnabled()) { 
       LOG.info("Connected to "+_computer.getUrl()+" with login "+_computer.getLogin()); 
      } 
     } catch(JSchException e) { 
      LOG.error("Auth failed", e); 
      throw e; 
     } 
    } 

    protected void connect(String path) throws Exception { 
     connect(); 
     if (_channelSftp != null && _channelSftp.isConnected()) { 
      _channelSftp.cd(path); 
     } 
    } 

    public boolean get(final String remoteDirectory, final String remoteFile, final String localDirectory) throws Exception { 
     boolean res = false; 
     if (LOG.isInfoEnabled()) { 
      LOG.info("Download file "+remoteDirectory+"/"+remoteFile+" from "+_computer+" in "+localDirectory); 
     } 
     if (remoteDirectory != null && remoteFile != null && !remoteFile.isEmpty() && localDirectory != null) { 
      try { 
       // connect to the server and change directory 
       connect(remoteDirectory); 
       // change local directory 
       _channelSftp.lcd(localDirectory); 
       // download the file, keeping the same name 
       _channelSftp.get(remoteFile, remoteFile); 
       // update exit value 
       _exitValue = _channelSftp.getExitStatus(); 

       if (_exitValue == 0) { 
        res = true; 
       } 
       if (LOG.isDebugEnabled()) { 
        LOG.debug("Exit status is: "+_exitValue); 
       } 
      } catch(SftpException e){ 
       LOG.error("Auth failed", e); 
       throw e; 
      } finally { 
       if (_channelSftp != null && _channelSftp.isConnected()) { 
        _channelSftp.disconnect(); 
        _channelSftp.exit(); 
       } 
      } 
     } else { 
      LOG.warn("Check remoteDirectory ('"+remoteDirectory+"') or remoteFile ('"+remoteFile+"') or localDirectory ('"+localDirectory+"')."); 
     } 
     return res; 
    } 

    public void put(final File localFile, final String destPath) throws Exception { 
     if (LOG.isInfoEnabled()) { 
      LOG.info("Send file "+localFile+" to "+_computer+" in "+destPath); 
     } 
     if (localFile == null) { 
      _exitValue = -1; 
      LOG.error("The given local file is null. Aborting tranfer."); 
      return; 
     } 
     if (!localFile.exists()) { 
      _exitValue = -1; 
      LOG.error("The given local file '"+localFile+"' does not exist. Aborting tranfer."); 
      return; 
     } 
     final InputStream input = new FileInputStream(localFile); 
     if (input == null || input.available() <= 0) { 
      _exitValue = -1; 
      LOG.error("Cannot read file "+localFile); 
      return; 
     } 
     try { 
      connect(destPath); 
      _channelSftp.put(input, localFile.getName()); 
      _exitValue = _channelSftp.getExitStatus(); 
      if (LOG.isDebugEnabled()) { 
       LOG.debug("Exit status is: "+_exitValue); 
      } 
     } catch(SftpException e){ 
      LOG.error("Auth failed", e); 
      throw e; 
     } finally { 
      if (_channelSftp != null && _channelSftp.isConnected()) { 
       _channelSftp.disconnect(); 
       _channelSftp.exit(); 
      } 
      IOUtils.closeQuietly(input); 
     } 
    } 

    public void disconnect() { 
     if (_channelSftp != null && _channelSftp.isConnected()) { 
      _channelSftp.disconnect(); 
      _channelSftp.exit(); 
     } 
     if (_session != null && _session.isConnected()) { 
      _session.disconnect(); 
      if (LOG.isInfoEnabled()) { 
       LOG.info("SECURED FTP disconnected"); 
      } 
     } 
    } 
} 

没有抛出异常。

顺便说一句,我想上传和下载的文件是tar文件。 Jsch有一个FTP二进制模式吗?

文件传输良好。我可以正确使用它们,但我担心退出状态。

我看看到Jsch API和它说:

The exit status is only available for certain types of channels, and only after the channel was closed (more exactly, just before the channel is closed).

我怎么能知道,如果退出状态是可以ChannelSftp

回答

1

查看源代码,它看起来退出状态不是为SFTP

channel.setExitStatus(reason_code); 

在会话类只有空两例实施实施

case SSH_MSG_CHANNEL_OPEN_FAILURE: 
case SSH_MSG_CHANNEL_REQUEST: 

和两种情况都不会为atleast叫我测试过的成功案例。

+0

所以没有办法从服务器获取回复代码?如何知道请求是否成功? – Maxbester

+0

请查阅http://code.google.com/p/securechannelfacade/source/browse/branches/test/src/main/java/org/rev6/scf/SshTask.java –

+0

好的,所以唯一的方法就是使用像JSch例子中的'checkAck()'方法......无论如何。 – Maxbester