I am writing several java programs and will need to kill off/clean up in a seperate JVM after I am done with whatever I wanted to do. For this, I will need to get the PID of the java process which I am creating.
jps -l works both on Windows and Unix. You can invoke this command from your java program using Runtime.getRuntime().exec. Sample output of jps -l is as follows
9412 foo.bar.ClassName
9300 sun.tools.jps.Jps
You might need to parse this and then check for the fully qualified name and then get the pid from the corresponding line.
private static void executeJps() throws IOException {
Process p = Runtime.getRuntime().exec("jps -l");
String line = null;
BufferedReader in = new BufferedReader(new InputStreamReader(
p.getInputStream(), "UTF-8"));
while ((line = in.readLine()) != null) {
String [] javaProcess = line.split(" ");
if (javaProcess.length > 1 && javaProcess[1].endsWith("ClassName")) {
System.out.println("pid => " + javaProcess[0]);
System.out.println("Fully Qualified Class Name => " +
javaProcess[1]);
}
}
}
you can try execute command
pidof <program name>
for you to find the pid of your program.
It is in Linux env.
Note that Java 9 is going to expose some system-agnostic methods such as:
System.out.println("Your pid is " + Process.getCurrentPid());
Related
I want to read output from ADB logcat (https://developer.android.com/studio/command-line/adb). I have such code (test):
try {
Process p = Runtime.getRuntime().exec("sh -c adb logcat");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
while(true) {
String s = bufferedReader.readLine();
if(s == null) {
continue;
}
System.out.println("From process: " + s);
}
} catch (IOException e) {
e.printStackTrace();
}
But this prints nothing. If I execute this:
Process p = Runtime.getRuntime().exec("sh -c ls");
It works.
Okay, I too fast asked the question on SO.
I read error stream instead of inputstream and I find out that cannot find program ADB. Need to provide full path:
ProcessBuilder processBuilder = new ProcessBuilder("/home/UserName/Soft/Android/Sdk/platform-tools/adb", "logcat");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
But on another computer path is different. Also you can on every computer make symbolic link and in code use as path simply "adb":
sudo ln -s /home/UserName/Soft/Android/Sdk/platform-tools/adb /bin/adb
ProcessBuilder processBuilder = new ProcessBuilder("adb", "logcat");
This is not the best solution, partially resolves problem. Would be great without making symbolic link, using simply "adb" in instantiating ProcessBuilder object. Because in every disk location on my computer I can use ADB in terminal, it is visible but in this code no. In Windows I know that this is in System Environments > PATH. In linux I wrote command "printenv" but I don't see anything with android & adb.
I need to start a server using bash, so I had created an UNIX shell , but I am not able to execute it with Java from Eclipse.
I tried the following code which doesn't work :
Process proc = Runtime.getRuntime().exec(./startServer);
Here is content of the startServer file :
#!/bin/bash
cd /Users/sujitsoni/Documents/bet/client
npm start
You can try the following two options.
Option 1
Process proc = Runtime.getRuntime().exec("/bin/bash", "-c", "<Abosulte Path>/startServer");
Option 2
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", "<Absolute Path>/startServer");
pb.directory(new File("<Absolute Path>"));
Process proc = pb.start();
A couple Of things can go wrong:
The path to the file you have given might be wrong for eclipse it can take relative path but from the command line, it will take the absolute path.
error=13, Permission denied - If the script file doesn't have required permissions. In your scenario, that might not the case as you are not getting any error.
At last, you are executing the script by java program so the output of your script will not be printed out. In your scenario, this might be the case. You need to capture the output of script from BufferedReade and print it. ( In your case server might have started but you are not seeing the logs/output of the script.
See the code sample below for printing output.
public static void main(String[] args) throws IOException, InterruptedException {
Process proc = Runtime.getRuntime().exec("./startServer");
proc.waitFor();
StringBuffer output = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
System.out.println(output);
}
This question already has answers here:
Runtime's exec() method is not redirecting the output
(2 answers)
Closed 7 years ago.
i'm trying to run shell command in linux via java. most of the commands work, but when i run the following command i get an execption, although it works in the shell:
String command = "cat b.jpg f1.zip > pic2.jpg";
String s = null;
try {
Process p = Runtime.getRuntime().exec(command);
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
System.exit(0);
}
catch (IOException e) {
System.out.println("exception happened - here's what I know: ");
e.printStackTrace();
System.exit(-1);
}
i am getting the error in the console:
cat: >: No such file or directory
cat: pic2.jpg: No such file or directory
The problem is the redirection.
cat: >: No such file or directory
The way to interpret this error message:
the program cat is trying to tell you about a problem
the problem is that there is no file named >
Indeed, > is not a file. It's not intended as a file, at all. It's a shell operator to redirect output.
You need to use ProcessBuilder to redirect:
ProcessBuilder builder = new ProcessBuilder("cat", "b.jpg", "f1.zip");
builder.redirectOutput(new File("pic2.jpg"));
Process p = builder.start();
When you run a command it doesn't start a shell like bash unless you do this explicitly. This means you are running cat with four arguments b.jpg f1.zip > pic2.jpg The last two files names don't exist so you get an error.
What you are likely to have intended was the following.
String command = "sh -c 'cat b.jpg f1.zip > pic2.jpg'";
This will run sh which in sees > as a special character which redirects the output.
Because you need to start a shell (e.g. /bin/bash) which will execute your shell command, replace:
String command = "cat b.jpg f1.zip > pic2.jpg";
with
String command = "bash -c 'cat b.jpg f1.zip > pic2.jpg'";
I am writing several java programs and will need to kill off/clean up in a seperate JVM after I am done with whatever I wanted to do. For this, I will need to get the PID of the java process which I am creating.
jps -l works both on Windows and Unix. You can invoke this command from your java program using Runtime.getRuntime().exec. Sample output of jps -l is as follows
9412 foo.bar.ClassName
9300 sun.tools.jps.Jps
You might need to parse this and then check for the fully qualified name and then get the pid from the corresponding line.
private static void executeJps() throws IOException {
Process p = Runtime.getRuntime().exec("jps -l");
String line = null;
BufferedReader in = new BufferedReader(new InputStreamReader(
p.getInputStream(), "UTF-8"));
while ((line = in.readLine()) != null) {
String [] javaProcess = line.split(" ");
if (javaProcess.length > 1 && javaProcess[1].endsWith("ClassName")) {
System.out.println("pid => " + javaProcess[0]);
System.out.println("Fully Qualified Class Name => " +
javaProcess[1]);
}
}
}
you can try execute command
pidof <program name>
for you to find the pid of your program.
It is in Linux env.
Note that Java 9 is going to expose some system-agnostic methods such as:
System.out.println("Your pid is " + Process.getCurrentPid());
I'm using this code to make my Java program open a (visible) CMD window:
try {
String line;
Process p = Runtime.getRuntime().exec("cmd /C start \"Render\" \"" + myPath + "\\punchRender.cmd\"");
BufferedReader input =
new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
jLabel7.setText(line);
}
input.close();
} catch (Exception err) {
err.printStackTrace();
}
and I've been trying to do the same thing with the OSX terminal, this is where I'm at right now:
try {
String line;
Process p = Runtime.getRuntime().exec("sh " + myPath + "/punchRender.sh");
BufferedReader input =
new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
jLabel7.setText(line);
}
input.close();
} catch (Exception err) {
err.printStackTrace();
}
So far, no luck :( Any suggestions? The .sh file isn't even running...
I would just make sure your shell script has the execute bits on and just pass in the shell script file name.
Process p = Runtime.getRuntime().exec(myPath + "/punchRender.sh")
Edit:
I don't know Java specifically if there is anyway to set file permissions for Unix/Linux with it to set the eXecute bit or how to escape quotes. But It would be something like this:
Process chmod = Runtime.getRuntime().exec("chmod u+x \"" + myPath + "/punchRenderer.sh\"")
This should work. Not only running the script, but opening a terminal also:
Process p = Runtime.getRuntime().exec("open -a /Applications/Utilities/Terminal.app \"" + myPath + " /punchRender.sh\"");
If you want a new visible Terminal window, you can't run the shell directly. You need to start Terminal and then run a .command file, not a shell script. I'm not sure how hard it would be to connect the stdout of that command to your Java process. You might have to figure out some other way of getting the output into the terminal.
By the way, I tried your code in a class on my own Mac at home, and it ran a .sh file just fine. I was running the java class from the command line. Maybe sh just isn't in your PATH.
I assume you've checked that the .sh file is executable, haven't you?
Can I suggest you capture the standard error as well as the standard output, and dump that. That should give you some idea as to what's going on (it's good practise generally).
You may need to gather standard output and standard error in different threads to avoid blocking issues. See here for a StreamGobbler