How do you get a process id in java? - java

I am trying to find a way to programmaticaly open and close an application. I can launch the application easily using
Runtime.getRuntime().exec(new String[] {"open", "<path to application>"});
however, the only way I can find to close it is to use the line
Runtime.getRuntime().exec(new String[] {"kill", "<process id#>"});
and I can't find anyway to get the id # other than manually opening terminal and using top to find the #. If there is a programmatic way to get this id, or just a better way to go about opening and closing applications i would love to hear about it.
Thanks

Use a java.lang.ProcessBuilder to start the subprocess. The returned Process object has a destroy() method which will let you kill it.

This probably isn't relevant anymore to the original poster (due to the elapsed time) but just for the sake of completeness...
You get a handle to the process object as a result of the exec(...) command:
Process myProcess = Runtime.getRuntime().exec("mybin");
You can then kill at any later time with destroy():
myProcess.destroy();
Note: This might be similar to what Jim was describing but not using the ProcessBuilder.

Related

how can we simulate Ctrl+C to stop the console app from waiting for user input in java

I am trying to test a command line app that waits for the user input after every step. I am able to test the app using System Rules provided by Stefan Birkner. Currently, I provide inputs from the beginning to the end which works like a charm and I can assert the final output from system log.
However, I want to test for the negative cases before the end of the app for which I give invalid inputs in the beginning to evaluate the error message. When invalid inputs are given, the console prints an error message and keeps waiting for the user to provide a valid input. How do I send Ctrl+C using as shown below:
systemInMock.provideLines(Ctrl+C);
systemInMock.provideLines accepts only strings. Is there a way to send Ctrl+C signal?
An example of my junit test is shown below:
#Test
public void testInValidMarker() throws Exception{
systemInMock.provideLines("abc","def","1");
Main.main(new String[]{});
assertTrue(systemOutRule.getLog().contains("Invalid marker, try again"));
}
Appreciate your help!
If I'm not mistaken, when you do ctrl+c, it doesn't actually get written to console. If that's true, then in no case will your program ever be given ctrl+c, so provideLines will never be in a position where it is given ctrl+c.
For proof, open up cmd and type in a program with program arguments (in my case, I use ant). If you type ant and then ctrl+c, the cursor is moved to a new line.
There are two ways you can control termination behavior:
You can use a shutdown hook (found from this previously asked question ). Doing this will allow you to handle what happens (potentially with issues).
Or you could create your own termination argument like -q or q, which would trigger an action to end the program (maybe a System.exit(1)). This way you can mock that input.
In UNIX/Linux, when you type CTRL-C, your shell intercepts it and sends the process a SIGINT signal -- see: How does Ctrl-C terminate a child process?
Therefore the System Rules project doesn't have anything to help you -- in this situation the process doesn't receive any character input.
By default, the whole JVM shuts down when it receives SIGINT. This is obviously bad news for a running test.
The SO question Signal handling using "TERM" -- may be of use.
A side effect of Java's portability is that for some OS features, it either abstracts things away until they're unrecognisable, or doesn't expose them at all.
I suspect what you're asking for can't be achieved.
If you're allowed to change the requirements slightly, you could ask the user to close with CTRL-D -- this closes stdin with EOF.
Although it's quite the overkill, you could launch a whole new JVM running your program, using ProcessBuilder. You might imagine you'd get an API to send arbitrary signals to that process. But for portability reasons, all you can do is process.destroy(), which sends SIGTERM.
Tried this as a comment, but it didn't read right. It's not exactly an "Answer" though.
So Java is really bad at console input. It reads an entire line at once and you can't do anything about it--there is no way to trap special characters or even see any of the input before the user hits return. Also I think a ctrl-d will close your input session--(Add that test to your use case if you don't use any other suggestion here because it can put you into a state you didn't expect!)
Three suggestions:
The simplest: If you can use a GUI and aren't really looking for an ongoing input/response REPL the simplest answer is usually to use JOptionPane to throw up a quick dialog. It's a one-line solution to get some user input, but not so good for an ongoing command-driven system.
If you can't use swing (If you are running headless) then you may have little choice, but you can use the JLine library. That will give you a lot more flexibility. This is how Groovysh does it's REPL. It will let you see each character as it is typed and do things like completion where a user might type part of a file name and hit tab and you put the rest in for him.
If you don't want to use JLine but want a REPL feel there is also a more complex GUI solution--create a swing console window. A trivial solution would just be a text input box to allow typing and a text area to display results, but there are certainly libraries out there with more complete console solutions.
The point here is that using Java standard input alone is just not a good solution for anything beyond a trivial/personal script--and even then I avoid it. Perhaps not the answer you asked for, but maybe it's the one you need :)

How to write an equivalent of KeyListener with JLine?

I am working on a console application written in Java. What I have to do is handle user keyboard input. When a long process in launched with our program in a terminal, the user must have the possibility to press 'q' at anytime to stop the process (which is running on a separate thread).
I've tried several things :
Running in another different thread something that read user input and throws an InterruptedException to the process' thread
Using JLine and its ConsoleReader
Using JLine and add a TriggeredAction linked to a keyboard key
But each time, I face the same problem : the user has to press ENTER key, and I don't want that.
Thanks for help if you have any ideas, or the actual solution of my problem.
PS : Please, if you think this is impossible, don't answer. I know it's possible.
Perhaps you could use one of these libraries,
http://sourceforge.net/projects/jxgrabkey/ for linux
https://code.google.com/p/jintellitype/ for windows
Less related with your question, but I think can help you,
http://sourceforge.net/projects/javacurses/
The problem, with all of this, is that you will lost the platform independence.
To avoid having the user press enter and to be able to directly respond to a keypress, we can make use of jline3 in the following way, wherein we first change the terminal into rawmode to directly respond to keys, and then wait for the next entered character.
var terminal = TerminalBuilder.terminal()
terminal.enterRawMode()
var reader = terminal.reader()
var c = reader.read()
<dependency>
<groupId>org.jline</groupId>
<artifactId>jline</artifactId>
<version>3.12.3</version>
</dependency>

Two separate console windows for input and output?

I have two threads - one awaits for input and the other is printing the debugging info.
However only one console window, so I can't type 'exit' (or whatever to stop the process), because System.out.println constantly prints the stuff. Can I have two separate console windows for each?
P.S. I wouldn't want to use Swing just for this purpose - there must be a way.
The only way I could think of would be to have two difference processes and a link betweeen the two processes. But I don't have a clue as to how to do that. Perhaps your best bet is to use the JOptionPane class.
While you stated that you don't want to use Swing, I believe that JOptionPane would be the best option for you. Simply using JOptionPane.showInputDialog is a fast way to solve your issue. Here's a link to JOptionPane's JavaDoc.
If you really can't use Swing, there's always the option to press Ctrl + C to stop the process.
A final option would be to buffer the output and only write it after the input. After you receive input, you would flush the buffer and then deal with the input. In this manner, you would prevent the application from closing before the buffer is flushed. There are two ways to do this:
You can use a BufferedWriter with a very large size (maybe 100,000?) and store this as a static variable. Instead of calling System.out.println(), you could call MyClass.out.println()
You could override System using System.setOut(). You would create your own PrintWriter that would take any input and send it to a LinkedList (or your own LinkedList designed for chars, if you choose). I suggest you use a linked list because appending is O(1) for a linked list while appending is O(n) for an array list.
Edit:
As for hmjd's suggestion (file writing), you would do that like this:
System.setOut(new FileWriter(new File(myFileName)));
Log to a file then go into another window and tail the file (in unix/mac use "tail -f filename", in another os--install unix/cygwin!)
This keeps your log separate from your console and makes it persistent as well.
There are a lot of logging utilities out there that will help with this and will even help a bit more by telling you what file a given line is coming from.
Your question is similar to this one, so I think the answer is the same. However, maybe this question might be right for you.

capture perl output with java

Alright, I'll get into the meat of things straight away:
I want to run a perl script from a java app (via ProcessBuilder), which will then parse an html page and find out some required information. I then want to pass that information back to my java app, and display that information in a JTextArea.
My knowledge of perl is VERY limited. My original thought was to write this data to a txt file, and then read that file with my java program, which could then display it to JTextArea pretty easily. However, this seems like an ugly solution, compared to simply returning a string.
Please let me know if there is a better way to do this. perhaps a completely different method than what I'm thinking of. Thanks,
Aelfhere
I think you want something like this
You can pass strings between processes only by using some type of inter-process communication: either a pipe or shared memory or using network.
Why can you not do in Java what you want to do in Perl?
when you use a ProcessBuilder you instantiate a Process Object it's java representation of a batch execution
Tipically you can hook process streaming via Java API.
Extracted from Process JAVA API:
abstract
InputStream getErrorStream()
Gets the error stream of the subprocess
abstract
InputStream getInputStream()
Gets the input stream of the subprocess
abstract
OutputStream getOutputStream()
Gets the output stream of the subprocess
If perl script write on standard output stream then you can read that output.
Generally, If process doesn't write on standard output stream then you cannot read it.

Why Use java.io.Console?

Just a quick one here.
What are the benefits of using java.io.Console as opposed to using a BufferedReader wrapping an InputStreamReader for System.in?
Why would I use it?
Thanks for any advice!
Because it's code that is already written for you...no need to re-invent the wheel. Chances are, you're not going to get it any better than it already is.
You can use java.io.Console to present an interactive command-line to the user. You could do all that with System.in yourself, but you would have to implement things like noticing when the input was done, or readPassword, etc.
See java.io.Console is finally here!
One of the most popular feature
requests for J2SE in recent times has
been the request to improve console
support and provide a way to enter
passwords with echo disabled.
Developers know this feature 4050435
as it has been skulking in the Top 25
RFEs list for some time.
java.io.Console only works when you start a Java program from a command line without redirecting STDIN/STDOUT.
The main advantage I see with Console over System.in is that you have the readPassword() method, which won't echo the characters typed by the user (I couldn't find a way to do this with System.in).
You also have readLine() which will present a prompt and read a single line. You don't have to create your own LineNumberReader.
But, if you want your Java program to be able to read from STDIN when it's redirected from a file or pipe, you still have to use System.in.
Another trick I'm pretty sure you won't get with Console--I created my own input and output streams and replaced System.in/out with them. My implementation of the stream appended to a log file as well as echoing to the screen.
When I turned on my poor-man's "Debug Info", I could even have it tell me what program/line the sysout came from (It was slow though. It created an exception and examined the appropriate stack entry so it was off by default)
java.io.Console is used to take and read input from the user at runtime and output are displayed after processing the input from user.
For more and detailed information visit https://www.examsmyantra.com/article/58/java/java-io---console-input-and-output

Categories