0

I understand how to create a ssh shell

Shell ssh = new SshByPassword("192.168.1.5", 22, "admin", "password");

i also understand how to run a command

String output = new Shell.Plain(ssh).exec("some command");

and i can easly analyze the output string

but how do i send in the same "shell" one command after the other

and bonus question sometimes the commands require a user confirmation ("press Y to continue")

is it possible with the library?

naoru
  • 2,149
  • 5
  • 34
  • 58

1 Answers1

1

Generally, most Java SSH APIs leave it to the developer to sort out the complexities of executing multiple commands within a shell. It is a complicated problem because SSH does not provide any indication of where commands start and end within the shell; the protocol only provides a stream of data, which is the raw output of the shell.

I would humbly like to introduce my project Maverick Synergy. An open-source API (LGPL) that does provide an interface for interactive shells. I documented the options for interactive commands in an article.

Here is a very basic example, the ExpectShell class allows you to execute multiple commands, each time returning a ShellProcess that encapsulates the command output. You can use the ShellProcess InputStream to read the output, it will return EOF when the command is done.

You can also use a ShellProcessController to interact with the command as this example shows.

SshClient ssh = new SshClient("localhost", 22, "lee", "xxxxxx".toCharArray());

ssh.runTask(new ShellTask(ssh) { 
    protected void onOpenSession(SessionChannelNG session) 
         throws IOException, SshException, ShellTimeoutException { 

         ExpectShell shell = new ExpectShell(this);

         // Execute the first command
         ShellProcess process = shell.executeCommand("ls -l");
         process.drain();
         String output = process.getCommandOutput();

         // After processing output execute another
         ShellProcessController controller =  
               new ShellProcessController(
                  shell.executeCommand("rm -i file.txt"));              

         if(controller.expect("remove")) {         
             controller.typeAndReturn("y");     
         }           

         controller.getProcess().drain();
   }
});

ssh.disconnect();
  • Thanks for the suggestion its looks very nicely coded but in the example given i see only one command which is the delete file, how for example i run an ls -l and based on the output rm a file? – naoru Feb 19 '20 at 15:15
  • I have edited my answer to show 2 commands, but you can execute as many commands as you want sequentially, the only requirement is that you make sure the previous command has completed, that means using drain on the ShellProcess, or ensuring the InputStream of the process returns EOF. – Lee David Painter Feb 19 '20 at 22:14
  • im sorry i wasnt able even to install it... i check the documentation and the maven coordinates point to maverick-synergy-client version 3.0.0, and its not on maven, in maven under com.sshtools there is the Maverick Legacy Client version 1.8.2 i tried this one but its not the one you are referring to... – naoru Feb 20 '20 at 15:17
  • Its currently a SNAPSHOT version and you need to add sonatype snapshots repository in it. I've updated the documentation on the project page to reflect this. – Lee David Painter Feb 20 '20 at 17:47
  • im always getting a timeout when trying to execute the runTask (without timeout param it just hangs) Task did not complete before the specified timeout – naoru Feb 25 '20 at 15:38
  • As discussed in your email to me, the problem is that ExpectShell is designed around bash type shells and your connecting to a router OS which does not support some of the commands required to place markers in the output which allows us to distinguish between command output. I'm looking into ways to support this. – Lee David Painter Feb 26 '20 at 16:12