0

I've a JavaFX application where I've a list of a bunch of script files. Once the application loads, it reads it and and checks which ones are running.

To do that I use a ProcessHandle, as mentioned in various examples here on StackOverflow and other guides/tutorials on the internet.

The problem is, it never finds any of them. There for I programmatically started one, which I know for a fact that it will be running, via Process process = new ProcessBuilder("/path/to/file/my_script.sh").start(); - and it won't find this one either.

Contents of my_script.sh:

#!/bin/bash
echo "Wait for 5 seconds"
sleep 5
echo "Completed"

Java code:

// List of PIDs which correspond to the processes shown after "INFO COMMAND:"
System.out.println("ALL PROCESSES: " + ProcessHandle.allProcesses().toList());

Optional<ProcessHandle> scriptProcessHandle = ProcessHandle.allProcesses().filter(processHandle -> {
    System.out.println("INFO COMMAND: " + processHandle.info().command());
    Optional<String> processOptional = processHandle.info().command();
    return processOptional.isPresent() && processOptional.get().equals("my_script.sh");
}).findFirst();

System.out.println("Script process handle is present: " + scriptProcessHandle.isPresent());

if (scriptProcessHandle.isPresent()) {  // Always false
    // Do stuff
}

Thanks to the good old fashioned System.out.println(), I noticed that I get this in my output console every time:

ALL PROCESSES: [1, 2, 28, 85, 128, 6944, 21174, 29029, 29071]
INFO COMMAND: Optional[/usr/bin/bwrap]
INFO COMMAND: Optional[/usr/bin/bash]
INFO COMMAND: Optional[/app/idea-IC/jbr/bin/java]
INFO COMMAND: Optional[/app/idea-IC/bin/fsnotifier]
INFO COMMAND: Optional[/home/username/.jdks/openjdk-17.0.2/bin/java]
INFO COMMAND: Optional[/usr/bin/bash]
INFO COMMAND: Optional[/home/username/.jdks/openjdk-17.0.2/bin/java]
INFO COMMAND: Optional[/home/username/.jdks/openjdk-17.0.2/bin/java]
INFO COMMAND: Optional[/usr/bin/bash]
Script process handle is present: false

The first line in the Javadoc of ProcessHandle.allProcess() reads:

Returns a snapshot of all processes visible to the current process.

So how come I can't see the rest of the operating system's processes?

I'm looking for a non-os-dependent solution, if possible. Why? For better portability and hopefully less maintenance in the future.

Notes:

  • A popular solution for GNU/Linux seems to be to check the proc entries, but I don't know if that would work for at least the majority of the most popular distributions - if it doesn't, adding support for them in a different way, would create more testing and maintenance workload.
  • I'm aware of ps, windir, tasklist.exe possible solutions (worst comes to worst).
  • I found the JavaSysMon library but it seems dead and unfortunately:
  • CPU speed on Linux only reports correct values for Intel CPUs

Edit 1:

I'm on Pop_OS! and installed IntelliJ via the PopShop as flatpak.

In order to start it as root as suggested by mr mcwolf, I went to /home/username/.local/share/flatpak/app/com.jetbrains.IntelliJ-IDEA-Community/x86_64/stable/active/export/bin and found com.jetbrains.IntelliJ-IDEA-Community file.

When I run sudo ./com.jetbrains.IntelliJ-IDEA-Community or sudo /usr/bin/flatpak run --branch=stable --arch=x86_64 com.jetbrains.IntelliJ-IDEA-Community in my terminal, I get error: app/com.jetbrains.IntelliJ-IDEA-Community/x86_64/stable not installed

So I opened the file and ran its contents:

exec /usr/bin/flatpak run --branch=stable --arch=x86_64 com.jetbrains.IntelliJ-IDEA-Community "$@"

This opens IntelliJ, but not as root, so instead I ran:

exec sudo /usr/bin/flatpak run --branch=stable --arch=x86_64 com.jetbrains.IntelliJ-IDEA-Community "$@"

Which prompts for a password and when I write it in, the terminal crashes.

Edit 1.1:

(╯°□°)╯︵ ┻━┻ "flatpak run" is not intended to be ran with sudo

Edit 2:

As mr mcwolf said, I downloaded the IntelliJ from the official website, extracted it and ran the idea.sh as root.

Now a lot more processes are shown. 1/3 of them show up as INFO COMMAND: Optional.empty.

scriptProcessHandle.isPresent() is still unfortunately returning false. I searched through them and my_script.sh is nowhere to be found. I also tried processOptional.isPresent() && processOptional.get().equals("/absolute/path/to/my_script.sh") but I still get false on isPresent() and it's not in the list of shown processes.

Though the last sentence might be a different problem. I'll do more digging.

Edit 3:

Combining .commandLine() and .contains() (instead of .equals()) solves the problem mentioned in "Edit 2".

Optional<ProcessHandle> scriptProcessHandle = ProcessHandle.allProcesses().filter(processHandle -> {
    System.out.println("INFO COMMAND LINE: " + processHandle.info().commandLine());
    Optional<String> processOptional = processHandle.info().commandLine();
    return processOptional.isPresent() && processOptional.get().contains("/absolute/path/to/my_script.sh");
}).findFirst();

System.out.println("Script process handle is present: " + scriptProcessHandle.isPresent());

if (scriptProcessHandle.isPresent()) {  // Returns true
    // Do stuff
}

.commandLine() also shows script arguments, so that must be kept in mind.

Doombringer
  • 596
  • 4
  • 19
  • > So how come I can't see the rest of the operating system's processes? Try to run app with root privileges – mr mcwolf Jun 11 '22 at 13:00
  • @mrmcwolf I tried, but apparently it might not be an option. See **Edit 1** for more information. x) – Doombringer Jun 11 '22 at 23:12
  • in the editorial it seems that your problem is `flatpak` and not `intellij`, `java` or the application you are writing. download intellij from the official website of `jetbains` (`tar.gz`). log in as root (`sudo su`), unzip the ide and run `idea.sh` from the `bin` directory. – mr mcwolf Jun 12 '22 at 05:32
  • Thank you for the idea (pun intended?). I did this and now more processes show up, though, unfortunately mine is still nowhere to be found. – Doombringer Jun 12 '22 at 09:09
  • here comes the question of what you expect to see. in the example above you test with my_script.sh and assume that you will see it as a process name. But this is not so. the script starts with `#!/bin/bash` which means that my_script.sh will be passed as a `bash` argument. in other words, the process will be named bash. to get the literal my_script.sh you need to check the arguments that started the corresponding process. – mr mcwolf Jun 12 '22 at 09:18
  • @mrmcwolf Just as you wrote this I was doing some testing. I tried `processHandle.info().commandLine()` and it showed up as `Optional[/usr/bin/bash /home/username/path/to/file/my_script.sh]`. There for, I went with `Optional processOptional = processHandle.info().commandLine();` and `processOptional.isPresent() && processOptional.get().equals("/usr/bin/bash " + "/absolute/path/to/my_script.sh");` and now `.isPresent()` returns `true`. Perhaps I can use `.contains("/absolute/path/to/my_script.sh")` instead of `.equals()` and it shouldn't matter if the script is `bash`. – Doombringer Jun 12 '22 at 09:30
  • I tried the `.contains()` and it works as well. I'll edit and post the full code. – Doombringer Jun 12 '22 at 09:32
  • @mrmcwolf Since the major issue was not seeing all the processes, if you post your suggestion to download IntelliJ, I'll mark it as the answer. ^_^ – Doombringer Jun 12 '22 at 09:40

0 Answers0