-1

I trying to execute terminal commands use Jsch. I have 3 servers: 1) server where application is installed; 2) server where database is installed; 3) ftp server where I want to store file. I get dump by using Jsch api and utility "expdp" and dump extracted successfully. But then I want to send dump from database server to ftp server use Jsch api and commands "lftp -u username ftpServer" and "put dumpFile.dmp". That doesn't work and I don't know why. Here is my function:

    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();
        }
    }

In output streams I get: enter image description here And there isn't anything else. What I did wrong? I will appreciate for suggestions.

Reason why I use output stream is that after call command "lftp -u user ftp" i will get prompt, that will offer input password. Simple example:

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();
        }

    }

May be on a picture would be more clearly explanation what I try to do. enter image description here

Nick
  • 117
  • 1
  • 10

1 Answers1

0

If I recall correctly, ChannelExec will execute whatever is in setCommand when you call channel.connect(). There's no way to perform multiple executions after you've connected. Certainly writing to the output stream is not the right approach.

You may be able to set the command to perform multiple actions:

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

If that's not possible (I haven't tested it) then I would create a script on your host which takes any number of parameters and then execute that:

channel.setCommand("myScript someDir someFilename");

Where myScript looks something like:

#!/bin/bash
pwd;
whoami;
set ssl:verify-certificate no;
cd $1;
pwd;
put $2;
pwd;
Michael
  • 41,989
  • 11
  • 82
  • 128
  • You forget, that when you execute command "lftp -u username ftpServer" you will get prompt "password". (I added example). – Nick Jun 07 '18 at 11:33
  • @Nick You could use [`spawn` and `expect`](https://stackoverflow.com/questions/16928004/how-to-enter-ssh-password-using-bash/16928662) to get around that problem. – Michael Jun 07 '18 at 11:36
  • Thank you for your suggestion, I am going to try it. – Nick Jun 07 '18 at 12:31
  • The commands that the OP wants to execute are subcommands of the `lftp`, not top-level shell commands. So the suggestion in this answer is wrong. What OP does in the code is the correct approach. – Martin Prikryl Jun 08 '18 at 05:24
  • I don't actually understand what(who) is OP, but you right commands that are beloved command lftp are subcommands. – Nick Jun 08 '18 at 05:54
  • OP is you (Original Poster). – Martin Prikryl Jun 08 '18 at 10:11
  • Martin Prikryl may be do you have any suggestions? – Nick Jun 08 '18 at 20:01