Reputation: 331
My requirement is as follow:
I have to login to Unix box using my credentials and once login, I have to do sudo to different user. Once sudo is successful, I have to invoke shell in nohup. On completion of executions, close channel and session both.
I tried the first step which is connect using sudo command, but I don't know how to invoke shell script after the sudo command.
In the below code I am able to execute sudo command, but after getting sudo access how can I execute a shell in nohup with user masteruser
. So that required files created my shell has owner as masteruser
.
public class SSHUploader {
Session session = null;
public SSHUploader(){
}
public void connect(){
try {
JSch jsch = new JSch();
session = jsch.getSession("user", "xxx.xxx.xx.xx", 22);
session.setPassword("test");
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void executeCommand(String script) throws JSchException, IOException{
System.out.println("Execute sudo");
String sudo_pass = "test";
ChannelExec channel = (ChannelExec) session.openChannel("exec");
((ChannelExec) channel).setCommand( script);
InputStream in = channel.getInputStream();
OutputStream out = channel.getOutputStream();
((ChannelExec) channel).setErrStream(System.err);
channel.connect();
out.write((sudo_pass + "\n").getBytes());
out.flush();
byte[] tmp = new byte[1024];
while (true) {
while (in.available() > 0) {
int i = in.read(tmp, 0, 1024);
if (i < 0)
break;
System.out.print(new String(tmp, 0, i));
}
if (channel.isClosed()) {
System.out.println("exit-status: " + channel.getExitStatus());
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee) {
System.out.println(ee);
}
}
channel.disconnect();
System.out.println("Sudo disconnect");
}
public void disconnect(){
session.disconnect();
}
public static void main(String... args) throws JSchException, IOException {
SSHUploader up = new SSHUploader();
up.connect();
up.executeCommand("sudo -u masteruser bash");
up.disconnect();
}
}
Upvotes: 8
Views: 31324
Reputation: 1517
Another solution which I find elegant is to use connection from type shell
instead of exec
.
But you will need to wait for the correct prompt to appear after each command like shown in the following example:
public static void main(String[] args) throws Exception{
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
Session session = null;
ChannelShell channel = null;
try {
JSch jsch = new JSch();
session = jsch.getSession("username", "192.168.1.1", 22);
session.setConfig(config);
session.setPassword("password");
session.connect();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
channel = (ChannelShell) session.openChannel("shell");
channel.setOutputStream(outputStream);
PrintStream stream = new PrintStream(channel.getOutputStream());
channel.connect();
stream.println("touch delme.txt");
stream.flush();
String response = waitForPrompt(outputStream, "$");
System.out.println(response);
stream.println("sudo chown root delme.txt");
stream.flush();
response = waitForPrompt(outputStream, ":");
System.out.println(response);
stream.println("mysecretrootpassword");
stream.flush();
response = waitForPrompt(outputStream, "$");
System.out.println(response);
stream.println("ls -la delme.txt");
stream.flush();
response = waitForPrompt(outputStream, "$");
System.out.println(response);
} finally {
if (channel != null) {
channel.disconnect();
}
if (session != null) {
session.disconnect();
}
}
}
static public String waitForPrompt(ByteArrayOutputStream outputStream, String prompt) throws Exception {
int retries = NUMBER_OF_RETRIES;
for (int x = 1; x < retries; x++) {
TimeUnit.SECONDS.sleep(1);
if (outputStream.toString().indexOf(prompt) > 0) {
String responseString = outputStream.toString();
outputStream.reset();
return responseString;
}
}
throw new Exception("Prompt failed to show after specified timeout");
}
Upvotes: 0
Reputation: 106
The post may be old, but I found another easy way that allows you to retrieve the output of each command separately. Note that this code has to be executed once the session has been opened, as shown in the examples (http://www.jcraft.com/jsch/examples/Exec.java.html):
for (String command : commands) {
ChannelExec channel = (ChannelExec) session.openChannel("exec");
channel.setInputStream(null);
channel.setErrStream(System.err);
channel.setCommand(command);
channel.connect();
printOutput(channel);
channel.disconnect();
}
Where printOutput
uses channel.getInputStream()
to read the result of the command.
Upvotes: 2
Reputation: 301
For executing multiple commands in sequence, you can create a command string like below:
String script ="pbrun su - user; cd /home/scripts;./sample_script.sh”
Execute it and pass this string to your method above.
Upvotes: 20