Flow execution Java JSsh - java

I'm very nubby at Java, so please excuse me if is a dummy question.
I have the following piece of code, and the execution flow is different from my intention:
channel = session.openChannel("shell");
OutputStream ops = channel.getOutputStream();
PrintStream ps = new PrintStream(ops, true);
channel.connect();
String sudo = "sudo su - user";
String copy = "copy from a to b;
String cd = "cd a directory";
String runload = "run a scrip in unix;
String cd1 = "cd a directoryu";
String executeload = "run a scrip in unix";
ps.println(sudo);
ps.println(copy);
ps.println(cd);
ps.println(runload);
ps.println(cd1 );
if (db.runload().contains("SUCCESS")) {
ps.println(executeload);
//execute this only if runload was success
} else {
System.exit(1);
}
The point is that "if block" is executed before previous lines. runload is script which load information in a table and is a precondition for executeload. In this case executeload will throw java.lang.NullPointerException.
My question is: it Is a way to control the flow in this piece of code? Every previous line is a precondition to the next one. My intention is to execute the next line when the current is finally executed.

The println just sends ("types") the command to the server. It does not wait for the command to be completed.
There's actually no way to wait for a command to be completed. A "shell" is a just a black-box with an input and an output. There's even no way to tell, what parts of the output corresponds to which input.
In general, you should use an "exec" channel for automation. The "shell" channel is intended for implementing an interactive terminal.
The "exec" channel closes with its command, so you can clearly tell that a command has finished. You can then open a new "exec" channel for further commands.
See JSch example for "exec" channel.
See also JSch Shell channel execute commands one by one testing result before proceeding.
Things get complicated though with your use of sudo.
See Running command after sudo login.

Related

passing password using process builder not working for "net use" command

I am trying to run the "net use" command by invoking it using process builder. As I pass the password to the OutputStream using PrintWriter it fails with the following error :
System error 1219 has occurred.
Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed. Disconnect all previous connections to the server or shared resource and try again.
I have checked the username, password and the command, by running it manually. Its working fine
The code snippet :
ProcessBuilder pb = new ProcessBuilder("net","use","\\\\<SERVERNAME>\\<SharedLocation>","/USER:<username>","*");
Process p = pb.start();
OutputStream out = p.getOutputStream();
PrintWriter writer = new PrintWriter(out);
writer.println("<pwd>".toCharArray());
int exitCode = p.waitFor();
System.out.println("Exit Code :"+ exitCode);
A couple of suggestions:
Run net use * /delete /y as your first step to remove all connections before you start. You can also try removing specific connections.
Use a pure Java solution instead of net use -- see https://stackoverflow.com/a/208896/4803

SSHJ How change current user with command su <user>?

I use sshj library for communication with linux from my Java app.
And I need change user with command: su
SSHClient ssh = new SSHClient();
ssh.connect(host);
ssh.authPassword(login, password);
Session s = ssh.startSession();
Command cmd = s.exec("su my_user");
List<String> resultLines = IOUtils.readLines(cmd.getInputStream(), Charset.defaultCharset());
But, in IOUtils.readLines(cmd.getInputStream(), ... app is waits and does not go next.
Thanks for any help.
So, a couple of things for you to do to check this. Given what you're describing, the IOUtils.readLines() method is never returning due to the InputStream never reaching the end of stream.
The only way I've ever seen this happen is if the command you've run is stuck awaiting input. My bet would be that it's prompting for a password and is sat waiting for a response that will never come.
The following steps should help you debug:
1) Add the following line before the exec command to allocate a pseudo-terminal and ensure that any prompts will definitely be written to the InputStream:
s.allocateDefaultPTY();
2) Change your output handling to print the output character by character to the console, instead of waiting for the end of stream to be reached. Something like the following would do the trick:
InputStream in = cmd.getInputStream();
System.out.println("Starting SSH output.");
int cInt;
while ((cInt = in.read()) >= 0) {
char c = (char) cInt;
System.out.print(c);
}
This will allow you to see in your console exactly what the prompt is that is causing your command to never finish executing.
If there is a prompt there, the best ways I've found to respond to them are either to:
1) use an expect script to look for the prompt and respond to it.
2) If you'd prefer to keep it within your java code, use the session.startShell() method instead of session.exec() in order to allow you to open a full shell session where you can use Input and Output streams to send your commands and monitor the output for prompts then handle them by writing your response to the provided OutputStream. This is definitely the longer and more involved approach however!

ProcessBuilder not executing program correctly

I am currently trying to make a litlle handy tool, you see I am a network administrator and my boss told me that he wanted me to monitor the network and block certain sites and ip for some game servers, so for the monitoring part we are going to redirect all traffic on the network to a server where we can monitor the traffic before sending it to the gateway.
For this we are going to use arpspoof in linux and I have finished a solution for the blocking of sites and servers, and what I am going to make is a GUI that makes it easier for me to handle and control these things and when I tried running arpspoof from java using a ProcessBuilder it does not work and I get no output?
It also does not enter the while loop. I can't really think of more to write atm, but if I can think of more I will update this thread.
My code:
new Thread() {
public void run() {
try {
System.out.println("running arpspoof...");
Process prb = new ProcessBuilder("gksudo", "arpspoof", "-i", "wlan0", Gateway).start();
InputStream is = prb.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println("Output: " + line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
I have never used gksudo, but I googled it and it says it's a GUI version of sudo. I'm guessing that you just launched a GUI app which does not write anything to stdout and which does not return. If so, then the code is doing what I would expect. It is blocking until the process writes a line of text that it can read - which never occurs so it blocks indefinitely.
First test your ProcessBuilder code using a trivial command like "echo" to make sure your Java code is working as expected. Then work your way back. Try running your program as root so you don't need the sudo argument and see if that works. Then finally try to run it using sudo instead of gksudo.
I think #user is on the right track, but there are a couple of other possible explanations.
The gksudo command could be asking for a password. I'm not sure where it would ask, but there's a good chance that it won't be the "stdout" stream of the "gksudo" process.
If "gksudo" or the command that you are "gksudo"-ing fails to launch, there is a good chance that it will write an error message to its "stderr" stream. But you are not reading "stderr".
To help diagnose this, you need to try the following:
Look in the log file that for "sudo" - it is "/var/log/secure" on my box.
Use "ps -efl" (or similar) to see what processes exist while your application is blocked waiting for output. (If that is happening ...)
Look to see if "gksudo" is prompting for a password in an unexpected place.
Try temporarily tweaking the "sudoers" file to allow the "arpspoof" command to be "sudo"-ed without a password.

Jsch shell commands with x11forwarding - reuse channel and run new command

I need to run ssh command that opens GUI applications.
I was able to get Jsch to run the commands and the GUIs are showing up on the client machine. My problem is I can't seem to get beyond 20 Jsch channel. I realize that the server has a setting that controls the number of ssh connection a user can make which here seems to be 20. What I can't understand is how to reuse an existing connection but run a different command....
I tried to run the commands two different ways:
EXAMPLE Command:
String command = "cd /home/test;xterm ";
String command = "cd /home/test;nedit myfile.txt ";
"1 way") each run command creates a new Jsch channel:
private void connect (String command) {
Channel channel = session.getChannel("shell");
channel.setXForwarding(true);
StringBufferInputStream reader = new StringBufferInputStream(command + " \n");
channel.setInputStream(reader);
channel.connect();
}
[ This code creates a new channel for each new command. works but hitting 20 ssh connection limitation. ]
or
"another way") tried to reuse the channel to run a new command where channel is a global variable:
int numruns =0;
private void connect (String command, int channelId) {
String cmd = command + " \n";
if (channel == null) {
numruns = 0;
channel = session.openChannel("shell");
channel.setXForwarding(true);
channel.connect();
stdIn = channel.getOutputStream();
stdOut = channel.getInputStream();
} else {
channel.connect(channelId);
}
((OutputStream)stdIn).write(cmd.getBytes());
stdIn.flush();
numruns++;
}
[ "other way" opens the application but it seems to create new ssh connections. so i still have 20 ssh connection limitations.]
So it seems like the server is only allowing maximum of 20 ssh connections.
But why doesn't it work with the "other way"?
So when I close my GUI applications, it doesn't seems to release the ssh connections because it still thinks I have maxed out so I get JschException on channel.connect();
My problem is all the command opens GUI applications so I can't tell when that application is closed to close the channel connection.
I wrote the "other way" method thinking that it will not create a new ssh connection but I should be allowed to use the existing connection but send a new command. Obviously it doesn't work that way.
How can I accomplish using one ssh connection to run different command when connect(command) is called? Is that possible with Jsch?
Not Solved! The following works to a point. It hides the fact that any "xterm" no longer has display information once Jsch channel connection closes.
=====================================
To keep the GUI from disappearing when the channel was disconnected, needed to kick off the command with "nohup" preceding the command or "xterm -hold -e"
So...
EXAMPLE Command:
String command = "cd /home/test;xterm";
String command = "cd /home/test;nohup nedit myfile.txt"; // this will only keep the GUI opened
String command = "cd /home/test;xterm -hold -e gedit myfile.txt"; // this one keeps the xterm window that kick off the program opened
So after making changes to the command, Thread.sleep(1000) was added so give application time to come up before disconnecting the channel.
This seems to work!
private void connect (String command) {
Channel channel = session.getChannel("shell");
channel.setXForwarding(true);
StringBufferInputStream reader = new StringBufferInputStream(command + " \n");
// or use
// ByteArrayInputStream reader = new ByteArrayInputStream((command + " \n").getBytes());
channel.setInputStream(reader);
channel.setOuputStream(System.out);
channel.connect();
try {
Thread.sleep(1000); // give GUI time to come up
} catch (InterruptedException ex) {
// print message
}
channel.disconnect();
}

My Java Program hangs after calling a shell command

I have written a small program to start to Hive Server. Command to start to Hive Server is in shell file. When I call the shell file to start Hive Server it tends to start it and get Hang. Is there any problem in program?
Code:
try
{
String cmd = "/home/hadoop/sqoop-1.3.0-cdh3u1/bin/StartServer.sh"; // this is the command to execute in the Unix shell
// create a process for the shell
ProcessBuilder pb = new ProcessBuilder("bash", "-c", cmd);
pb.redirectErrorStream(true); // use this to capture messages sent to stderr
Process shell = pb.start();
InputStream shellIn = shell.getInputStream(); // this captures the output from the command
// wait for the shell to finish and get the return code
// at this point you can process the output issued by the command
// for instance, this reads the output and writes it to System.out:
int c;
while ((c = shellIn.read()) != -1)
{
System.out.write(c);
}
// close the stream
shellIn.close();
}
catch(Exception e)
{
e.printStackTrace();
e.printStackTrace(pw);
pw.flush();
System.exit(1);
}
Please let me know this. Is something I missed in the program?
Thanks.
It looks like your program is doing what you've told it to do.
The first few lines should indeed start the Hive server. The lines after that, read from the standard output of the server process, and echo each character to your Java process' console. Your Java process sits in a loop (making blocking I/O calls) for as long as the Hive server's output stream exists.
That is, your Java process will sit in a loop, echoing output, for as long as the Hive server is running.
Is this what you want it to do? If so, then it obviously won't be able to exit. If not, then there's no reason for you to read from the server's input stream at all, and your Java program can exit after it has started the server process. Alternatively, if you want to listen for output and do other things in your Java process, you'll need to use multiple threads in order to do two things at once.
As far as I can see you are starting server, i.e. application that starts and does not terminates soon. It remains running. This means that the STDOUT of this applcation (the server) is not closed (unless you are killing the server).
Method shellIn.read() is blocking. It reads the next byte from input stream and returns when the byte is read or when stream is closed.
So, in your case the stream is never closed, therefore your program got stuck: it is waiting forever for the input (and probably reading it).
To solve this problem you need separate thread: either in java or in OS. You can run your server from separate java thread or compose command line to run server in background (for example using trailing &).

Categories

Resources