1

Can any one please explain difference between ProcessBuilder and FileHandler, which one should be used in which situation.

For example if we want to redirect the output of a command to a text file say "logfile.txt", ProcessBuilder takes few seconds to get the output to the file.

What can this FileHandler do in situations like 100 processes has to send their output to same "logfile.txt"?

Is there a way to get output of all the hundred records to same "logfile.txt" without using process.waitFor() method in ProcessBuilder? This is my code, but if 100 records are scheduled at same time then p.waitfor() method will not help me because it takes few seconds to execute command and get output to logfile for every process and for 100 processes means it will take more time to execute same commands for all the records in DB. but my application will start for every minute. Thats the problem, process.waitFor() helps me in getting exact output but for more number of records means it takes more time. I want another method where it shouldn't wait but all outputs should append synchronously into file.

while(rs1.next())
    {
        instance_id = rs1.getString(1);
        startdate = rs1.getString(2);
        starttime = rs1.getString(3);
        endtime = rs1.getString(4);
        enddate = rs1.getString(5);
        if(presentdate.equals(startdate) || presentdate.equals(enddate))
        {
            if(presenttime.equals(starttime))
            {
                String[] s1 = new String[]{"cmd", "/c","ec2-start-instances",instance_id,">>","D:\\logfile.log"};
                ProcessBuilder builder1 = new ProcessBuilder(s1);
                Process p1 = builder1.start();
                p1.waitFor();
            }
            else if(presenttime.equals(endtime))
            {
                String[] s1 = new String[]{"cmd", "/c","ec2-stop-instances",instance_id,">>","D:\\logfile.log"};
                ProcessBuilder builder1 = new ProcessBuilder(s1);
                Process p1 = builder1.start();
                p1.waitFor();
            }
        }
    }
user3364490
  • 113
  • 2
  • 10
  • you can `flush` outputstream to get changes written to the file. If and how much buffer you have depends on the outputstream implementation you are using. Give some more details + example what you are trying to achieve. – akostadinov Jun 17 '14 at 13:21
  • http://stackoverflow.com/questions/24230003/multiple-execution-of-a-processbuilder-in-a-java-program/24230302?noredirect=1#comment37508343_24230302 Code in the link is mine where either of this concepts should be used. Sorry I can't post the code here as it will be irrelevant to the question I have asked here. So please kindly look at the code and suggest me if I could use processbuilder or filehandler or threadpool as mentioned by one of the user in the below answers.. – user3364490 Jun 19 '14 at 15:20
  • When I asked you for a code sample, that's because your question shows that you have some misconceptions about what is going on or is unclear. A few lines of code will show a lot more clearly what is the problem. – akostadinov Jun 23 '14 at 06:07
  • Sir I have given the code, can you suggest me the appropriate method to get all outputs to same logfile without time delays which we get while using process.waitFor()?? – user3364490 Jun 24 '14 at 09:52

3 Answers3

0

For ProcessBuilderaccording to documentation:

Note that this class is not synchronized. If multiple threads access a ProcessBuilder instance concurrently, and at least one of the threads modifies one of the attributes structurally, it must be synchronized externally.

Example

Process p = new ProcessBuilder("myCommand", "myArg").start();

From my understanding, ProcessBuilder is used to communicate with other software on the OS. (Which could be an outside logging script or some form of logging software)


FileHandler is a more of a standard file logging system. However, to avoid the problems from multiple calls, make your logging code static to make sure when it gets called that it finishes it's process. FileHandler flushes by default (according to documentation).

Hope that helps a little bit

Josef E.
  • 2,179
  • 4
  • 15
  • 30
  • Thanks for the reply. But as you suggested I cannot make the logging code static, My web app start every minute and checks records in DB, I mean 50 to 100 processes vary for every minute and the logging info also has to be changed according to each record that is successful in that validations. But your info regarding the difference between them is very useful, Thank you. – user3364490 Jun 18 '14 at 05:45
  • @user3364490 Would synchronized your logging method work for you? – Josef E. Jun 18 '14 at 13:36
  • Sorry I have not used any synchronised method, I have used a processbuilder to get output of a command to a file, and then used process.waitFor() in order to get the output to the file and then goes to next iteration. Here if there are like 1 lakh records scheduled at the same time, then for each process to execute command and for each of this process it has to wait. So practically cannot execute in 1 minute. – user3364490 Jun 19 '14 at 15:05
  • Synchronised method will execute one thread at a time right? So as far as I understood, if the process enters synchronised method and couldn't finish the operation due to any reason,then no other processes cannot enter their output to that file because it is in another process. So in this case how is it going to help me? If I am wrong can you explain why?? I would like to know. Thank you. – user3364490 Jun 19 '14 at 15:31
0

They are two mostly unrelated objects and areas.

Yes a Process Builder gives us a standard output and error output stream which can be saved to a file, but it could also be saved to a data base or discarded.

ava.util.logging.FileHandler on the other hand is an appendar part of the logging system. We generally use logging for our own code, though nothing wrong with logging the output of external processes we have called in there too.

But if other classes log while process is logging then will get mixed up logs.

Similarly if your running 50 processes I suggest you dont log to the same file. But log to 50 different files - using 50 threads. Each thread would check the eroror and output streams and save when you have a new line or end of that stream.

When all are done can copy to log file or to a new file as preferred.T

tgkprog
  • 4,493
  • 4
  • 41
  • 70
  • Hai thanks for the reply.But actual case is for every minute web application gets refreshed.So, every minute it has to take log about all files,As I mentioned 50 to 100 processes(each process/command executed in cmd using java program) are scheduled at that time, that particular output only should be appended into same file for every minute. So if in that minute also I cant take output to individual files and then copy all that output to one file. It will be extra work to the web application. But tnx for the info. – user3364490 Jun 18 '14 at 03:33
  • It should still be done in threads, java can start 100 threads a minute as long as their task is done within a minute. can have a control thread monitoring the worker threads to see if any getting stuck. there are many ways to solve any software issue, suggest using thread pools and seperate threads for each stream for more robustness. but if commands take few seconds only then *Might be okay to do in 1 thread. – tgkprog Jun 18 '14 at 09:06
  • Thread pool is a good idea. I know what it can do, but I don't know its implementation. I will try to implement it in my program and let you know as soon as it works thank you. – user3364490 Jun 19 '14 at 15:14
0

Posting your code actually gives much more idea what is going on. Now I see you are using the windows cmd.exe redirection capabilities instead of reading the outputs from the spawned processes with java and doing something with them. If you like any different behavior, you have to:

  1. if possible execute process without cmd.exe (to avoid buffering from it) - new String[]{"ec2-start-instances",instance_id)
  2. combine process stdout and stderr (easier to catch all output) processBuilder.redirectErrorStream(true)
  3. close process stdin (just a precaution) - process.getOutputStream().close()
  4. spawn threads to read all concurrent processes output streams
  5. have those threads write what they are reading to a file in a thread safe way

Now #4 and #5 are not trivial but there is plenty of information in the internet how to achieve. In Java 7 you have also the option to redirect to file without any code from your part - processBuilder.redirectOutput(File file), but I think it is not thread safe so your multiple processes wont play well with each other.

Here are two questions that give some examples how to achieve #4 and #5:

Community
  • 1
  • 1
akostadinov
  • 17,364
  • 6
  • 77
  • 85
  • Sir, if I remove cmd.exe where will my command[ec2-start-instances] get executed? – user3364490 Jun 26 '14 at 09:17
  • @user3364490, `cmd.exe` is a shell interpreter or some kind of it. The processes execute on the OS itself. So you need to use `cmd.exe` only if you are executing a windows command batch file. If you're executing some native binary executables, you don't need to trun them through a shell but execute them directly. – akostadinov Jun 26 '14 at 09:36
  • I am sorry, not able to get what you are saying, ec2-start-instances gets executed in cmd only. So I have used cmd in the code mentioned above. Can you explain me clearly what you want to suggest(removing cmd)? So that it might help me in my work. – user3364490 Jun 26 '14 at 10:35
  • I tried to execute my program removing the cmd.exe, but couldn't get the output. So now I am even more sure that ec2 command executions also require cmd.exe.. I have taken action log here to know how much delay is there every time my application starts 1) If no instances scheduled it has 5 seconds delay 2) If any instances scheduled at that time it may be even more than that(example lets say 2 instances scheduled at same time means may be 3 to 5 seconds each) I didn't find an alternate for this process.waitFor(). I hope I will sort out my problem soon. – user3364490 Jun 26 '14 at 18:05