I am having trouble executing commands on a remote GNU/Linux system over SSH from Java. The following commands work fine when executed in the local Bash (of course the user and host are different but the behaviour is unchanged).
$ ssh [email protected] 'hostname'
host
$ ssh [email protected] 'hostname -f'
host.example.com
$ ssh [email protected] "hostname -f"
host.example.com
Doing what I think is the same from Java fails for anything more complex than hostname without arguments.
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.Executor;
import org.apache.commons.exec.PumpStreamHandler;
public class SOPlayground {
public static void main(String[] args) throws Exception {
for (String argument : new String[]{"hostname", "'hostname'", "\"hostname\"",
"'hostname -f'", "\"hostname -f\""}) {
CommandLine commandLine = new CommandLine("ssh");
commandLine.addArgument("[email protected]");
commandLine.addArgument(argument);
System.out.println(commandLine);
final Executor executor = new DefaultExecutor();
try (ByteArrayOutputStream os = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream()) {
executor.setStreamHandler(new PumpStreamHandler(os, err));
int exitcode = executor.execute(commandLine);
System.out.println("exitcode=" + exitcode);
System.out.println(new String(os.toByteArray(), "UTF-8"));
System.err.println(new String(err.toByteArray(), "UTF-8"));
} catch (IOException ex) {
System.err.println(ex.getMessage());
}
}
}
}
The output is:
ssh [email protected] hostname
exitcode=0
host
ssh [email protected] 'hostname'
exitcode=0
host
ssh [email protected] "hostname"
exitcode=0
host
ssh [email protected] 'hostname -f'
Process exited with an error: 127 (Exit value: 127)
ssh [email protected] "hostname -f"
Process exited with an error: 127 (Exit value: 127)
As you can see, executing hostname -f over SSH from Java fails with an exit code of 127. I wonder what bash (local or remote) was unable to find what command.
I've tried to use the variant
addArgument(String argument, boolean handleQuoting)
but there was no difference in the result.
How must I build a CommandLine from Java that works over SSH?
JSch shell = new JSch(); session = shell.getSession(userName, serverIP, 22); session.setPassword(password);execto execute a single remote command and then closes the connection, please post it as an answer.