I need to find out how much memory a certain process (java.exe) is using from within a java webapp.
I have tried the following:
Process proc = Runtime.getRuntime().exec("tasklist /v | find \"java.exe\"");
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader errInput = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
But this returns the following:
ERROR: Invalid argument/option - '|'.
Type "TASKLIST /?" for usage.
I know this is because a pipe is a shell feature and is parsed by Java before being passed to the shell.
I have also tried:
String[] procString = {
"cmd",
"/c",
"tasklist /v | find \"java.exe\""
};
Process proc = Runtime.getRuntime().exec(procString);
But this doesn't return anything to either BufferedReader.
Is there a way to get the correct output into the webapp?
The stdInput and errInput streams must be periodically consumed before the exec () function returns. The exec () function blocks whenever the buffer is full. That is, the command through the exec () function does not proceed when there is no space to write to the buffer. To solve this problem, read the buffer after each buffer is full in another thread.
It is a mistake that is easy for a person who gets into a Java program. If you have defined a stream, it must be consumed (via the read function)
Related
I'm trying to use the WMIC command 'DESKTOP' in an application through a method which is implemented from an interface. Before using WMIC commands in cmd, it's necessary to first input 'WMIC' and press enter, as I'm sure you all know. I can do this just fine, however after the command line enters WMIC mode, I need to subsequently enter the DESKTOP command, or any other WMIC command (see list : http://ss64.com/nt/wmic.html). Here's the overridden method code I'm currently using to enter WMIC mode :
#Override
public void Desktop(){
try {
Runtime rt = Runtime.getRuntime();
String cmd = "cmd /c WMIC";
Process pr = rt.exec(cmd);
}
Perhaps I'm going about this the wrong way? Any help would be much appreciated.
You need to get the output stream of the process you started and write to it.
OutputStream os = pr.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
bw.write("DESKTOP");
bw.newLine();
bw.flush();
If you need to see the output/errors from the process you started you need to use getInputStream() and getErrorStream() methods to get the output/error streams and read from it.
Check the javadoc of Process for more details.
http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html
Pay special attention to this part -
By default, the created subprocess does not have its own terminal or
console. All its standard I/O (i.e. stdin, stdout, stderr) operations
will be redirected to the parent process, where they can be accessed
via the streams obtained using the methods getOutputStream(),
getInputStream(), and getErrorStream(). The parent process uses these
streams to feed input to and get output from the subprocess. Because
some native platforms only provide limited buffer size for standard
input and output streams, failure to promptly write the input stream
or read the output stream of the subprocess may cause the subprocess
to block, or even deadlock.
It's a fairly silly answer.
WMIC is normally used in non interactive mode.
wmic desktop get
However you are a programmer. Therefore you are supposed to program.
Here's vbs script that does it. The help is filled with sample scripts in C, VB, VBS, and JScript.
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_Desktop")
For Each objItem in colItems
msgbox objItem.Name & " " & objItem.Wallpaper
Next
I am new to this console problems. I am simply creating a application which executes few command lines. I have a commands
mysql -u root -p
which is for opening MySQL console.
Here, how can I input password?
I did:-
cd c:\\Program Files (x86)\\MySQL\\MySQL Server 5.5\\bin
&& mysql -u root -p && root && create database testingdb;
&& quit && mysql –u root –p testingdb < mysql_dump.testingdb.sql
Here, first input is root which is password and second mysql_dump.testingdb.sql is sql file located in mysql_dump package.
This is not working and a thread is opened even though cmd console window is close.
How does java work in this situation?
Running the command
ProcessBuilder provides a full API for starting commands.
ProcessBuilder processBuilder = new ProcessBuilder("mysql", "-u", "root", "-p");
processBuilder.directory(new File("myDir"));
pb.redirectErrorStream(true);
Process proc = pb.start();
Pipe into the command
You can write strings into a BufferedWriter that wraps the confusingly named "output" stream from the Process object returned by processBuilder.start()
OutputStream stdin = proc.getOutputStream();
OutputStreamWriter osr = new OutputStreamWriter(stdin);
BuffererWriter bw = new BuffererWriter(osr);
bw.write("Hello\n");
A word of warning
You need to be very careful when using Process to consume the standard output/error streams otherwise the process can lock. A robust implementation should create 2 threads to read stdout and stderr asynchronously and perhaps a 3rd to feed the process.
The parent process uses these streams (#getInputStream(),
getErrorStream()) to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer
size for standard input and output streams, failure to promptly write
the input stream or read the output stream of the subprocess may cause
the subprocess to block, and even deadlock.
This guide When Runtime.exec() won't has all the information you need.
you can use Runtime class to execute OS commands. Since i donot have mysql installed canot check the senario mentioned. checked with cmd commands.
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec("mysql -u root -p");
InputStream is = pr.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null){
System.out.println(inputLine);
}
I have a command line Java program which i unfortunately cannot modify for certain integrity reasons, I am providing a GUI for this program and i got it all covered except that i am unable to provide notifications about completion of processes to the user as the program prints data to command line using System.out.println() , I designed the UI using net beans and it resides in a separate file , so how can i do this..?
Are you using Runtime.exec to execute the program? Then you can get the output stream as well like this:
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("java yourOtherProgram.jar");
InputStream stdin = proc.getInputStream();
If you're calling some method directly, you could redirect System.out like this:
PrintStream out = ...;
PrintStream err = ...;
System.setOut(out);
System.setErr(err);
ThatOtherProgram foo = new ThatOtherProgram();
foo.main(new String[0]);
EDIT
You could then use the Scanner to scan the input and do something with it.
My problem is that, i am using Runtime.getruntime.exec() function to run my unix command on Java. But, it jumps to the end of codes while exec() command is being run. The codes are below.
Process songProcess;
ArrayList<String> xmlFilePathsForEmi = new ArrayList<String>();
int countForEmiSongUpdates = 0;
String line;
try {
songProcess = Runtime.getRuntime().exec(new String[]{"find /home/gozenem/emiornek/ -name '*.xml'"}); // It jumps here !
songProcess.waitFor();
bufferedReaderSong = new BufferedReader(new InputStreamReader(songProcess.getInputStream()));
while((line = bufferedReaderSong.readLine()) != null){
xmlFilePathsForEmi.add(line);
}
...
...
...
}
I do not know what it is related to, may be there is a character that exec function could not run. I need your precious help. Thank you.
Your String[] parameter to Runtime.exec() is incorrect. It must be split up so that it contains one element per item (the executable must be one string, then each individual argument must come in its own string).
Try something like:
songProcess = Runtime.getRuntime().exec(new String[]{"find", "/home/gozenem/emiornek/", "-name", "*.xml"});
Also calling waitFor where you are doing isn't appropriate. You need to read the output while the process is running, otherwise you risk filling up the I/O buffers that are used between the Java VM and your process. So move that waitFor to after you've processed the output.
From the Process docs:
By default, the created subprocess does not have its own terminal or console. All its standard I/O (i.e. stdin, stdout, stderr) operations will be redirected to the parent process, [...]. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, or even deadlock.
I am running the following code, and it stops at waitfor() function. What could be the reason and how can I solve it?
String line;
Process albumProcess;
try {
albumProcess = Runtime.getRuntime().exec(
"iconv -f UTF-16 -t UTF-8 /home/gozenem/"+ xmlFileName +
".xml | grep albumID");
albumProcess.waitFor();
BufferedReader in = new BufferedReader(
new InputStreamReader(albumProcess.getInputStream()));
ArrayList<String> lineList = new ArrayList<String>();
while ((line = in.readLine()) != null) {
lineList.add(line);
}
result[0] = lineList.size();
albumProcess.destroy();
} catch (Exception e) {}
The | grep ... is not consuming the output from the command as you expect because getRuntime().exec does not understand piping symbols. The process gets bogged down waiting for something to consume its output and its getting passed bogus command line arguments "|", "grep", and "albumId".
A shell will understand | but execv will not, so you need to use bash -c instead to get a shell to do the piping (see java shell for executing/coordinating processes? do the piping yourself (see Pipe between java processes on command shell not reliable working). Java 7 has a new ProcessBuilder class that makes it easy to set up pipes so you can use those if you're only running on a bleeding edge JVM.
Once you've got grep running, if there's a bunch of lines that match, it may still fill up the buffer, so you need something sitting on the buffer consuming the process's output stream. Moving
albumProcess.waitFor();
after the while loop should do it.
I think you should try to read the output from the process before waiting on it. Otherwise, if the command outputs to much then the buffer may get filled.
Have a look at this article which explains how to read from the process: http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4