I have been trying this for hours and I don't know what to do. I'm creating a Minecraft Bukkit plugin which it's supposed to have a "restart" command, which sends some warning messages and after that I would like to close the server. I created a batch file to do it but, I want Java to do it for me when the warnings are over, something like, idk:
open("C:/Users/Blablabla/Desktop/close.bat");
And for the moment I have this:
public String document = "C:/Users/Joan-Server/Desktop/Server/closer.bat";
if (args[0].equalsIgnoreCase("restart")) {
while(x != 0) {
Bukkit.broadcastMessage(plugin.name + ChatColor.GOLD + "¡ATENCIÓN! " + ChatColor.WHITE + "Reinicio del servidor en "
+ ChatColor.RED + x + " segundos.");
//Try--
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
x = x - 1;
}
//Try--
}
You could use something like this to execute your bat file:
try{
Process p = Runtime.getRuntime().exec("C:/path/to/file.bat");
p.waitFor();
}catch( IOException ex ){
//Catch if file doesn't exist or is inaccessible
}
catch( InterruptedException ex ){
//If the p.waitFor() is interrupted
}
Use this to execute your restart script and you should be good to go! Assuming your restart script stops the server, waits, and starts the server again.
Let me know if you need anything else!
You could also do your restart directly from your plugin via
getServer().dispatchCommand(getServer().getConsoleSender(), "restart");
If you really want to run the batch file, use
Runtime.getRuntime().exec("C:\\Users\\Blablabla\\Desktop\\close.bat");
If you also want to handle the console output of the bat file, check out this answer.
Related
I am currently working with eXist-db, and what I want to accomplish is executing command line script to start eXist-db (/bin/startup.sh) wait for it to create database so I can get collection from it.
//start database
try {
Runtime.getRuntime().exec(path + start);
} catch (IOException ex) {
return false;
}
//get collection
col = DatabaseManager.getCollection(URI + "/db", username, password);
I want to wait with the getCollection until database is created (can be called) , or after certain amount of waiting time if the database doesn't initialise I would like to kill it (lets say one minute at most). What is the best solution for this problem? Using sleep/wait several times and trying to call database? Something like this?
Process pr = null;
try {
pr = Runtime.getRuntime().exec(path + start);
} catch (IOException ex) {
return false;
}
for (int i = 0; i < 60; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
pr.destroy();
return false;
}
try {
dbDetected = initCollection();
} catch (XMLDBException ex) {
if (ex.errorCode != ErrorCodes.VENDOR_ERROR ||
"Failed to read server's response: Connection refused (Connection refused))"
.compareTo(ex.getMessage()) != 0 ) {
pr.destroy();
return false;
}
}
And as to killing part, I would like to confirm the assumption that storing the process and killing it using Process.destroy() function should be enough (basing it on assumption that the script for database is taking too long, in normal runtime, at the end of my application I would use provided eXist-db script /bin/shutdown.sh).
Rather than using startup.sh, if you are running in embedded mode, then you can use ExistEmbeddedServer (or it might be called EmbeddedExistServer, sorry I am away from my computer for a few days) class from the test package instead.
I don't think you can use startup.sh directly for your purpose, as it creates a foreground process. Instead you should start eXist from your Java application as described above.
I have a c++ program (.exe) that runs in the command line. You don't open it with cmd, it just opens the command prompt on its own and uses it as a menu. I also have a login system built in Java. My issue is, I'm trying to open my C++ program in the Java program, and it just isn't working. Here is the latest iteration of the relevant code:
btnLaunchMyProgram.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
File file1 = new File("C://Users//" + System.getProperty("user.name") + "//Desktop//My Program//myprogram.exe");
if(!file1.exists()) {
try {
HttpDownloadUtility.downloadFile("https://www.example.com/downloads/MyProgram.exe", "C://Users//" + System.getProperty("user.name") + "//Desktop//My Program//");
} catch (IOException e) {
e.printStackTrace();
}
}
try {
Process p = Runtime.getRuntime().exec(new String[] {"cmd.exe", "\"" + "C://Users//" + System.getProperty("user.name") + "//Desktop//My Program//MyProgram.exe" + "\""});
} catch (IOException e) {
e.printStackTrace();
}
}
});
In order to get rid of a few concerns you might have
- I have also tried the following, which runs my program in the background, but doesn't open the command prompt:
Process p = Runtime.getRuntime().exec(new String[] {"C://Users//" + System.getProperty("user.name") + "//Desktop//My Program//MyProgram.exe"});
and also:
Process p = Runtime.getRuntime().exec(new String[] {"cmd.exe", "C://Users//" + System.getProperty("user.name") + "//Desktop//My Program//MyProgram.exe"});
None of these work.
Just to be clear about what I need to happen:
1. I press the button (btnLaunchMyProgram)
2. It opens the exe and, by extension, the command prompt / console.
3. That's basically all it needs to do.
I am attempting to change the ACL permissions active on certain files using a result from an API I have built.
executorService.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println("hello");
JSONArray data = ServerAPI.riskCheck();
if(data != null){
JSONArray policycontent = data;
for(int i = 0; i < policycontent.length(); i++){
JSONObject privilege = policycontent.getJSONObject(i);
String user = privilege.getString("user");
String filepath = privilege.getString("filePath");
String accesses = "";
if(privilege.getBoolean("read") == true){
accesses = accesses + "r";
}
if(privilege.getBoolean("write") == true){
accesses = accesses + "w";
}
if(privilege.getBoolean("execute") == true){
accesses = accesses + "x";
}
if(privilege.getBoolean("execute") == false && privilege.getBoolean("write") == false && privilege.getBoolean("read") == false){
accesses = "-";
}
try {
System.out.println("TRYING TO RUN:");
Process p = Runtime.getRuntime().exec("setfacl -m \"u:" + user + ":" + accesses + "\" " + filepath);
//p.waitFor();
int exitVal = p.waitFor();
System.out.println("Exited with error code "+exitVal);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//System.out.println("setfacl -m \"u:" + user + ":" + accesses + "\" " + filepath);
}
}
System.out.println(ServerAPI.getRiskValue());
}
},1, 1, TimeUnit.SECONDS);
}
The query to the API is done every 1 second currently, checking as soon as a "risk value" is changed, it will get new permissions.
I am running this as a JAR in the folder with the files upon which the permissions should be enacted.
I am running the JAR as root.
I have attempted to do something as simple as append a line to a file in the same directory as the JAR on each iteration of the loop, however it does not do anything.
Each of the commands is a valid command that works when I run it in the terminal manually. The System.out.println was used to ensure that the command is being interpreted correctly, but seeing as it didn't matter what command I tried, I am running out of ideas.
It also exits with status 0 each time, and I have not been able to debug despite also trying to use processbuilder and variants of that approach, including error outputs.
Is this simply something I can not do using a Java program?
Thanks in advance!
The usual source of this sort of the problem is that Runtime.exec() does not provide a shell. If you want to execute commands in a shell, you'll need to actually execute a shell.
A possible work-around is to create bash shell script containing the commands that you want to run. Put #!/usr/bin/env bash at the top of the script to make sure that it gets run by the bash shell.
Then you can exec() the script, and pass it any arguments that you need to.
Edit - I've done this in the past by creating a single shell script as part of the application installation, not creating it dynamically. If you only need to do one thing, and can parameterize the script, this works well.
I have a executable program made on C++ (cf.exe) that takes parameters from a few text files (.txt), performs some calculations, and creates a file with the results (results.txt). This program needs no interaction. Once executed, when the calculations are done, it's automatically closed.
Then, I have other program made on Java, which contains a button that executes the cf.exe. When the button is pressed the following method is called:
public void executeExternalProgram(){
String filePath = "C++" + File.separator + "cf.exe";
try {
System.out.println("Executing C++ exe...");
Process p = Runtime.getRuntime().exec(filePath);;
} catch (Exception e) {
e.printStackTrace();
}
}
I don't get any error, but the cf.exe is not being executed when I press the button. When I execute manually the cf.exe, the results file is correctly created. Furthermore, I've tried to copy other programs, such as notepad.exe, to the same folder and execute it through Java without any problem. Can anyone see why it's not working?
I found that changing the command given to the process makes it work correctly. The change is the following:
Process p = Runtime.getRuntime().exec("cmd /c start "+ filePath);
Then, the updated code for the method called when the button is pushed:
public void executeExternalProgram(){
String filePath = "C++" + File.separator + "cf.exe";
try {
System.out.println("Executing C++ exe...");
Process p = Runtime.getRuntime().exec("cmd /c start "+ filePath);
} catch (Exception e) {
e.printStackTrace();
}
}
When i try this code, it seems as executed but it is not executed.
The process builder can find the executable file. System writes the println commands.
I found some example codes but my executable file is not in same folder with java file.
private static void executeOneFile(String folderPath) {
Process p;
String exePath = path + "\\" + folderPath + "\\";
try {
p = new ProcessBuilder(exePath + "myFile.exe").start();
//p = Runtime.getRuntime().exec("myFile.exe", null , new File(exePath) );
System.out.println("p is running");
p.waitFor();
System.out.println("p ended");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
There are several problems with the code above:
You don't handle stdin/stdout properly. So maybe there is an error but you won't see it because you're not reading the output of the child process.
Next, it's always a good idea to close the child's stdin with p.getOutputStream().close() to make sure it doesn't hang waiting for input.
Lastly, the current directory of the process is the same as that of the Java VM. So if you use relative paths to write the file, it will end up somewhere but rarely where you expect. Pass the absolute path of the file to your child process to make sure the output goes where it should.