hi Ehud
Thanks a lot for your very reactive response. This will probably help us a
lot.
Actually we did use Jsch for few years now in the context of multiple
appliczation for provisioning as well as telecom platform config
management.
But we need to comply to some customer specific requirement now and I had in
mind to either use expect or adapt jsch that I'm addicted to.
We'll test your proposition. however, thanks to all who have helped to come
up with this.
Thanks again
Karim
On Fri, Apr 2, 2010 at 8:12 PM, Ehud Kaldor <[email protected]> wrote:
> 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® 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® 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