3

JSchライブラリを使用してSFTPクライアントを開発しています。

問題は両方getであり、putメソッドのステータスは-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ですか?

4

1 に答える 1

3

ソースコードを見ると、ExitStatusがSFTPに実装されていないように見えます

channel.setExitStatus(reason_code);

セッションクラスの2つのケースの下でのみ実装されます

case SSH_MSG_CHANNEL_OPEN_FAILURE:
case SSH_MSG_CHANNEL_REQUEST:

そして、両方のケースは、私がテストした成功したシナリオでは少なくとも呼ばれていません。

于 2013-02-21T17:04:05.237 に答える