Java - JSCH Library - 运行命令,它需要密码

时间:2015-08-25 04:19:04

标签: java jsch

我正在编写一个java程序,它在本地Linux主机上运行rsync以将数据复制到远程主机。我正在使用jsch库。我查看了jsch示例,但我没有发现任何相关内容。

我无法设置密钥身份验证,因此当rsync命令运行提示输入密码时,我希望自动输入远程主机的密码。

我在网上搜索了一些方法,我找不到任何简单的方法。

以下函数只执行输入命令,此函数是具有服务器,用户名,密码的类的一部分

public int executeCommand(String command) throws Exception {
    JSch jsch = new JSch();
    Session session = null;
    Channel channel = null;
    int exitCode;
    try {
        //Initialize session
        session = jsch.getSession(this.username, this.server, 22);
        session.setPassword(this.password);
        session.setConfig("StrictHostKeyChecking", "no");
        session.setConfig("PreferredAuthentications", "publickey,password");
        //Connect
        session.connect();
        //Open a channel for communication
        channel = session.openChannel("shell");

        OutputStream ops = channel.getOutputStream();
        PrintStream ps = new PrintStream(ops, true);

        channel.connect();

        logger.info("Sending command {} ",command);
        ps.println(command);
        ps.flush();

        InputStream inputStream = channel.getInputStream();

        processOutput(inputStream, "password:", timeout);
        logger.info("Sending password.");
        ps.println(this.targetPassword);
        ps.flush();


        processOutput(inputStream, "total size is", timeout);

        //Get the process exit code
        String exitCodeCommand = "echo $?";
        logger.info("Sending command {} ",exitCodeCommand);
        ps.println(exitCodeCommand);
        ps.flush();

        String exitCodeOutput = processOutput(inputStream, "", 0.5);

        String[] outputArray = exitCodeOutput.split(System.lineSeparator());

        if (outputArray.length < 2) {
            String msg = String.format("Exit code of command $1%s is invalid %2$s", exitCodeCommand,
                    exitCodeOutput);
            throw new Exception(msg);
        }

        try {
            exitCode = Integer.parseInt(outputArray[1]);
        } catch (NumberFormatException nfe) {
            logger.error("Exception occurred while parsing {}", outputArray[1], nfe);
            String msg = String.format("Exit code of command $1%s is invalid %2$s. Exit code parsed %3$s is " +
                    "not an integer", exitCodeCommand, exitCodeOutput, outputArray[2]);
            throw new Exception(msg);
        }

        logger.info("Exit code {}", exitCode);

        inputStream.close();
        ps.close();
        channel.disconnect();
        session.disconnect();
    } catch (JSchException e) {
        logger.error("Exception occurred while creating session with {}. Error message {}", this.server, e
                .getMessage(), e);            
    } catch (IOException e) {
        logger.error("Exception occurred while creating performing IO with server {}. Error message {}", this
                .server, e.getMessage(), e);            
    } finally {
        logger.info("Closing channels");
        if (channel != null && !channel.isClosed()) {
            channel.disconnect();
        }
        if (session != null) {
            session.disconnect();
        }
    }
    return exitCode;
}

private String processOutput(InputStream inputStream, String outToFind, double timeout) throws Exception {
    byte[] bt = new byte[1024];

    StringBuilder builder = new StringBuilder();

    double timeoutBeforeExit = timeout * 1000 * 60;

    double timeElapsed = 0;

    while (true) {
        try {
            while (inputStream.available() > 0) {
                int i = inputStream.read(bt, 0, 1024);
                if (i < 0) {
                    break;
                }
                String str = new String(bt, 0, i);
                builder.append(str);
                //displays the output of the command executed for debug purpose.
                logger.info(str);
                if (str.contains(outToFind)) {
                    logger.info("{} output is found.", outToFind);
                    return builder.toString();
                } else {
                    logger.info("{} is not matched", str);
                }
            }
        } catch (IOException e) {
            logger.error("Exception occurred while creating performing IO with server {}. Error message {}", this
                    .server, e.getMessage(), e);
            throw new Exception(e.getMessage());
        }
        timeElapsed = timeElapsed + SLEEP_TIME;

        if (timeElapsed >= timeoutBeforeExit) {
            throw new Exception("Timeout while waiting for output.");
        }

        try {
            Thread.sleep(SLEEP_TIME);
        } catch (InterruptedException e) {
            logger.warn("Benign exception occurred inputStream thread sleep. Continuing.", e);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

您可以尝试以下代码。它会自动读取提供的密码并继续运行下一个命令。

 /**
     * Transfer a file to remote destination via JSCH library using sFTP protocol
     * 
     * @param username String remote SFTP server user name.
     * @param password String remote SFTP server user password
     * @param host String remote SFTP server IP address or host name.
     * @param file File to transfer to SFTP Server.
     * @param transferProtocol protocol to transfer a file. {@link FileTransferProtocol}
     * @return boolean true if file is transfered otherwise false.
     * @throws ApplicationException
     */
    public static boolean transferFile(final String username, final String password, final String host,
                                       final File file, final FileTransferProtocol transferProtocol) {
  //      throws ApplicationException {
        // currently can deal with sftp only.
 //       LOGGER.trace("Invoking transferFile...");
        JSch jsch = new JSch();
        try {
            Session session = jsch.getSession(username, host);
 //           LOGGER.debug("Session Host: " + session.getHost());
            session.setPassword(password);
            Properties properties = new Properties();
            properties.put("StrictHostKeyChecking", "no");
            session.setConfig(properties);
 //           LOGGER.debug("Connecting to a session Host Server...");
            session.connect();
 //           LOGGER.debug("session is established with host server.");
 //           Channel channel = session.openChannel(transferProtocol.ftpStringRepresentation());
            Channel channel = session.openChannel("sftp");
 //           LOGGER.debug("Connecting to a sftp Channel...");
            channel.connect();
 //           LOGGER.debug("Connected with sftp Channel.");
            ChannelSftp channelSftp = (ChannelSftp) channel;
            channelSftp.put(new FileInputStream(file), file.getName());
 //           LOGGER.debug("File transfered successfully");
            channelSftp.exit();
 //           LOGGER.debug("sftp channel disconnected.");
            channel.disconnect();
 //           LOGGER.debug("channel disconnected.");
            session.disconnect();
  //          LOGGER.debug("session disconnected.");
            return true;
        } catch (JSchException | FileNotFoundException | SftpException e) {
            e.printStackTrace();
//            LOGGER.error(e.getMessage(), e.getCause());
//            throw new ApplicationException(e.getMessage(), ApplicationSeverity.ERROR, e.getCause(), e);
        }
        return false;
    }