I need to automate some linux console task. Those box are accessible via ssh password based authentication.
I have my local machine (A). One linux jump box (B). And one linux production box (C). The box "C" only accessible from jump box. The jump box and prodution box don't have java or Expect module. So i choose to do the automation from my local machine "A".
I try following method to execute command on box "C" via box "B". But it didn't work.
spawn.send("ssh " + strDestinUser + "@" + strDestinHost + " \"echo hello world | awk '{print \$1}'\"" + "\n");
spawn.expect("password:");
spawn.send(strDestinPass + "\n");
My full code block as follows
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.security.Security;
import java.util.Properties;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import expectj.ExpectJ;
import expectj.Spawn;
import expectj.TimeoutException;
public class App {
public static void main(String[] args) {
App objApp = new App();
String strJumpHost = "127.234.123.12";
String strJumpUser = "root_jump";
String strJumpPwd = "passforjump";
objApp.sshExecPassword(strJumpHost, strJumpUser, strJumpPwd);
}
public void sshExecPassword(String host, String USERNAME, String PASSWORD) {
App objApp = new App();
int port = 22;
try {
JSch jsch = new JSch();
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
Session session = jsch.getSession(USERNAME, host, port);
session.setConfig(config);
session.setConfig("PreferredAuthentications", "keyboard-interactive,password"); // Skip
// kbros
// authentication
Security.insertProviderAt(new BouncyCastleProvider(), 1);
session.setPassword(PASSWORD);
session.connect();
Channel channel = session.openChannel("shell");
objApp.expectExec(channel);
session.disconnect();
System.out.println("Script completed");
} catch (Exception e) {
System.out.println("SSH connection failed");
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw, true);
e.printStackTrace(pw);
System.out.println(sw.getBuffer().toString());
System.exit(0);
}
}
public void expectExec(Channel channel) {
App objApp = new App();
try {
ExpectJ ex = new ExpectJ(30);
Spawn spawn = ex.spawn(channel);
String strDestinUser = "destin_user";
String strDestinPass = "destin_pass";
String strDestinHost = "127.45.23.12";
spawn.send("cd /var/www/html/poc/" + "\n");
spawn.send("ssh " + strDestinUser + "@" + strDestinHost + "" + "\n");
spawn.expect("password:");
spawn.send(strDestinPass + "\n");
spawn.send("sh /var/www/html/poc/expect.sh" + "\n");
spawn.send("\n");
spawn.send("exit\n");
spawn.send("ssh " + strDestinUser + "@" + strDestinHost + " \"echo hello world | awk '{print \$1}'\"" + "\n");
spawn.expect("password:");
spawn.send(strDestinPass + "\n");
spawn.send("\n");
spawn.send("exit\n");
String lsResults = spawn.getCurrentStandardOutContents();
objApp.writeFile(lsResults);
String[] lsRows = lsResults.split("\r\n");
for (int i = 0; i < lsRows.length; i++) {
System.out.println(i + ":" + lsRows[i]);
}
spawn.send("exit\n");
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
public void writeFile(String strContent) {
File fout = new File("out.txt");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(fout);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
try {
bw.write(strContent);
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
How can I execute the linux command through jumb box "B" to prod box "C". And how to get the output to java variable?
Your question is quite old, but I would rather open a tunnel from your machine A to C using port forwarding through B. This can be done by using Session.setPortForwardingL, then open a "direct" connection to C by SSHing to your local port, and send the commands through this connexion.