I'm using Java Process as below :
Runtime rt = Runtime.getRuntime();
try {
Process pr = rt.exec(cmd);
response = IOUtils.toString(pr.getInputStream(), "UTF-8");
response = response.substring(2, response.length()-4);
logger.debug("response :" + response);
} catch (IOException e) {
logger.error(e);
e.printStackTrace();
}
I can see the loggers in my local machine(Mac OSX). But when I run the same program in a Redhat Linux machine, I'm having problem seeing the logs. I don't have any clue whats happening after pr.getInputStream(). Having a logger before that statement is working fine. I want to see the response of the exec(cmd). How can I achieve this. I suspect something is wrong when I'm trying to read the InputStream.
Try reading input stream and error stream in two threads other than the one that launched the process.
I have seen processes gets stuck writing to error or output streams if no one is reading what they are writing.
Related
I have a reader module written in Java that checks whether a reader is connected to the system and if yes it scans any tags present in its vicinity.
If the reader is not connected, the program continuously throws following exception stack trace:
Exception de.feig.FedmException:
Error -111 - Error in Module FEDM: No port handle set
(in Function: FedmIscReader_SendProtocol(0xB0), Line: 3362)
native Library Version: 04.07.0
Here is the code that is generating the above exception:
try {
fedm = new FedmIscReader();
}
catch (de.feig.FedmException e) {
e.printStackTrace();
return;
}
catch(java.lang.Exception e) {
e.printStackTrace();
return;
}
The problem here is that I'm writing the output of this program into a nohup file on Ubuntu system and this file size grows to a large extent since the above exception is written continuously to this file.
I want this exception to be written to nohup only once and continue detecting for any reader connections. How do I achieve this?
Any suggestion or solution for this is greatly appreciated.
Thanks
I have a utility where Jmeter sends a request and the utility sends back response to Jmeter. When load increases, the Utility shuts down with an "EXCEPTION_ACCESS_VIOLATION".
Since it is an error, I am not able to handle it in a catch block. I made a second utility to restart the first utility when the error occurs. Below is the code of the second, restart, utility. In this second utility's code, at the second while, my program sometimes hangs. How do I detect this and restart the process?
public static void main(String[] args)
{
String line = null;
String currPID = null;
try
{
while(true)
{
Process process = Runtime.getRuntime().exec("java -XX:+HeapDumpOnOutOfMemoryError -Xms250M -Xmx500M -XX:ErrorFile=NUL ws ");
BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
while ((line = input.readLine()) != null) //Program stucks at this Line
{
if(line.trim().length() != 0)
{
if(line.startsWith("PID"))
{
currPID = line.substring(line.indexOf("#")+1);
}
}
}
System.out.println("Ended");
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
I analysed process through jvisualvm where i found two java process is in running mode when i start second(restart) utility. I can see first utility is restarting regularly because its PID is changing frequently in jvisualvm and same happening in task manager. Everything is going on very well manner.
After sometime i found only one process is in Jvisualvm ie second(restart) utility.
It means first utility JVM is crashed just guessing not sure. Something unusual is happening here. Because if JVM is crashed so It should be restarted.
So i opened task manager and found first utility PID exists there but it is not changing as happening in starting. If i kill the process(first utility) explicitly from task manager.
Seconds utility again restarts first utility same thing happens again, After some time first utility disappeared from jvisualvm, exists in taskmanager and delete process from taskmanager. What needs to do?
Try using .ready() function.
try {
if (stdError.ready())
{
while((line= stdError.readLine()) != null){
logger.error(line);
}
}
}
Do the same for the stdout.
It worked like a charm for me.
Your problem with hanging appears to be at the call to readLine.
readLine is for reading lines. The method will not return until the call is sure the end of line has been reached. It expects either a newline character or the complete cease of communications.
Is your first utility not sending a new line char?
Does your first utility fail to close the stream?
Your while call will hang indefinitely if the answer to both questions is yes.
You might be better off consuming with a custom implementation of the Scanner class.
Try to use getErrorStream() it'll catches the error message, if you use getInputStream() it'll reads only the success message or feedback messages.
for ex: if you execute the following command & read the process message using getInputStream(),
Process process = Runtime.getRuntime().exec("net use u: \\sharedIP\sharedFolder");
BufferedReader input = new BufferedReader(new inputStreamReader(process.getInputStream()));
you can only get feedback messages like "network drive connected successfully" but not the error messages.
if you use getErrorStream() to read the process message it'll read the error messages like "the network drive was not found". when the process executed it'll give a message to either getInputStream() or getErrorStream(). so use both method to read the message from the process, if i'm correct this'll work. I'm just trying to give you an idea but i'm not sure.
I use ProcessBuilder to start a new process (child) form a java application (host). Something like this:
ProcessBuilder processBuilder = createProcess(commandLine);
processBuilder.directory(new File(baseDir));
processBuilder.redirectErrorStream(true);
Process process = null;
try {
process = processBuilder.start();
} catch (Exception e) {
e.printStackTrace();
}
I do see in the system monitor that the child process has been started but it's not functioning unless I stop the host application. More specifically the child proecess is a server and after starting it with a ProcessBuilder it's not responding to the requests if the host application still is running. Moreover, the port that server is using still is available. The server starts working immediately if I stop the host application. Is there anything that I missed or that's how ProcessBuilder suppose to work?
Many thanks in advance.
Under most circumstances, until a process's standard out buffer is emptied, it will not terminate. It might be that your process has filled this buffer and has stopped (for some reason)
Try consuming the processes standard out (via Process#getInputStream) and see if that makes a difference.
It could also be that the process is waiting for input for the user.
Take a look at I'm not getting any output and probably the machine hangs with the code for an example
#MadProgrammer is correct. I was able to fix the issue and I want to answer to my question with a code example. That could be usefull for others too.
You need to consume the standard out of the child process after starting it. Something like this:
process = processBuilder.start();
InputStream is = process.getInputStream();
INputStreamReadr isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while (!stopProcess) {
if (br.ready()) {
line = br.readLine();
System.out.println(line);
}
}
Im using sshj and im trying to tail a file, but my problem is that the remote process is never killed.
In the following example code you can see that i try to tail /var/log/syslog, and then i send a kill signal to the process. However after the application has stopped and i list out all the processes on the server, i can still see an active tail process.
Why will not this code kill the process? and what can i do to remedy that?
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
try {
ssh.connect("localhost");
ssh.authPassword("xxx", "xxx");
final Session session = ssh.startSession();
try {
final Command cmd = session.exec("tail -f /var/log/syslog");
cmd.signal(Signal.KILL);
System.out.println("\n** exit status: " + cmd.getExitStatus());
} catch (IOException e) {
e.printStackTrace();
}finally{
session.close();
}
} finally{
ssh.disconnect();
}
EDIT
also tried sending all available signals.
for(Signal s : Signal.values()){
cmd.signal(s);
}
Allocating a PTY and sending a Ctrl+C character code did the trick for me:
final Session session = ssh.startSession();
session.allocateDefaultPTY();
try {
final Command cmd = session.exec("tail -f /var/log/syslog");
// Send Ctrl+C (character code is 0x03):
cmd.getOutputStream().write(3);
cmd.getOutputStream().flush();
// Wait some time for the process to exit:
cmd.join(1, TimeUnit.SECONDS);
// If no exception has been raised yet, then the process has exited
// (but the exit status can still be null if the process has been killed).
System.out.println("\n** exit status: " + cmd.getExitStatus());
} catch (IOException e) {
e.printStackTrace();
}finally{
session.close();
}
Of course, being able to send signals would be better, but if even the OpenSSH server does not support it, there's no hope there :/
openssh doesn't support it https://bugzilla.mindrot.org/show_bug.cgi?id=1424
Just use cmd.close(), that should term the process as well
This is most likely a problem with the ssh server implementation, as i have tried using two different ssh clients and getting the same result. My solution ended up being a client-side tail logic, instead of "tail -f" to prevent free roaming processes.
Had a similar issue recently. In my specific case it was the OpenSSH issue mentioned by #shikhar.
My solution was to run start another session (sharing the connection) and run a kill command pgrep mycommand | xargs kill.
i have a jar file: myServerSide.jar,
this jar takes request from client apps, processes them, each one ina thread and renders a response
i've put my jar on linux, but i want it to be ALWAYS running
if i do java -jar myServerSide.jar & for no reason it stops after a while
i also tried deamon -- java -jar myServerSide.jar & it also stops
do you know the reason why?
what should i do,so that it stays always running, and never exit.(is it necessary to make it a service)
thanks for your help
(i'm hosting my jar on linode (a VPS) if it is related)
this is the code for my server
try
{
FTLogger.getInstance().logMessage(Level.FINE, "S: Connecting...");
ServerSocket serverSocket = new ServerSocket(SERVERPORT);
while (true)
{
Socket client = serverSocket.accept();
Thread serverThread = new Thread(new ServerThread(client));
serverThread.start();
}
}
catch (Exception e)
{
FTLogger.getInstance().logMessage(Level.SEVERE, "S: Error getting connection", e);
}
in my logs, i don't see any error, and when working the jar works as it should.
(if you're sure that it's smthg from my code, should i open another question, and discard this?)
if i do java -jar myServerSide.jar & for no reason it stops after a while
The reason it stops could be (probably is) in your code.
Debugging it should tell you why it stops.
Assuming you don't have access to screen you can try nohup java -jar myServerSide.jar > log.out &
If an java.lang.Error occurs it wouldn't be catched by
catch (Exception e) {
...
}
only
catch( Throwable t ) {
...
}
would do it.
I think that you should ensure this programatically by something like infinite loop waiting for requests from client and delegating them to separate threads for processing:
// this is very high-level and obviously a exit point from this loop should be provided
while (true) {
Request r = waitForRequest();
processRequestInNewThread(r);
}
Or is there something more you need that I'm missing? Maybe a sample code from your implementation of request handling will help.
You should give us some code. The first thing that pops into my mind is that you need to make sure your method that accepts the connections from clients need to run in an infinite loop. For example:
while (true) {
acceptAndParseRequest();
}
If you launch a java application, and you embed your code into a loop:
while(true){
...
}
It will never stop, the only reason why it should stop it's because an exception is launched (do you consume resources inside the while) ?
In case it really stops, try to understand what is the problem in this way:
while(true){
try{
... your code ....
}catch(Throwable t){
system.out.println("This is my problem:" + t.printStackTrace);
}
}
Sure it helps