Im developing a simple console Application using java. The code is given below
` try {
File file = new File("writer.txt");
writer = new BufferedWriter(new FileWriter(file));
Process myProcess = Runtime.getRuntime().exec("jps -l");
BufferedReader stdout = new BufferedReader(new InputStreamReader(
myProcess.getInputStream()));
String line = stdout.readLine();
while (line != null) {
if (line.contains(".jar")) {
writer.write(line);
System.out.println(line);
}
line = stdout.readLine();
}
writer.close();
}
`
The code will display the currently running the jar in my windows. The output format is displayed 2356 Timeout.jar I want to display it only Timeout.jar How to remove that integer values. Thanks in advance.
Assuming you have "2356 Timeout.jar" in line, this will return just the jar name:
line.substring(line.indexOf(" ") + 1);
I think there must be an easier way to get the running jar though. I did a quick search and you may want to look at these questions:
How to get the path of a running JAR file?
http://arstechnica.com/civis/viewtopic.php?f=20&t=261563
You could:
Apply a regular expression to line before writing it out. (Think start-of-line, then integers, ending at the first whitespace)
Use ls (or dir) as your exec process instead of jps
Just grab the directory listing directly instead of via the external process as per below:
File dir = new File("directoryName");
String[] children = dir.list();
Doing what you have via JPS is probably not a good idea if this isn't a quick one-off app or a learning exercise because of the following note from the jps man page:
NOTE- You are advised not to write scripts to parse jps output since
the format may change in future releases. If you choose to write
scripts that parse jps output, expect to modify them for future
releases of this tool.
Tokenizing the result is one way.
if you are in unix, use awk to get the second field.
If you are using a Linux based OS,
Instead of
Process myProcess = Runtime.getRuntime().exec("jps -l");
try this one
Process myProcess = Runtime.getRuntime().exec("jps -l | cut -d \" \" -f2");
Related
I am trying to expand a zip file using 7zip but I keep getting the 7zip Usage printout.
The zip exist in c:\temp
The same command succeed in batch window :
C:\TEMP>7z x "tryThis.zip"
I tried adding the workdir path to the file,And also without the working dir,
nothing help. - I can probably run this using CMD/c command but I prefer to keep the code clean
What am I doing wrong?
Thank you!
String pathTo7ZipExe = "c:\\program files\\7-zip\\7z.exe";
String fileName ="tryThis.zip";
String workingDir = "c:\\temp\\";
Process process = Runtime.getRuntime().exec(
new String[]{pathTo7ZipExe},
new String[]{" x \"" + fileName +"\""},
new File(workingDir));
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
// wait for zip to end.
int exitVal = process.waitFor();
Please have a look at the documention for Runtime.exec
What you were actually trying to do is calling 7-zip without arguments and providing the arguments as your environment. Environment is something like Windows PATH etc.
so you would probably want to do something like:
Runtime.getRuntime().exec(new String[]{pathToZipExe, "x", fileName}, null, new File(workingDir));
On the other hand I would strongly advise to have a look on ZipInputStream which is included in java - using that you can also unpack zip files.
Cheers
You're invoking the overload of exec which accepts envp array as the second argument. This envp array is not for arguments at all, so actually you don't pass any arguments: that's why you get the usage printout.
Quotes and spaces aren't themselves part of arguments: they are used for separation into argv (with minor reservations, it's also true for Windows: that's how CommandLineToArgW works, even though full original command line with quotes and spaces is always available).
So it should be something like this:
Runtime.getRuntime().exec(new String[]{pathTo7ZipExe, "x", fileName},
new String[]{}, new File(workingDir));
(too bad I don't know Java, so the code might be unidiomatic, but it should work).
I know more or less how to do this, but I think I'm getting burned by the complexity of this command due to inexperience.
I'm trying to feed some raw html into wkhtmltopdf. I can do this from the command line like this:
echo "<p>Hello</p>" | wkhtmltopdf - ~/somePdf.pdf
That works fine, but how do I do this from a Java app? Here's a couple things I've tried:
String[] cmd = { "echo", html.body(), "|", "wkhtmltopdf", "-", "/home/sam/yourPdf.pdf" };
Runtime.getRuntime().exec(cmd);
OR
Runtime.getRuntime().exec("echo " + html.body() + " | wkhtmltopdf - /home/sam/yourPdf.pdf");
Neither one of these produces a file in my home folder.
I've read that wkhtmltopdf will output to STDERR, but I'm not sure how to view that from Eclipse. I was told it should be available in my Console view, but I don't see anything there.
Any help is appreciated, thanks!
Edit
The accepted answer will work for wkhtmltopdf, but for anyone else using the Play! framework who finds this post, there is a Play! module that generates a PDF based on a scala template. It works really well, but don't forget to set media="print" in your stylesheet :)
You cannot do this directly, because you are running two commands and you create a pipe. Neither the Runtime.exec() nor the ProcessBuilder.command() methods are made for this. The easiest way to still achieve something akin to this from Java is to put all that stuff into a shell script and call that script with Runtime.exec() .
EDIT:
You can also skip the shell script and call
Runtime.getRuntime().exec( new String[] { "bash", "-c", "\"echo \"<p>Hello</p>\ | wkhtmltopdf - ~/somePdf.pdf\""} );
That save you writing the shell script, but you may have to fiddle with the quotes a little to get it right.
You can try something like this to output your error stream to your console:
try{
Runtime runTime= Runtime.getRuntime();
Process process= runTime.exec("echo " + html.body() + " | wkhtmltopdf - /home/sam/yourPdf.pdf");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = null;
while ( (line = reader.readLine()) != null){
System.err.println(line);
}
}catch(Exception exe){
exe.printStackTrace();
}
Note that this is specific to getting what is printed to your error stream. I hope this helps to get you started
I'm making an update function for my project, it's working great, until i want it to restart, basically I download the new file and replace it with the old one, and then i want to run it again, now for some reason it doesn't wna run, and i don't get any error...
Here is the complete update class:
http://dl.dropbox.com/u/38414202/Update.txt
Here is the method i'm using to run my .jar file:
String currDir = new File("(CoN).jar").getAbsolutePath();
Process runManager = Runtime.getRuntime().exec("java -jar " + currDir);
It's not clear to me, why do you need to run the jar with a call to exec() . Given that you need to run the code in the .jar file from a Java program, you could simply run the main() method as defined in the jar's manifest, and capture its output - wherever that is.
Using exec() is OK when you need to call a program from the underlying operating system, but there are easier ways to do this if both the caller and the callee are Java programs.
Now, if your jar is gonna change dynamically and you need to update your program according to a new jar, there are mechanisms for reloading its contents, for instance take a look ath this other post.
The JavaDocs for the Process class specifically point out that if you don't capture the output stream of the Process and promptly read it that the process could halt. If this is the case, then you wouldn't see the process that you started run.
I think you have to capture the stream like this :
BufferedReader stdInput = new BufferedReader(new InputStreamReader(runManager.getInputStream()),8*1024);
BufferedReader stdError = new BufferedReader(new InputStreamReader(runManager.getErrorStream()));
// read the output from the command
String s = null;
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
The exec function doesn't automatically lookup into the PATH to start a process, so you have to pass the complete path for the java binary.
You can do that by using the java.home system property, see this answer: ProcessBuilder - Start another process / JVM - HowTo?
No one here seemed to help me, so I went to ask my friend and I had it almost right. It abiously required the string to be an array.
solution:
String[] cmd = {"java", "-jar", currDir};
try {
Runtime.getRuntime().exec(cmd);
} catch (IOException e1) {
e1.printStackTrace();
}
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
I need to run a couple of other programs from my own Java program, basically I need to run these command line statements.
svn log --xml -v > svn.log
and
java -jar example.jar arg1 arg2
and I need to use the text outputs written to the console from these programs in my own program. I've tried Runtime.getRuntime().exec() with the svn, but it doesn't seem to be doing anything because it doesn't make a svn.log file. Also both programs need to be called in different places, the svn line needs to be called from inside one folder and the java line needs to be called from another.
Any ideas on how to go about this? If this is not possible in Java, is there a way to do it in C#?
Thanks
Here:
ProcessBuilder processbuilder
try
{
processbuilder.directory(file);
processbuilder.redirectErrorStream(true);
process = processbuilder.start();
String readLine;
BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream()));
// include this too:
// BufferedReader output = new BufferedReader(new InputStreamReader(process.getErrorStream()));
while((readLine = output.readLine()) != null)
{
m_Logger.info(readLine);
}
process.waitFor();
}
I've used something similar. You'll actually want to do something with the readLine. I just copied and pasted from code where I didn't care what it said.
The redirection > (like the pipe |) is a shell construct and only works when you execute stuff via /bin/sh (or equivalent). So the above isn't really going to work. You could execute
/bin/sh -c "svn log --xml -v > svn.log"
and read svn.log.
Alternatively, you can read the output from the process execution and dump that to a file (if you need to dump it to a file, or just consume it directly as you read it). If you choose this route and consume stdout/stderr separately, note that when you consume the output (stdout), you need to consume stderr as well, and concurrently, otherwise buffers will block (and your spawned process) waiting for your process to consume this. See this answer for more details.
instead of piping in your command, just let it print to standard output and error output. You can access those streams from your process object that is returned from exec.
For the svn stuff use java SVNKit API.
Seeing your two commands, why don't you do it directly from Java, without executing ? You could use SVNKit for the svn part, and include directly the jars in your classpath.
Try this
public static void main(String[] args) {
try {
// Execute a command with an argument that contains a space
System.out.println(args[0]);
String[]commands = new String[]{"svn", "info", args[0]};
Process process = Runtime.getRuntime().exec(commands);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder builder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
}
String result = builder.toString();
System.out.println(result);
}catch(Exception e){
System.out.print(e);
}
}