Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

execute sequense of commands in sshj

Tags:

java

ssh

sshj

I need to execute some sequence of commands at the remote server via ssh, using sshj library.

I do

        Session session = ssh.startSession();
        Session.Command cmd = session.exec("ls -l");
        System.out.println(IOUtils.readFully(cmd.getInputStream()).toString());
        cmd.join(10, TimeUnit.SECONDS);
        Session.Command cmd2 = session.exec("ls -a");
        System.out.println(IOUtils.readFully(cmd2.getInputStream()).toString());

and it throws me

net.schmizz.sshj.common.SSHRuntimeException: This session channel is all used up

But I can't recreate session for every single command, because this example it will show home directory list, but not the /some/dir list.

like image 892
NullPointer Avatar asked Mar 28 '14 21:03

NullPointer


2 Answers

As odd as it is, session can only be used once. So you have to reset the session every time.

    Session session = ssh.startSession();
    Session.Command cmd = session.exec("ls -l");
    System.out.println(IOUtils.readFully(cmd.getInputStream()).toString());
    cmd.join(10, TimeUnit.SECONDS);

    session = ssh.startSession();
    Session.Command cmd2 = session.exec("ls -a");
    System.out.println(IOUtils.readFully(cmd2.getInputStream()).toString());

Or if the shell you are connecting to supports delimited commands (and the situation allows it), you can do this (bash example):

session.exec("ls -l; <command 2>; <command 3>");

like image 63
lampwins Avatar answered Oct 22 '22 22:10

lampwins


You can consider using an Expect-like third party library which simplifies working with remote services and capturing output. Those libraries are designed to execute a sequence of commands. Here is a good set of options you can try:

  • Expect4J
  • ExpectJ
  • Expect-for-Java

However, when I was about to solve similar problem I found these libraries are rather old. They also introduce a lot of unwanted dependencies. So I created my own and made it available for others. It is called ExpectIt. The advantages of my library it are stated on the project home page. You can give it a try.

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

    SSHClient ssh = new SSHClient();
    ...
    ssh.connect("sdf.org");
    ssh.authPassword("new", "");
    Session session = ssh.startSession();
    session.allocateDefaultPTY();
    Shell shell = session.startShell();
    Expect expect = new ExpectBuilder()
            .withOutput(shell.getOutputStream())
            .withInputs(shell.getInputStream(), shell.getErrorStream())
            .build();
    try {
        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(": $"));
        expect.send("\b");
        expect.expect(regexp("\\(y\\/n\\)"));
        expect.sendLine("y");
        expect.expect(contains("Would you like to sign the guestbook?"));
        expect.send("n");
        expect.expect(contains("[RETURN]"));
        expect.sendLine();
    } finally {
        session.close();
        ssh.close();
        expect.close();
    }

Here is the link to the complete workable example.

like image 26
Alexey Gavrilov Avatar answered Oct 22 '22 22:10

Alexey Gavrilov