I have a very basic Java program that is using Jsch library to automate execution of some shell scripts located in my Unix box.
In order to automate execution of these shell scripts following steps need to be followed:
- Login into Unix box with user
john
- Switch to another user
simba
- Provide credentials of this new user using
OutputStream
bypassing the input prompt atcli
and flush it usingos.flush()
- Check that the user switch happened using
whoami
command
I wrote following program to achieve this functionality but as you can see in the console output the user switch did NOT happen and the second whoami
command gives me the same username (ie: john
)
Another question that comes to my mind is what should I do for commands that do not have any output from cli
such as su -
, logout
, bash
etc. It doesn't make sense to wait for the output in that infinite while(true)
loop when nothing is going to be returned.
Please guide.
Current Console Output
Connecting SSH to my-unix-box.net - Please wait for few seconds...
Connected!
Executing command: whoami
john
Executing command: su - simba
Setting suPasswd now....
Executing command: whoami
john //WRONG: SHOULD BE "simba"
Disconnected channel and session
Process finished with exit code 0
SSHConn.java
public class SSHConn {
static Session session;
static String[] commands = {"whoami", "su - simba", "whoami"};
public static void main(String[] args) throws Exception {
open();
runCmd(commands);
close();
}
public static void runCmd(String[] commands) throws JSchException, IOException {
for (String cmd : commands) {
System.out.println("Executing command: " + cmd);
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(cmd);
InputStream in = channel.getInputStream();
OutputStream out = channel.getOutputStream();
channel.connect();
//passing creds only when you switch user
if (cmd.startsWith("su -")) {
System.out.println("Setting suPasswd now....");
out.write((Constants.suPasswd + "\n").getBytes());
out.flush();
}
System.out.println("Flushed suPasswd to cli...");
//capture output that we receive from cli (note: some commands such as "su -" does not return anything)
if (!cmd.startsWith("su -")) {
captureCmdOutput(in, channel);
}
channel.setInputStream(null);
channel.disconnect();
}
}
public static void captureCmdOutput(InputStream in, Channel channel) throws IOException {
System.out.println("Capturing cmdOutput now...");
byte[] tmp = new byte[1024];
while (true) {
System.out.println("in the while loop...");
while (in.available() > 0) {
System.out.println("into the available loop...");
int i = in.read(tmp, 0, 1024);
if (i < 0) {
break;
}
System.out.print(new String(tmp, 0, i));
}
if (channel.isClosed()) {
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee) {
System.out.println(ee.getMessage());
}
}
System.out.println("Command output captured...");
}
public static void open() throws JSchException {
JSch jSch = new JSch();
session = jSch.getSession(Constants.userId, Constants.host, 22);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(Constants.userPasswd);
System.out.println("Connecting SSH to " + Constants.host + " - Please wait for few seconds... ");
session.connect();
System.out.println("Connected!\n");
}
public static void close() {
session.disconnect();
System.out.println("\nDisconnected channel and session");
}
}
pom.xml
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.51</version>
</dependency>
su Command Usage:
su [options] [-] [USER [arg]...]
Change the effective user id and group id to that of USER.
A mere - implies -l. If USER not given, assume root.
Options:
-m, -p, --preserve-environment do not reset environment variables
-g, --group <group> specify the primary group
-G, --supp-group <group> specify a supplemental group
-, -l, --login make the shell a login shell
-c, --command <command> pass a single command to the shell with -c
--session-command <command> pass a single command to the shell with -c
and do not create a new session
-f, --fast pass -f to the shell (for csh or tcsh)
-s, --shell <shell> run shell if /etc/shells allows it
-h, --help display this help and exit
-V, --version output version information and exit
For more details see su(1).