I'm writing a program that needs to be able to open and terminate a Minecraft server via command prompt. The code I have for it so far is this:
Runtime.getRuntime().exec("cd ./Server"); //go to the server directory
Process server = Runtime.getRuntime().exec("java -Xmx1024M -Xms1024M -jar minecraft_server.exe nogui"); //run minecraft server in nogui mode
Thread.sleep((long)(1000*60*.5)); //wait 30 seconds
Runtime.getRuntime().exec("stop"); //terminate the server
Thread.sleep((long)(1000*60*.5)); //wait 30 seconds
server.destroy(); //forcibly terminate the server assuming it hasn't already
System.exit(0);
This is just the basic logic code I have come up for it. I have tried using BufferedWriters but they just don't work and it gets an error even by doing the cd command. I am useing Minecraft_Server.exe which is at minecraft.net/download.jsp. The "stop" command runs while the process is active and tells the program to save the server and then terminate. Do I need to be using Threads in some way. Please help :) I've put several hours trying to find the answer already and I'm just clueless lol.
Your "cd ./Server" command, I think is going to lose context here, because the next call to exec isn't going to get the results of the first call. In other words, each call to exec is completely independent of other calls to exec.
Try putting some of this in a shell script instead, and simply exec the script. If you're controlling the server via the command line anyway, then this isn't any more complex than what you've already tried.
You might want to the look at the ProcessBuilder (here) where you can specify the working directory that will be used for all the command you want to execute after.
Each command is run as a separate process.
Your "cd ./Server" has no effect on the commands you run after.
Do you have a command line program called stop?
I would write
Thread.sleep(30 * 1000); // 30 Seconds.
and I wouldn't call System.exit(0);
To run command in particular dir use special version of exec
public Process exec(String command, String[] envp, File dir)
where dir is working dir for the process
Try putting the commands in a string array :
String[] cmd = { "cd","./Server" };
and
String[] cmd2 = {"java", "-Xmx1024M", "-Xms1024M", "-jar", "minecraft_server.exe", "nogui"}
Then try to
Runtime.getRuntime().exec(cmd); //go to the server directory
Process server = Runtime.getRuntime().exec(cmd2); //run minecraft server in nogui mode
Thread.sleep((long)(1000*60*.5)); //wait 30 seconds
Runtime.getRuntime().exec("stop"); //terminate the server
Thread.sleep((long)(1000*60*.5)); //wait 30 seconds
server.destroy(); //forcibly terminate the server assuming it hasn't already
System.exit(0);
Also stop will do nothing since you do not reference what to stop.
Related
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 using Intellij IDEA and i'm trying to run a shell script with arguments, and read the result of the execution.
this script is on my java SRC packge,
myScript.sh run a compiled c program
String[] cmd = { "/bin/bash", "-c", "myScript" };
Runtime.getRuntime().exec(cmd);
i resolved this by making a copy of myScript.sh in /ect/bin.
so this make my script as an environment path and give me the ability to read all the out put or add supplement arguments.
no changes has been made
on my Java code
.
Use ProcessBuilder:
Process process = new ProcessBuilder(cmd).start();
Then process.getInputStream() gives you access to the process standard output (stdout) which you can read as usual; process.getErrorStream() allows to read standard error (stderr).
Also you can do process.waitFor() to wait for the project to finish.
Note that to read anything from the stdout of a process you need to wait for the process to finish (or read it in a loop) and not just finish your main program.
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!
I would like to check whether a jar of mine is running on the users system, to then relaunch if it is closed.
I am aware of the command jps -l which makes it possible to check the current running jars. Only problem is that for that line to work, it requires the user to have a JDK installed. So I was then wondering whether or not there is an equivalent to the jps -l line, which doesn't need a JDK or anything, but just checks whether a specific jar is running.
In the past I have also used the line cmd /c tasklist for Windows and the line top -F -R -o cpu for Mac. To check whether an app or exe was running, but that doesn't really seem to be working. When running the tasklist line on Windows and I then check for an exe called "myApp", it doesn't find it. Even though it might be running. Otherwise this would have been a perfect method, to check for a running app, exe or jar.
Here is an example code of how I tried to use the tasklist command to check for a specific executable.
try {
String procss;
Process pRun = Runtime.getRuntime().exec("cmd /c tasklist");
BufferedReader input = new BufferedReader(new InputStreamReader(pRun.getInputStream()));
while ((procss = input.readLine()) != null) {
if(!procss.contains("myApp"))
{
//Runtime command to launch exe or app.
}
}
input.close();
} catch (Exception err) {
err.printStackTrace();
}
Basically I would like to just edit the code above, to have a command line, of which is able to actually check whether the exe, app or jar is running. Maybe there is an alternative to cmd /c tasklist and top -F -R -o cpu, which is able to get all processes running on a pc and not just .exe or .app
On windows, you could use the wmic command to get the command line parameters a program was launched with.
For example, using wmic process where "name like '%java%'" get commandline,processid (basically just means "get the PID and command line arguments of process with a name like java") gives me this output for a test program:
616
"C:\Program Files\Java\jre1.8.0_111\bin\javaw.exe" -jar "A:\Programmering\Java\Pong\out\artifacts\Pong_jar\Pong.jar"
As you can see, you can get the location of the jar file which is running (which you could then use to check if it's your program). In this case, I just launched it by double clicking the jar file, you may get different outputs if you launch it in a different way, but there should always be something you can use to identify the java process (like a main class or jar file).
I know how to start the batch file using java code.
When i run the batch file command prompt is opened.
To close the command prompt i am using the taskill /im cmd.exe.
but the problem is that the command prompt that is used to start the jboss is also closed.
i want to kill the cmd with a particular process id.
How do i get the process id of a particular cmd promt and kill that using java
Run the batch file with cmd.exe /c job.bat. The /c switch carries out the command and then terminates the command interpreter.
can't you add exit to your batch file to exit it's own command prompt. Uisng taskill seems overkill for just closing one command prompt, don't you think?
PS: I've never worked on batch files just the command prompt so I'm assuming it accepts the same commands.
Here is the solution that works: to close command window after executing the commands from the batch (.bat) file you need to add "exit" (without the quotes) in a new line of your batch file. If you want to delay the execution this is the way and it works:
public class TestSleep
{
public static void main ( String [ ] args )
{
System.out.println("Do this stuff");
try
{
Thread.currentThread().sleep(3000);
}
catch ( Exception e ) { }
System.out.println("Now do everything after this");
}
}
Cheers
If you start the batch file with Runtime.exec(), it returns you a Process object. Calling the destroy() method will kill that process.
Although this seems to be an old question and probably resolved.. I struggled with the same thing for a long time.. Finally this works
String command = "cmd.exe /c build.bat";
Runtime rt = Runtime().getRuntime();
Process pr = rt.exec(command);
I too had the same problem. I first used as
Runtime.getRuntime().exec("cmd.exe start /c test.bat");
Then I tried as below. It works fine.
Runtime.getRuntime().exec("cmd.exe /c start test.bat");
Try this.