I have a java app from which I run console based programs on linux system, I am reading the output of those programs and then my java app is sending it to a webpage.
But once I close my java app all the processes will get "stuck" or they just simply crash. So everytime I want to make some changes to my java app and I need to restart it I also have to close all processes that were running from my app. I would like to save their PIDs when closing my app and then take control (output streams) over those processes again based on saved PIDs of the processes.
Is there any way to do it?
I am running my programs like this:
ProcessBuilder processBuilder = new ProcessBuilder(new String[] { "su", "-
s", "/bin/sh", "myuser", "-c", "java -jar myjar.jar" });,
Process p = processBuilder.start();
Edit:
My problem is not finding the process PID my problem is that my subprocesses lanched from my java app are crashing after my java app is closed/terminated and I need them to continue running even while my app is restarting/stopped.
Your problem is due to what is called Unix job control.
Like many shells do, /bin/sh intercepts SIGHUP and SIGINT signals, and before exiting, it sends signals to some of its child processes groups, depending on its configuration and on their state (for instance, stopped background processes receive a SIGCONT).
So, when your main java app is closed, the /bin/sh shell that your app had forked is terminated, and just before exiting, it sends a SIGHUP signal to its subprocesses corresponding to the command java -jar myjar.jar.
So, the answer to your question is: just use the huponexit /bin/sh shell option to avoid killing subprocesses. They will be detached from the controlling terminal, if any, but they will not be killed.
So, replace this java -jar myjar.jar by shopt -u huponexit; java -jar myjar.jar:
ProcessBuilder processBuilder =
new ProcessBuilder(new String[] {
"su", "-s", "/bin/sh", "myuser", "-c",
"shopt -u huponexit; java -jar myjar.jar"
});
Process p = processBuilder.start();
Try to run your command like this:
Runtime.getRuntime().exec("gedit");
It executes the specified string command in a separate process.
Some time ago I have found some useful information here. Try this.
I would use the ps command in Linux to get the number of each process(s) running which you want to control, of course you would execute it just as you have above with your ProcessBuilder. I would then pipe; "|" (Linux Command), the output into a file you have saved somewhere in your Java project.
The Linux command to execute from your Java program would look something a long the lines of
ps -A | grep "your_program_name" > /path/to/your/project/my_process_list_file.txt
Where the > stores the output of the command executed to your file.
I would then read from this file and execute some other Linux commands to take control of that process in whichever way you desire.
Good Luck, and happy coding my friend!
Related
So I have a Docker network that has a Docker file with a bunch of information. I have a java program that is going to bring up the enviorment and then produce several commands to run within this enviorment. To be clear, the first command I need to run is NOT inside the Docker enviorment. I am having some challenges with the Process and Runtime classes.
First, say I wanted my java program to launch a new gnome terminal and then run a command to get into the docker network. I have this command,
Process process = Runtime.getRuntime().exec(new String[]{"gnome-terminal"});
Gnome terminal sucessfully comes up but any additional arguments I give in this array are just ignored. For example,
Process process = Runtime.getRuntime().exec(new String[]{"gnome-terminal","ls"});
Does not work. The command I ultimatly want to run would look something like this,
Process process = Runtime.getRuntime().exec(new String[]{"gnome-terminal","sudo","docker","exec","-it","sawtooth-shell-default", "bash"});
Second, Once I have this running, will additional commmands I run work within the Docker enviorment? I have a python file with a Stream handler that specifies the correct commands to run.
Other documentation on related issues was limited.
I made sure my code was wrapped in a runtime exception try catch and that I was running the correct .class file. Any help on this would be great!
Edit: I have also tried to run this in another linux terminal like Hyper and Tilda
I also am able to get a sudo sign in when I run the command like so,
Process process = Runtime.getRuntime().exec(new String[]{"gnome-terminal","--","sudo","docker","exec","-it","sawtooth-shell-default", "bash"});
However it closes immediatly after authorizing.
Okay this is what I was attempting to do.
https://www.atlassian.com/blog/software-teams/deploy-java-apps-with-docker-awesome
This site is outdated and I had to use this link for getting that latest version of the java PPA.
This process basically installs java into the docker contatiner so that I can run a java program that uses Runtime.
I have a Java application that needs to spawn another Java application. This second java application is long lived and might outlive the original java application. It's basically a big while loop that executes some networking code, and is not intended to terminate unless a specific condition happens. To launch this application, I use a bash script to double fork it, so that the original java application doesn't wait for it to complete:
How the original java app launches the shell script:
ProcessBuilder processBuilder = new ProcessBuilder(
"myshellscript",
"-a", "somearg",
"-b", "anotherarg");
final Process process = processBuilder.start();
process.waitFor();
if (process.exitValue() != 0)
{
// do something
}
The contents of the shell script:
fork() {
echo "Going to fork" >> /tmp/output.log
(setsid java -jar ./anotherapplication.jar "$#" &);
echo "Exited" >> /tmp/output.log
}
fork "$#"
In "output.log", I see "Going to fork" and "Exited" messages, but I never see any logs from the "anotherapplication.jar" app, which makes me think it doesn't start successfully. It also doesn't show in the output of ps aux either, so it definitely isn't running. Is this the right way to start the second application, or am I not starting it correctly?
Setsid should do what you want. I can't tell why your application doesn't start, but the application will not print anything to the /tmp/output.log, simply because you don't redirect output of the setsid line to the log file. I would redirect the stdout and stderr of that line to the output.log using:
(setsid java -jar ./anotherapplication.jar "$#" &) >>/tmp/output.log 2&>1
This will almost certainly show an error documenting why it fails to start. It's often a good idea to reset the standard input and output of daemon-like processes like this anyway.
I'm trying to write a small Java command-line application that will create a new file, and then open it with the systems default editor stored in $EDITOR, and then exit after the editor is closed.
So far, without luck, I've tried the following:
Desktop dt = Desktop.getDesktop();
dt.edit(file);
This method resulted in an UnsupportedOperationException, which sort of makes sense as I'm running my program from the terminal, not as a Java appliacation from the desktop.
Right now, I have this:
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(commandString); // "vim newfile"
proc.waitFor();
This is working, but not how I need it to. When I run
ps a | grep vim
I can see that it is indeed running in the background, with the filename I've given it:
1000 pts/1 S+ 0:00 vim 2014-07-16.23-02
Any ideas on how to make this run in the foreground?
vim, like many interactive programs, expects its stdin to be a real terminal that it can send ioctl calls to. But when executing through Runtime.exec() stdin will be redirected to the parent process (see the Javadoc on Process for more information).
In Java 7, you should be able to use ProcessBuilder.inheritIO() to pass along the file handles. (Disclaimer: I haven't tried it, YMMV.)
How to invoke sh file in linux terminal using Runtime.getRuntime().exec in java ?
I want to invoke the sh file in new terminal from java code. If i run it in terminal only it runs as a separate process, which will not be closed even if my programs exits. And thats why I'm not using ProcessBuilder, which stops the process invoked by it if the program using it exits.
If your script is marked as executable (chmod +x script.sh), you can invoke it by exec("./script.sh"). Otherwise you can directly call it using exec("sh script.sh").
Use:
Runtime.getRuntime().exec(new String[] { "/bin/bash", "-c", "sh myfile.sh" });
Since ProcessBuilder is just a thin wrapper around Runtime, using it directly will not do what you want.
Instead, you need to write a second script which creates a terminal window as a background process and detaches this process. General approach:
ProcessBuilder to start outer script
Outer script uses the Linux command nohup(1) to create a detached process for inner script. For example: `nohup xterm -e /bin/bash "script.sh &"
nohup cuts the connections between the new X terminal and the Java process. & sends the whole thing into the background, so the command doesn't until xterm exits.
I want to kill the particular Java process in Windows, like in Linux (ps -aux to get processid and then kill processid to kill the process).
You can use the jps utility that is included in the JDK to find the process id of a Java process. The output will show you the name of the executable JAR file or the name of the main class.
Then use the Windows task manager to terminate the process. If you want to do it on the command line, use
TASKKILL /PID %PID%
You can also find the PID of a java program with the task manager. You enable the PID and Command Line columns View -> Select Columns and are then able to find the right process.
Your result will be something like this :
This will work even when there are multiple instance of jar is running
wmic Path win32_process Where "CommandLine Like '%yourname.jar%'" Call Terminate
After setting the path of your jdk use JPS.Then You can eaisly kill it by Task ManagerJPS will give you all java processes
The solution I found is very simple. Use Window's WMIC & Java's Runtime to locate & kill the process.
Part 1: You need to put some sort of identifier into your app's startup command line. E.g. something like:
String id = "com.domain.app";
Part 2: When you run your app, make sure to include the string. Let's say you start it from within Java, do the following:
Runtime.getRuntime().exec(
"C:\...\javaw.exe -cp ... -Dwhatever=" + id + " com.domain.app.Main"
);
Part 3: To kill the process, use Window's WMIC. Just make sure you app was started containing your id from above:
Runtime.getRuntime().exec(
"wmic process Where \"CommandLine Like '%" + id + "%'\" Call Terminate"
);
In windows, we can use the PowerShell to list the java running process. Then using the process id we can kill the process. Please find the below commands that needs to be executed in the PowerShell.
To list the Java Process.
ps | Where-Object -Property ProcessName -EQ -Value 'Java'
To kill the java process with specific id.
Stop-Process <PID>
The above approach worked for me.
In windows XP and later, there's a command: tasklist that lists all process id's.
For killing a process in Windows, see:
Really killing a process in Windows | Stack Overflow
You can execute OS-commands in Java by:
Runtime.getRuntime().exec("your command here");
If you need to handle the output of a command, see example: using Runtime.exec() in Java
This is specific to Windows.
I was facing the same issue where I have to kill one specific java program using taskkill. When I run the java program, tasklist was showing the same program with Image name set as java.exe.
But killing it using taskkill /F java.exe will stop all other java applications other than intended one which is not required.
So I run the same java program using:
start "MyProgramName" java java-program..
Here start command will open a new window and run the java program with window's title set to MyProgramName.
Now to kill this java-program use the following taskkill command:
taskkill /fi "MyProgramName"
Your Java program will be killed only. Rest will be unaffected.
Open Git Bash
Type ps -ef | grep java
Find the pid of running jdk
kill -9 [pid]