Hi Karim,
i faced the same problem some time ago, though not in the context of Web
App. asked on this list, got a fair response and customized to my needs
(don't remember who it was that responded but kudos and credits due :) ).
The way I used is to issue a connect command when the session begins. you
hold the inputStream and outputStream of the channel as class members and
reuse them throughout the flow:

    public boolean connect() {
        try {
            lock.lock();
            if (this.ip == null) {
                log.error("tried to connect when IP is null. throwing
NullPointerException");
                throw new NullPointerException("Tried to connect when IP is
null");
            }
            if (this.userInfo == null) {
                log.error("tried to connect when UserInfo is null. throwing
NullPointerException");
                throw new NullPointerException("Tried to connect when
UserInfo is null");
            }
            if (this.userInfo.getUsername() == null) {
                log.error("tried to connect when UserInfo.Username is null.
throwing NullPointerException");
                throw new NullPointerException("Tried to connect when
UserInfo.Username is null");
            }
            log.debug("starting connect() to IP " + ip.toString());
            JSch jsch = new JSch();
            log.debug("jsch created");
            session = jsch.getSession(userInfo.getUsername(),
ip.getIpString(), Tweaks.getInt("network.port.ssh"));
            log.debug("session acquired from jsch");
            session.setPassword(userInfo.getPassword());
            log.debug("password set");
            java.util.Properties config = new java.util.Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            log.debug("set StrictHostKeyChecking=no");

            //                  session.setPassword(password);
            log.debug("sending session.connect()...");
            session.connect();
            log.debug("session.connect() returned with status: " +
session.isConnected());
            channel = session.openChannel("shell");
            log.debug("created channel of type shell");
            ((ChannelShell)channel).setPty(pty);
            log.debug("channel pty set to " + pty);
            channel.connect();
            log.debug("channel connected");
            stdIn = channel.getOutputStream();
            log.debug("stdIn set to channel's outputStream");
            stdOut = channel.getInputStream();
            log.debug("stdOut set to channel's inputStream");
            long timeout = 10*1000;  //10 seconds;
//            String response = read(timeout, "[Q] Quit");
            read(timeout);
//            String response = read(timeout);
//            log.debug("connect response: " + response);

            log.debug("returning connected=" + session.isConnected());
            return session.isConnected();
        } catch (JSchException e) {
            //            e.printStackTrace();
            return false;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        } finally {
            lock.unlock();
        }
    }


then, each command is done with sendCommand:
    public String sendCommand(String command) {
        log.debug("starting sendCommand with command text: " + command);
        try {
            lock.lock();
            if (!session.isConnected()) {
                log.error("trying to send a command while session is
disconnected");
            }
            stdIn.write((command + "\n").getBytes());
            log.debug("command set to channel");
            stdIn.flush();
            log.debug("stdIn flushed");
//            String response = read(120*1000, "[Q] Quit");
            String response = read(120*1000);
//            log.debug("command response: " + response);
            return response;
        } catch (IOException e) {
            log.error("caught exception of type " + e.getClass() + ",
returning null", e);
            return null;
        } finally {
            lock.unlock();
        }
    }

to send each command and get it's response. this model assumes you know what
the output should be (or could be) and you need to parse it from the output.
a good thing to use for an endian of the output is the prompt, if known.

the read() method below is in charge of reading the output, and also has
facets to handle longer-than-screen output ("hit enter to continue...")
parsing and sending the correct 'continue' command (if known).

    private String read(long timeoutInMillis) {
        StringBuilder readText = new StringBuilder();
        List<String> cleanup = new CopyOnWriteArrayList<String>();
        try {
            lock.lock();
            long startTime = System.currentTimeMillis();
            ByteBuffer readBuffer = ByteBuffer.allocate(1);
            boolean promptFound = false;
            boolean timeputExceeded = false;
            log.debug("starting read");
            while (true) {
//                log.debug("while(true) starting");
                while (stdOut.available() > 0) {
//                    log.debug("stdOut has bytes available");
                    int i = stdOut.read(readBuffer.array(), 0, 1);
//                        log.debug("read " + i + " bytes from input
stream");
//                        log.debug("\tpayload: " + new
String(readBuffer.array(), 0, i));
                    if (i < 0) {
                        log.debug("breaking read loop");
                        break;
                    }
                    readText.append(new String(readBuffer.array()));
//                    log.debug("readBuffer content appended to readText");
//                    System.out.println("StringBuffer content: " +
readText.toString());
                    readBuffer.clear();
//                    log.debug("readBuffer cleared");
                }

                if (prompt != null) {
                    //no more bytes in inputStream. check if what was
already read contains the expected endian
                    if (readText.toString().contains(prompt)) {
                        log.debug("found prompt (" + prompt + "), breaking
read loop");
                        promptFound = true;
                        break;
                    }
                }
                //endian not found, checking if timeout is exceeded
                if (isTimeoutExceeded(startTime, timeoutInMillis)) {
                    log.error("timeout exceeded, breaking read loop");
                    timeputExceeded = true;
                    break;
                }

                //check if there is a 'continue' note, and send appropriate
continue commnad
                for (Object continueStringKeyObject :
continueChallangeStrings.keySet()) {
                    String continueString =
continueChallangeStrings.getProperty((String)continueStringKeyObject);
                    if (readText.toString().contains(continueString)){
//                        String prefix = new
StringTokenizer((String)continueStringKeyObject, ".").nextToken();
                        String continueCommand =
Tweaks.getString(((String)continueStringKeyObject).replace("challanges",
"responses"));
                        log.debug("found 'continue' prompt: " +
continueChallangeStrings.getProperty((String)continueStringKeyObject));
//                        readText.replace(readText.indexOf(continueString),
readText.indexOf(continueString)+continueString.length(), "");
                        log.debug("sending continue key: " +
continueCommand);
//                        stdIn.write((continueCommand+"\n").getBytes());
                        stdIn.write((continueCommand).getBytes());
                        stdIn.flush();
//
readText.replace(readText.indexOf(continueCommand),
readText.indexOf(continueCommand)+continueCommand.length(), "");
                        cleanup.add(continueString);
                        cleanup.add(continueCommand);
                    }
                }


                //checking if the channel is closed [error, channel should
not be cloesd here]
                if (channel.isClosed()) {
                    log.error("channel is closed. exit-status: " +
channel.getExitStatus());
                    break;
                }

                //endian not found and timeout not exceeded, sleeping 1
second
                // and looping in hope the inputStream will have more bytes
soon
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    log.debug("interruped while sleeping in read loop");
                }
            }
            if (prompt == null) {
                prompt =
readText.toString().substring(readText.lastIndexOf("\n")+promptSeekOffset);
                log.debug("prompt set to " + prompt);
            }
            return readText.toString();
        } catch (IOException e) {
            log.error("caught IOException while reading channel. returning
null", e);
            return null;
        } finally {
            lock.unlock();
        }
    }


On Fri, Apr 2, 2010 at 9:24 AM, karim aklouche <[email protected]>wrote:

> Hi all
>
> I need to plan a web application design in order to perform configuration
> management.
> for some use cases we need to implement some kind of expect and support
> multiple commands execution remotly.
>
> we've been through the Shell example but without any idea on how to
> redirect steams in order to implement some kind of expect interface to be
> able to trigger commands based on  a previous command response.
>
> Did anyone have done this kind of interface and how?
>
> Regards
>
> Karim
>
>
>
> ------------------------------------------------------------------------------
> Download Intel&#174; Parallel Studio Eval
> Try the new software tools for yourself. Speed compiling, find bugs
> proactively, and fine-tune applications for parallel performance.
> See why Intel Parallel Studio got high marks during beta.
> http://p.sf.net/sfu/intel-sw-dev
> _______________________________________________
> JSch-users mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/jsch-users
>
>
------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
JSch-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jsch-users

Reply via email to