java - JSch ChannelSftp 退出状态始终为 -1

标签 java sftp jsch

我使用 JSch 库开发 SFTP 客户端。

问题是 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它说:

退出状态仅对某些类型的 channel 可用,并且仅在 channel 关闭后(更准确地说,就在 channel 关闭之前)可用。

我如何知道 ChannelSftp 的退出状态是否可用?

最佳答案

查看源代码,似乎没有为 SFTP 实现 ExitStatus

channel.setExitStatus(reason_code);

在Session类中仅针对以下两种情况实现

case SSH_MSG_CHANNEL_OPEN_FAILURE:
case SSH_MSG_CHANNEL_REQUEST:

并且至少对于我测试的成功场景,这两种情况都没有被调用。

关于java - JSch ChannelSftp 退出状态始终为 -1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14751266/

相关文章:

java - Log4j.properties 在类路径上但未加载

java - 即使未在 Spring Boot 配置文件中指定,也会在 Spring Boot 中加载方法

linux - 使用 wget 和 SFTP 获取文件

java - 在 Java 中使用 JSch 列出 SFTP 服务器上目录的完整层次结构

java - 使用 Java JSch 确定来自 SFTP 服务器的最新文件

java - 使用 == 与 .equals 比较 Java 中的字符串

java - 将 bitmab 从 Activity 传递回 Fragment

python - 我可以从 Python 脚本控制 PSFTP 吗?

Perl远程写文件连接报错Net::SFTP::Foreign

java - Jsch - 每个 session 多个 channel