ProcessBuilder not executing program correctly - java

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.

Related

Java Multi-Threaded Processes

I'm making a core server-management system for my company, and both the server manager and server itself are Java jar files. What I need to do is boot up the server from the server manager, and the server needs to be able to read console input. However, the way I currently have it coded, it ignores console input. I believe the while loop is freezing the thread, but IDK what to do about it. Any ideas?
Process process = Runtime.getRuntime().exec("sh start.sh");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while((line = reader.readLine()) != null){
System.out.println(line);
}
Technically, your while loop isn't freezing the thread - the call to reader.readLine() is. I'd recommend you listen to both your InputStream and ErrorStream, and to do both at the same time you either need to use Threads or java NIO. For a Threaded solution, I built and used DataFetcher for specifically this kind of purpose. All you need to do is create a DataFetcher around an InputStream, add a FetcherListener, and start the DataFetcher with a new Thread

Nothing being sent to server via URLConnection

So I've created a program that communicates with both a FTP and SQL server. I run my program on my Windows machine and everything is working fine. But when I run the program on my Ubuntu VM it is not working. My code is as follows:
try {
URL url = new URL(location);
System.out.println("Created url");
URLConnection urlc = url.openConnection();
System.out.println("Created URLConnection");
urlc.setDoOutput(true);
System.out.println("Set Output");
OutputStreamWriter out = new OutputStreamWriter(urlc.getOutputStream());
System.out.println("Created OutputStreamWriter");
System.out.println("Hello World.");
out.write(Var.pressed);
System.out.println("Wrote String");
out.close();
System.out.println("Closed OutputStreamWriter");
} catch (Exception ex) {
ex.printStackTrace();
}
The program creates a file on my FTP and then writes to it. The file is being created but it is empty. No errors are ever thrown my program prints the following
Created url
Created URLConnection
Set Output
And then does nothing. It doesn't throw an error, it doesn't crash, it doesn't stop. The terminal is just left open. I also tried just running the .jar but nothing happens.
It seems as though the problem is created here:
OutputStreamWriter out = new OutputStreamWriter(urlc.getOutputStream());
Why is nothing being written to the file? And what is wrong with my program if no errors are ever thrown?
It does throw an error,
From everything else, I think you meant to say it doesn't throw an error. My answer is assuming that anyway.
First there are many reasons for a program to hang or wait and not produce an error. Sometimes if you wait long enough a system threshold will be passed and it will timeout even though your program would be happy to wait forever. Other times the system isn't paying attention either. Error conditions are sort of like a courtesy.
I suggest you should try to make the connection with the Ubuntu ftp line command and compare the same with Windows. FTP protocol does some unusual things with ports. The connection opens on one port, but the data transfer connection is switched over to another port. Firewalls can be tripped up with the change of port and prevent the data transfer. This also has created clients that do "passive" versus "active" FTP.
You need to at least get the response code, or the input stream. Otherwise not even a TCP connection is formed. And otherwise you have no idea whether the server accepted your input.
Your title was wildly inaccurate. Obviously you are creating the OutputStreamWriter. Your issue is that nothing is being sent. And the SQL tag was simply irrelevant.
Without an error message it is nearly impossible to figure out why it fails. A few suggestions, though.
First of all, try adding a System.err.println("test") This will prove that the output log will not only catch System.out AKA standard output stream, but also standard error stream.
I asssume, that in after this fix, the ex.printStackTrace() will be visible.
Otherwise: You do not specify how your location String is filled. Are you sure, you have write access to that directory?
If location is /tmp/foo/bar/myFile.txt, make sure the directory /tmp/foo/bar/ exists (mkdir /tmp/foo/bar/) and that the file is accessible (touch /tmp/foo/bar/myFile.txt).
If both report no error AND the first suggestion would bring up no error, the program might really lock up and wait for something from the outside. Difficult to say what at the moment.

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!

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 &).

Issues receiving in RXTX

I've been using RXTX for about a year now, without too many problems. I just started a new program to interact with a new piece of hardware, so I reused the connect() method I've used on my other projects, but I have a weird problem I've never seen before.
The Problem
The device works fine, because when I connect with HyperTerminal, I send things and receive what I expect, and Serial Port Monitor(SPM) reflects this.
However, when I run the simple HyperTerminal-clone I wrote to diagnose the problem I'm having with my main app, bytes are sent, according to SPM, but nothing is received, and my SerialPortEventListener never fires. Even when I check for available data in the main loop, reader.ready() returns false. If I ignore this check, then I get an exception, details below.
Relevant section of connect() method
// Configure and open port
port = (SerialPort) CommPortIdentifier.getPortIdentifier(name)
.open(owner,1000)
port.setSerialPortParams(baud, databits, stopbits, parity);
port.setFlowControlMode(fc_mode);
final BufferedReader br = new BufferedReader(
new InputStreamReader(
port.getInputStream(),
"US-ASCII"));
// Add listener to print received characters to screen
port.addEventListener(new SerialPortEventListener(){
public void serialEvent(SerialPortEvent ev) {
try {
System.out.println("Received: "+br.readLine());
} catch (IOException e) { e.printStackTrace(); }
}
});
port.notifyOnDataAvailable();
Exception
java.io.IOException: Underlying input stream returned zero bytes
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:268)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.read(BufferedReader.java:157)
at <my code>
The big question (again)
I think I've eliminated all possible hardware problems, so what could be wrong with my code, or the RXTX library?
Edit: something interesting
When I open HyperTerminal after sending a bunch of commands from java that should have gotten responses, all of the responses appear immediately, as if they had been put in the buffer somewhere, but unavailable.
Edit 2: Tried something new, same results
I ran the code example found here, with the same results. No data came in, but when I switched to a new program, it came all at once.
Edit 3
The hardware is fine, and even a different computer has the same problem. I am not using any sort of USB adapter.
I've started using PortMon, too, and it's giving me some interesting results. HyperTerminal and RXTX are not using the same settings, and RXTX always polls the port, unlike HyperTerminal, but I still can't see what settings would affect this. As soon as I can isolate the configuration from the constant polling, I'll post my PortMon logs.
Edit 4
Is it possible that some sort of Windows update in the last 3 months could have caused this? It has screwed up one of my MATLAB mex-based programs once.
Edit 5
I've also noticed some things that are different between HyperTerminal, RXTX, and a separate program I found that communicates with the device (but doesn't do what I want, which is why I'm rolling my own program)
HyperTerminal - set to no flow control, but Serial Port Monitor's RTS and DTR indicators are green
Other program - not sure what settings it thinks it's using, but only SPM's RTS indicator is green
RXTX - no matter what flow control I set, only SPM's CTS and DTR indicators are on.
From Serial Port Monitor's help files (paraphrased):
the indicators display the state of the serial control lines
RTS - Request To Send
CTS - Clear To Send
DTR - Data Terminal Ready
OK, sorry it's taken me so long to come back to this question. Here's how I got things working.
Note: This method will NOT work for everyone, please read below before copy/pasting into your own code
public void connect(CommPortIdentifier portId) throws Failure {
if (portId == null)
throw new Failure("No port set");
try { port = (SerialPort) portId.open(getClass().getName(), 10000); }
catch (PortInUseException e) {
throw new Failure("Port in use by " + e.currentOwner,e); }
try {
port.setSerialPortParams(9600, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
port.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN
| SerialPort.FLOWCONTROL_RTSCTS_OUT);
} catch (UnsupportedCommOperationException e) { throw new Failure(e); }
port.setRTS(true);
// More setup
}
So, in my case, the problem was that my particular device requires RTS flow control. Other devices may require different things (CTS, XON/XOFF), so check that device's manual. By default, RXTX disables all flow control mechanisms (unlike Hypertrm or other programs). Enabling each one is a two-step process.
Once you have a SerialPort object, call the setFlowControlMode() method, and bitwise-OR ('|') the necessary SerialPort.FLOWCONTROL_ constants
Set the appropriate flow control to true or false (like I did with port.setRTS(true))
For the others with similar problems, if this doesn't work, I suggest
Using a serial port monitoring program like Serial Port Monitor and/or PortMon (both Windows) to see what is actually going on.
Emailing the RXTX developers at rxtx#qbang.org (they are very helpful)
There is a simpler solution to this problem. This is what I did:
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
while (keepRunning) {
try {
while ((br.ready()) && (line = br.readLine()) != null) {
....
}
If you check that the buffer "is ready" before you read it there should be no problem.
Ok, I do realize this thread is extremely old, but none of these solutions worked for me. I had the same problem and I tried everything to fix it, to no avail. Then I did some research on what causes the problem, and, when not dealing with Serial Communication, it happens at the end of a file. So, I figured I needed to add an ending to whatever is being received by the Java Application, specifically, a line return (\n). And sure enough, it fixed the problem for me! Hopefully this helps someone new, as I'm not expecting this to help anyone already on this thread...
(might be too simple, but might as well start somewhere...)
Is the port in use? Rather than:
port = (SerialPort) CommPortIdentifier.getPortIdentifier(name)
.open(owner,1000)
what about:
CommPortIdentifier portIdentifier;
try {
portIdentifier = CommPortIdentifier.getPortIdentifier(name);
} catch (NoSuchPortException nspe) {
// handle?
}
if (portIdentifier.isCurrentlyOwned()) {
// handle?
}
port = portIdentifier.open(owner, 1000);
if (!(port instanceof SerialPort)) {
// handle?
}
Are you swallowing any exceptions?
I tried RXTX a few months ago and ran into similar problems. I suggest two things:
Create a virtual comport using com0com. Enable trace logging. Compare the logs for when you use Hyperterminal versus when you run your own program. The difference will highlight what you are doing wrong.
In my humble opinion, RXTX's design is flawed and its implementation is quite buggy (take a look at its source-code, what a mess!). I've published an alternative library at http://kenai.com/projects/jperipheral with the following caveats: It's Windows-only and there are no pre-built binaries. Both of these will change in the near future. If you are interested in trying it out send me an email using http://desktopbeautifier.com/Main/contactus and I'll send you a pre-built version.
If anyone is still getting java.io.IOException: Underlying input stream returned zero bytes after you've read your characters using br.readline() for RXTX (even when you are checking first to see if br.readline() == null), just do this simple fix with a try/catch:
String line;
while (true){
try{
line = br.readLine();
}catch(IOException e){
System.out.println("No more characters received");
break;
}
//Print the line read
if (line.length() != 0)
System.out.println(line);
}
I've done some searching and it appears that this is the best/easiest way to get around this problem.
EDIT : I take that back. I tried this and still ended up having some problems. I'd recommend working with the raw InputStream directly, and implementing your own read/readLine method using InputStream.read(). That worked for me.

Categories

Resources