Question

I am using Jsch library to execute about 1000 different of shell scripts in few linux machines and update the status into a table.

I used jsch exec channel [ChannelExec], it was working only for the single script, if the shell script calls another script, ChannelExec was not giving correct result.

now I am using shell channnel of jsch. it is working well to get output from any kind of shell script.

the problem is, if I execute many shell scripts at once , I am getting all result in one bulk.

there is no way to get one Shell script executed and its result received.

if i want to get individual scripts execution result, I need to login to the machine for each script execution , this is taking very long time.

can somebody post a solution, suggestion on how to go about , login into machine once and execute multiple scripts and receive each script result individually.

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;

public class JschShellExample {

    public static void main(String[] args) {

        try {
            JSch jsch = new JSch();

            Session session = jsch.getSession("user", "10.32.248.158", 22);
            session.setPassword("password");

            java.util.Properties config = new java.util.Properties();
            config.put("StrictHostKeyChecking", "no");
            config.put("PreferredAuthentications","publickey,keyboard-interactive,password");
            session.setConfig(config);
            session.connect(100);

            Channel channel = session.openChannel("shell");

            OutputStream inputstream_for_the_channel = channel.getOutputStream();
            PrintStream commander = new PrintStream(inputstream_for_the_channel, true);

            channel.setOutputStream(null);
            channel.connect(100);
            //shell script
            commander.println("cd /user/home/work ; ./checkstaus.sh ; exit");
            commander.flush();

            System.out.println(channel.getExitStatus());

            InputStream outputstream_from_the_channel = channel.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(outputstream_from_the_channel));
            String line = null;
            StringBuilder sb = new StringBuilder();
            boolean isloginStringPassed = false ;

            while ((line = br.readLine()) != null) {
                    sb.append(line.trim());
            }
            System.out.println("Result ="+sb.toString());

            channel.disconnect();
            session.disconnect();
            System.out.println("completed .. ");
        } catch (JSchException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

}
Was it helpful?

Solution

Usually when you connect to a remote machine for the first time and after executing a command you'll get a shell command line prompt printed to the output stream. You can use it as a marker between output of different shell commands.

You may consider using an Expect-like third party library which simplify working with a remote services and capturing output. There a good set of options you can try:

However, when I was about to solve similar problem I found these libraries are rather old and hard to use in a commercial software. So I created my own and made it available for others. It it called ExpectIt. The advantages of my library it are stated on the project home page.

Here is an example of interacting with a public remote SSH service:

    JSch jSch = new JSch();
    Session session = jSch.getSession("new", "sdf.org");
    Properties config = new Properties();
    config.put("StrictHostKeyChecking", "no");
    session.setConfig(config);
    session.connect();
    Channel channel = session.openChannel("shell");

    Expect expect = new ExpectBuilder()
            .withOutput(channel.getOutputStream())
            .withInputs(channel.getInputStream(), channel.getExtInputStream())
            .withEchoOutput(adapt(System.out))
    //        .withInputFilters(removeColors(), removeNonPrintable())
            .withErrorOnTimeout(true)
            .build();
    // try-with-resources is omitted for simplicity
    channel.connect();
    expect.expect(contains("[RETURN]"));
    expect.sendLine();
    String ipAddress = expect.expect(regexp("Trying (.*)\\.\\.\\.")).group(1);
    System.out.println("Captured IP: " + ipAddress);
    expect.expect(contains("login:"));
    expect.sendLine("new");
    expect.expect(contains("(Y/N)"));
    expect.send("N");
    expect.expect(regexp(": $"));
    // finally is omitted
    channel.disconnect();
    session.disconnect();
    expect.close();

You can also take a look a at this example interacting with a Karaf shell which captures individual command output.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top