登录后执行几个命令使用Jsch

时间:2018-06-07 11:14:07

标签: java jsch

我尝试使用Jsch执行终端命令。我有3台服务器:1)安装了应用程序的服务器; 2)安装数据库的服务器; 3)我要存储文件的ftp服务器。 我通过使用Jsch api和实用程序“expdp”获得转储并成功转储提取。但后来我想从数据库服务器发送转储到ftp服务器使用Jsch api并命令“lftp -u username ftpServer”和“put dumpFile.dmp”。这不起作用,我不知道为什么。这是我的功能:

    public void passDataFromDbServerToFtpServer(String dbUserName, String dbUserPassword, String dbHost, String dbDumpDir,
                                                String ftpUserName, String ftpUserPassword, String ftpDomain, String ftpDir, String fileName) throws ExtractionDumpException {
        JSch jsch = new JSch();
        Session session = null;
        Channel channel = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;
        BufferedReader bufferedReader = null;
        String line;
        try{
            session = jsch.getSession(dbUserName, dbHost, 22);
            Properties config = new Properties();
            config.put("PreferredAuthentications", "publickey,keyboard-interactive,password");
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.setPassword(dbUserPassword);
            session.connect();
//            String command = "cd " + dbDumpDir + "; pwd; gzip " + fileName + ".dmp; lftp -u " + ftpUserName + " " + ftpDomain;
            String command = "lftp -u " + ftpUserName + " " + ftpDomain;
            channel = session.openChannel("exec");
            ((ChannelExec) channel).setCommand(command);
            inputStream = channel.getInputStream();
            outputStream = channel.getOutputStream();
            ((ChannelExec) channel).setErrStream(System.err);
            bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            channel.connect();
            outputStream.write((ftpUserPassword + "\n").getBytes());
//            outputStream.write(("pwd; set ssl:verify-certificate no; cd " + ftpDir + "; pwd; put " + fileName + ".dmp.gz; pwd\n").getBytes());
            outputStream.write(("pwd\n").getBytes());
            outputStream.write(("whoami\n").getBytes());
            outputStream.write(("set ssl:verify-certificate no\n").getBytes());
            outputStream.write(("cd " + ftpDir + "\n").getBytes());
            outputStream.write(("pwd\n").getBytes());
            outputStream.write(("put " + fileName + ".dmp.gz\n").getBytes());
            outputStream.write(("pwd\n").getBytes());
            outputStream.flush();
            log.debug("Execute command from dbServer on ftpServer");
            while((line = bufferedReader.readLine()) != null){
                log.debug(line);
                System.out.println(line);
            }
        } catch (JSchException | IOException e) {
            log.error("Dump extraction failed", e);
            throw new ExtractionDumpException(e);
        } finally {
            try {
                bufferedReader.close();
                inputStream.close();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            channel.disconnect();
            session.disconnect();
        }
    }

在输出流中我得到: enter image description here 而且没有别的。 我做错了什么? 我将很感激您的建议。

我使用输出流的原因是在调用命令“lftp -u user ftp”之后我会得到提示,这将提供输入密码。简单的例子:

public static void main(String[] args) {
        JSch jsch = null;
        Session session = null;
        String host = "example";
        String user = "example";
        String password = "example";
        String su_pass = "example";
        String su_command = "example";
        Channel channel = null;
        InputStream in = null;
        OutputStream out = null;
        BufferedReader bufferedReader = null;
        try {
            jsch = new JSch();
            session = jsch.getSession(user, host, 22);
            Properties config = new Properties();
            config.put("PreferredAuthentications", "publickey,keyboard-interactive,password");
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.setPassword(password);
            session.connect();
            channel = session.openChannel("exec");
            ((ChannelExec) channel).setCommand(su_command);
            in = channel.getInputStream();
            out = channel.getOutputStream();
            ((ChannelExec)channel).setErrStream(System.err);
            channel.connect();
            out.write((su_pass+"\n").getBytes());
            out.write(("whoami\n").getBytes());
            out.write(("pwd\n").getBytes());
            out.write(("cd /home/netcrk\n").getBytes());
            out.write(("pwd\n").getBytes());
            out.write(("mkdir test\n").getBytes());
            out.flush();
            String line = null;
            bufferedReader = new BufferedReader(new InputStreamReader(in));
            while((line = bufferedReader.readLine()) != null){
                System.out.println(line);
            }
//            byte[] tmp=new byte[1024];
//            while(true){
//                while(in.available()>0){
//                    int i=in.read(tmp, 0, 1024);
//                    if(i<0)break;
//                    System.out.print(new String(tmp, 0, i));
//                }
//                if(channel.isClosed()){
//                    System.out.println("exit-status: "+channel.getExitStatus());
//                    break;
//                }
//                try{Thread.sleep(1000);}catch(Exception ee){}
//            }

        } catch (JSchException | IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            channel.disconnect();
            session.disconnect();
        }

    }
可能会在图片上更清楚地解释我尝试做什么。 enter image description here

1 个答案:

答案 0 :(得分:0)

如果我没记错的话,ChannelExec会在您拨打setCommand时执行channel.connect()中的任何内容。在您连接后,无法执行多次执行。当然写入输出流不是正确的方法。

您可以设置命令以执行多个操作:

channel.setCommand("pwd; whoami; cd somewhere");

如果那不可能(我还没有测试过),那么我会在你的主机上创建一个脚本,它接受任意数量的参数,然后执行:

channel.setCommand("myScript someDir someFilename");

myScript看起来像:

#!/bin/bash
pwd;
whoami;
set ssl:verify-certificate no;
cd $1;
pwd;
put $2;
pwd;