2

How do I run multiple commands in SSH using Java runtime?

the command: ssh user@127.0.0.1 'export MYVAR=this/dir/is/cool; /run/my/script /myscript; echo $MYVAR'

@Test
  public void testSSHcmd() throws Exception
  {
    StringBuilder cmd = new StringBuilder();

    cmd.append("ssh ");
    cmd.append("user@127.0.0.1 ");
    cmd.append("'export ");
    cmd.append("MYVAR=this/dir/is/cool; ");
    cmd.append("/run/my/script/myScript; ");
    cmd.append("echo $MYVAR'");

    Process p = Runtime.getRuntime().exec(cmd.toString());
  }

The command by its self will work but when trying to execute from java run-time it does not. Any suggestions or advice?

stackoverflow
  • 18,348
  • 50
  • 129
  • 196

6 Answers6

5

Use the newer ProcessBuilder class instead of Runtime.exec. You can construct one by specifying the program and its list of arguments as shown in my code below. You don't need to use single-quotes around the command. You should also read the stdout and stderr streams and waitFor for the process to finish.

ProcessBuilder pb = new ProcessBuilder("ssh", 
                                       "user@127.0.0.1", 
                                       "export MYVAR=this/dir/is/cool; /run/my/script/myScript; echo $MYVAR");
pb.redirectErrorStream(); //redirect stderr to stdout
Process process = pb.start();
InputStream inputStream = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line = null;
while((line = reader.readLine())!= null) {
    System.out.println(line);
}
process.waitFor();
dogbane
  • 266,786
  • 75
  • 396
  • 414
  • Hi dogbane I need to run multiple ssh commands in a single run, the link which you shared was not clear to me. So ple if you have any clear document can you please share to me. Thanks – Anand Kumar May 06 '16 at 10:16
1

The veriant of Runtime.exec you are calling splits the command string into several tokens which are then passed to ssh. What you need is one of the variants where you can provide a string array. Put the complete remote part into one argument while stripping the outer quotes. Example

Runtime.exec(new String[]{ 
    "ssh", 
    "user@127.0.0.1", 
    "export MYVAR=this/dir/is/cool; /run/my/script/myScript; echo $MYVAR"
});

That's it.

A.H.
  • 63,967
  • 15
  • 92
  • 126
1

If the Process just hangs I suspect that /run/my/script/myScript outputs something to stderr. You need to handle that output aswell as stdout:

public static void main(String[] args) throws Exception {
    String[] cmd = {"ssh", "root@localhost", "'ls asd; ls'" };
    final Process p = Runtime.getRuntime().exec(cmd);

    // ignore all errors (print to std err)
    new Thread() {
        @Override
        public void run() {
            try {
                BufferedReader err = new BufferedReader(
                        new InputStreamReader(p.getErrorStream()));
                String in;
                while((in = err.readLine()) != null)
                    System.err.println(in);
                err.close();
            } catch (IOException e) {}
        }
    }.start();

    // handle std out
    InputStreamReader isr = new InputStreamReader(p.getInputStream());
    BufferedReader reader = new BufferedReader(isr);

    StringBuilder ret = new StringBuilder();
    char[] data = new char[1024];
    int read;
    while ((read = reader.read(data)) != -1)
        ret.append(data, 0, read);
    reader.close();

    // wait for the exit code
    int exitCode = p.waitFor();
}
dacwe
  • 43,066
  • 12
  • 116
  • 140
0

Here is the right way to do it:

Runtime rt=Runtime.getRuntime();
rt.exec("cmd.exe /c start <full path>");

For example:

Runtime rt=Runtime.getRuntime();
rt.exec("cmd.exe /c start C:/aa.txt");
Jason Sturges
  • 15,855
  • 14
  • 59
  • 80
0

If you are using SSHJ from https://github.com/shikhar/sshj/

public static void main(String[] args) throws IOException {
    final SSHClient ssh = new SSHClient();
    ssh.loadKnownHosts();

    ssh.connect("10.x.x.x");
    try {
        //ssh.authPublickey(System.getProperty("root"));
        ssh.authPassword("user", "xxxx");
        final Session session = ssh.startSession();

        try {
            final Command cmd = session.exec("cd /backup; ls; ./backup.sh");
            System.out.println(IOUtils.readFully(cmd.getInputStream()).toString());
            cmd.join(5, TimeUnit.SECONDS);
            System.out.println("\n** exit status: " + cmd.getExitStatus());
        } finally {
            session.close();
        }
    } finally {
        ssh.disconnect();
    }
}
depicus
  • 301
  • 4
  • 19
  • Hi Depicus I need to run multiple ssh commands in a single run, the link which you shared was not clear to me. So ple if you have any clear document can you please share to me. Thanks – Anand Kumar May 06 '16 at 07:05
  • Hi Anand, basically separate each command with a ; and you should be good to go. The link works for me. – depicus May 07 '16 at 11:08
  • okay Depicus. I need to run multiple ssh commands with select query to view the status. I can't execute the query if you know how to execute select query please let me know. Here I Show the full commands. cd /aep/cu/scripts/;./dbutil.ksh E1QA;select * from tgpoa01.aud_trail_dtl where AUD_TRAIL_REC_ID = '-9223372036798689753' – Anand Kumar May 09 '16 at 05:17
  • The `System.out.println(IOUtils.readFully(cmd.getInputStream()).toString());` line should return any output – depicus May 11 '16 at 21:35
0

You might want to take a look at the JSch library. It allows you to do all sorts of SSH things with remote hosts including executing commands and scripts.

They have examples listed here: http://www.jcraft.com/jsch/examples/

Chris Dail
  • 25,715
  • 9
  • 65
  • 74