0

I'm making an application and one of the requirements at the moment is to be able to search for processes of other running applications and kill them if needed.

I have tried "jps" which comes with the JDK and this is exactly what I need. The process id of the application, and the real name of the application. Using this I can kill by process id, as well as match by name what processes I actually need to terminate, without terminating the wrong processes. Unfortunately not all of the end-users of this application will have the JDK so jps is not reliable. I need another way to do this.

I have tried many "ps" commands that don't seem to work correctly. For example at the moment I am using

ps -e -o command

Which gives me...

line:  2729 ?        00:02:53 chrome
line:  2824 ?        00:00:00 cat
line:  2825 ?        00:00:00 cat
line:  2945 ?        00:00:00 chrome
line:  2946 ?        00:00:00 nacl_helper
line:  2959 ?        00:00:00 chrome
line:  2962 ?        00:00:00 gconfd-2
line:  3120 ?        00:07:39 chrome
line:  3179 ?        00:00:00 chrome
line:  3296 ?        00:00:44 chrome
line:  3500 ?        00:00:00 bash
line:  3751 ?        00:07:27 java
line:  3832 ?        00:00:00 file-roller
line:  4832 ?        00:00:23 chrome
line:  4883 ?        00:00:03 gnome-terminal-
line:  6085 ?        00:00:51 chrome
line:  6380 ?        00:00:06 chrome
line:  7865 ?        00:00:16 chrome
line:  8961 ?        00:00:06 chrome
line:  9404 ?        00:00:43 chrome
line: 10344 ?        00:00:02 chrome
line: 10761 ?        00:00:05 chrome
line: 11158 ?        00:00:00 java
line: 11193 ?        00:00:00 sh

This does not help me as it doesn't display the process names, and also it does not seem to be accurate. When I run my java applications from the terminal and then re-run the program, the running applications don't change when I should expect to see an extra process added.

From Java I am currently using

/bin/sh -c ps -e -o command

Is there any way to do this? Or some way to isolate the jps executable so I can pack it into my project and use it in a portable manor?


When running jps from the JDK, I get this output

3751 Main
14015 Jps
**11503** updater.jar

When I run ps -ef from my machine terminal, I get this output

root     10519     2  0 20:25 ?        00:00:00 [kworker/5:0]
root     11156     2  0 20:40 ?        00:00:00 [kworker/7:1]
root   **11503**  6170  0 20:49 pts/1    00:00:01 java -jar game/updater.jar /home
root   13031  2959  0 21:15 ?        00:00:13 /opt/google/chrome/chrome --type
root     13071     2  0 21:19 ?        00:00:00 [kworker/4:2]

When I run ps -ef from my Java application, I get the following and the process id 11503 is nowhere to be seen...

Process process = Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", "ps", "-ef" });

line:  7865 ?        00:00:17 chrome
line:  8961 ?        00:00:06 chrome
line:  9404 ?        00:00:43 chrome
line: 10344 ?        00:00:03 chrome
line: 13031 ?        00:00:09 chrome
line: 13098 ?        00:00:15 chrome
line: 13961 ?        00:00:00 java
line: 13996 ?        00:00:00 sh
line: 13997 ?        00:00:00 ps

The issue was the /bin/sh -c in the command. Removing this gave me the correct output although I still think jps is a better solution (the jps can be isolated but the final size is ~100mb)

kbz
  • 984
  • 2
  • 12
  • 30
  • If you can wait a few weeks, Java 9 is expected to be released soon (September 2017), and will have a [ProcessHandle.allProcesses()](http://download.java.net/java/jdk9/docs/api/java/lang/ProcessHandle.html#allProcesses--) method. – VGR Aug 20 '17 at 23:00
  • @VGR thanks I'll try this out. – kbz Aug 21 '17 at 18:16

3 Answers3

0

There are two very different things here:

  1. What/how to run the ps command. My personal take here: ps -ef - which lists all processes with "full" format. See this for more information.
  2. How to invoke and read the output from java. For that, see here for example.
GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Thanks for the quick reply. Yes my program already has the ability to execute commands and read the output so I just need to know the command. I have tried ps -ef also, it works a charm in the terminal on the machine itself, but the output from the java application is very different to what I receive in the terminal. – kbz Aug 20 '17 at 18:52
  • You have to make sure to sure to pass the arguments as array, as shown [here](https://stackoverflow.com/questions/7134486/how-to-execute-command-with-parameters) for example. – GhostCat Aug 20 '17 at 19:12
  • Yes I have just tried this as well, it's giving me the same results. – kbz Aug 20 '17 at 19:33
  • I have updated my post if you could please give it a quick read, there must be something I'm doing wrong but I have tried building the command in Java in multiple ways and it gives me the same output every time. – kbz Aug 20 '17 at 19:42
0

Since this seems to be Linux, or similar, I would have thought a nicer approach than to capture the output of "ps" would be to enumerate all the files in /proc with numerical filenames, and examine the file cmdline in each. That is, all the various /proc/NNNN/cmdline files. This doesn't require running ps, or any other external process whose output might be subtly different between systems. It provides access to all the information the operating system has -- you don't have to rely on "ps" doing exactly what you want.

Moreover, you don't have to rely on Runtime.exec() and all it's subtle nasties.

Kevin Boone
  • 4,092
  • 1
  • 11
  • 15
0

Although the answers posted to this question seemed to address an issue, ultimately it did not solve my problem.

The issue was the command I was passing

Process process = Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", "ps", "-ef" });

The /bin/sh -c should be removed and it returns the correct processes.

Process process = Runtime.getRuntime().exec(new String[] { "ps", "-ef" });

Also I dedicded to use the jcmd application shipped from the JDK as this provides exactly what I'm looking for as well as being supported across platforms.

kbz
  • 984
  • 2
  • 12
  • 30