I'm trying to run a multi-agent system using JADE by code.
Usually, I can run the jade system by command line using the following command:
java jade.Boot -gui
It also works well using Netbeans IDE by changing the project properties and pointing the run configuration to the jade.Boot class.
My problem is: I want to run this system by java code... let's say, when a user clicks a button, and as far as I know, this command specified above should work using the following code:
Process p=null;
try {
p = Runtime.getRuntime().exec("java jade.Boot -gui;");
}
catch (IOException ex) {
Logger.getLogger(SimulationCreator.class.getName()).log(Level.SEVERE, null, ex);
}
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
String s;
try {
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
} catch (IOException ex) {
Logger.getLogger(SimulationCreator.class.getName()).log(Level.SEVERE, null, ex);
}
But I'm getting nothing, neither the JADE system is running nor I'm getting any error.
What am I missing ?
P.S.: I'm working on ubuntu 20.0.
P.S.: running other commands by code like "ps -aux" works very well!
Your problem may be a difference between PATH of the current running VM, compared the shell (bash etc) you use and implicit passing of CLASSPATH. Check the location of java which which java in the shell that works and try using in your exec.
Also you won't see all issues when running as you don't access the error stream at same time as the output stream, changing to ProcessBuilder allows easier debugging as you can redirect the out/err streams to a file. But if JADE runs for a long time or produces a lot of output you should consumer STDOUT+ERR in background threads.
Try this in jshell:
String[] cmd = new String[]{"java", "jade.Boot", "-gui"};
ProcessBuilder pb = new ProcessBuilder(cmd);
File fileOut = new File("stdout.log");
File fileErr = new File("stderr.log");
pb.redirectError(fileErr);
pb.redirectOutput(fileOut);
Process p = pb.start();
int rc = p.waitFor();
String stdout = Files.readString(fileOut.toPath());
String stderr = Files.readString(fileErr.toPath());
System.out.println("Exit : "+rc +' '+(rc == 0 ? "OK":"**** ERROR ****"));
System.out.println("STDOUT : "+stdout);
System.out.println("STDERR : "+stderr);
Related
I am trying to build a GUI for GCC which has some basic functionalities like compile, link, execute, debug, etc for C++ programs using Java. I am creating strings of command which I pass to the ProcessBuilder and run it via command prompt and GCC.
command = "cd src & cd Resources & g++ " + compileFile.cpp +" -Wall "+ " -o "+ "tempOut";
This is a sample code for compiling the file.
Part of this is the debug functionality for which I am using GDB. Now the problem is GDB needs additional input to add breakpoints, remove breakpoints and so on. I am having trouble on how to pass these necessary inputs to GDB via Java terminal. If I pass the commands in the command prompt, it is working fine and I get the desired output.
enter image description here
But whenever I fire the GDB command from the Java program, I cannot pass any inputs from the IDE's terminal. I am aware that each GDB command uses a different process and I tried attaching Java's process ID to GDB but I just get a blank output console. It seems that the GDB session has started but there is no way to interact with that process through the IDE's output console.
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("#")[0]);
command = "gdb attach "+ pid;
fireCommand();
EDIT
This is the method that interacts with command prompt to take input and display output in the IDE's output console:
public void fireCommand() {
String line;
String os = System.getProperty("os.name");
ProcessBuilder builder;
if(os.startsWith("Win")) {
builder = new ProcessBuilder("cmd.exe", "/c", command);
}
else{
builder = new ProcessBuilder("bash", "-c", command);
}
try {
process = builder.start();
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
while ((line = reader.readLine()) != null) {
if(line.contains("Input the value")) {
//any other user input in non debug execution
String value = JOptionPane.showInputDialog(line);
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(process.getOutputStream()));
writer.write(value, 0, value.length());
writer.newLine();
writer.close();
}
else {
output.append(line).append("\n");
}
}
int exitVal = process.waitFor();
if (exitVal == 0) {
//display("Success!");
display(output.toString());
} else {
String lineErr;
BufferedReader readerErr = new BufferedReader(
new InputStreamReader(process.getErrorStream()));
while ((lineErr = readerErr.readLine()) != null) {
outputErr.append(lineErr).append("\n");
}
//display(exitVal);
display(outputErr.toString()); //Display the uncatched errors
}
} catch (IOException e) {
display("There was a problem with the I/O");
e.printStackTrace();
} catch (InterruptedException e) {
display("There was a interruption with the execution");
e.printStackTrace();
}
if(!outputErr.toString().isEmpty())
errorFormatDisplay(); //display Error output function
}
Any leads on this would be very helpful. Thank you.
I am aware that each GDB command uses a different process
No, gdb runs as one process. Did you mean to say that you are creating a new gdb process every time you try to pass it a gdb command ?
It seems that the GDB session has started but there is no way to interact with that process through the IDE's output console.
Maybe you should use The GDB/MI Interface, which e.g. the Emacs debugger mode gud uses.
Here's the situation. Im creating a UI which will allow make using a genetic programming system (ECJ) easier to use.
Currently you need to run a command prompt within the ECJ folder and use the commands similar to this to execute a parameter file.
java ec.Evolve -file ec\app\tutorial5\tutorial5.params
Where the full path of tutorial5 is
C:\Users\Eric\Documents\COSC\ecj\ec\app\tutorial5\tutorial5.params
and the command prompt must be executed from
C:\Users\Eric\Documents\COSC\ecj
My program makes the user select a .params file (which is located in a ecj subdirectory) and then use the Runtime.exec() to execute
java ec.Evolve -file ec\app\tutorial5\tutorial5.params
What i have so far
// Command to be executed
String cmd = "cd " + ecjDirectory;
String cmd2 = "java ec.Evolve -file " + executeDirectory;
System.out.println(cmd);
try {
Process p = Runtime.getRuntime().exec(
new String[]{"cmd.exe", "/c", cmd, cmd2});
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
statusTF.append(r.readLine());
p.waitFor();
} catch (IOException | InterruptedException ex) {
System.out.println("FAILED: " + ex.getMessage());
statusTF.append("Failed\n");
}
Currently it outputs the change directory command but nothing else.
Can this be done?
First, the 'cd' command can't be executed by Runtime.exec() in the first place (see How to use "cd" command using Java runtime?). You should be able to just set the working directory for the process when you call exec (see below).
Second, running 'cmd.exe /c' to execute your process isn't what you want here. You won't be able to get the results of your process running, because that is returned to the command window -- which eats the error and then closes without passing the error along to you.
Your exec command should look more like this:
Process p = Runtime.getRuntime().exec(
command, null, "C:\Users\Eric\Documents\COSC\ecj");
Where 'command' looks like this:
String command = "java ec.Evolve -file ec\app\tutorial5\tutorial5.params"
Edit: For reading error messages, try this:
String error = "";
try (InputStream is = proc.getErrorStream()) {
error = IOUtils.toString(is, "UTF-8");
}
int exit = proc.waitFor();
if (exit != 0) {
System.out.println(error);
} else {
System.out.println("Success!");
}
You can use Java processbuilder:
processBuilder documentation!
you can define the working directory of the process and all other stuff.
Each call to exec() runs in a new environment, this means that the call to cd will work, but will not exist to the next call to exec().
I prefer to use Apache's Commons Exec, it's provides an excellent facade over Java's Runtime.exec() and gives a nice way to specify the working directory. Another very nice thing is they provide utilities to capture standard out and standard err. These can be difficult to properly capture yourself.
Here's a template I use. Note that this sample expects an exit code of 0, your application may be different.
String sJavaPath = "full\path\to\java\executable";
String sTutorialPath = "C:\Users\Eric\Documents\COSC\ecj\ec\app\tutorial5\tutorial5.params";
String sWorkingDir = "C:\Users\Eric\Documents\COSC\ecj";
try (
OutputStream out = new ByteArrayOutputStream();
OutputStream err = new ByteArrayOutputStream();
)
{
// setup watchdog and stream handler
ExecuteWatchdog watchdog = new ExecuteWatchdog(Config.TEN_SECONDS);
PumpStreamHandler streamHandler = new PumpStreamHandler(out, err);
// build the command line
CommandLine cmdLine = new CommandLine(sJavaPath);
cmdLine.addArgument("ec.Evolve");
cmdLine.addArgument("-file");
cmdLine.addArgument(sTutorialPath);
// create the executor and setup the working directory
Executor exec = new DefaultExecutor();
exec.setExitValue(0); // tells Executor we expect a 0 for success
exec.setWatchdog(watchdog);
exec.setStreamHandler(streamHandler);
exec.setWorkingDirectory(sWorkingDir);
// run it
int iExitValue = exec.execute(cmdLine);
String sOutput = out.toString();
String sErrOutput = err.toString();
if (iExitValue == 0)
{
// successful execution
}
else
{
// exit code was not 0
// report the unexpected results...
}
}
catch (IOException ex)
{
// report the exception...
}
On Windows, I try to execute a java command (java -version for example) using Runtime.getRuntime().exec("java -version").
There is no errors , but the command seems to be never executed. Or JAVA is called but do nothing.
I put this command in a BAT file and try to execute Runtime.getRuntime().exec("file.bat").
I have the same bad result.
Six months before, it was OK.
Is there any RESTRICTIONS now to do that ? Only on Windows ?
Thanks for your help.
Try to send -version as a second String to the Runtime Executor.
Additionally, you can log the OutputStream to help investigate the issue.
try {
Process process = Runtime.getRuntime().exec(new String[]{"java", "-version"});
try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while((line = br.readLine()) != null){
LOGGER.info("RuntimeProcess Printed: {}", line);
}
}
} catch (IOException e) {
LOGGER.error("ERROR: {}", e);
}
Lastly, be mindful of the command you are running. For instance if you try to run a Unix command on a Windows machine you're going to see exceptions.
Hope this helps.
I'm trying to run a shell script (say myscript.sh) from a java program.
when i run the script from terminal, like this :
./myscript.sh
it works fine.
But when i call it from the java program, with the following code :
try
{
ProcessBuilder pb = new ProcessBuilder("/bin/bash","./myScript.sh",someParam);
pb.environment().put("PATH", "OtherPath");
Process p = pb.start();
InputStreamReader isr = new InputStreamReader(p.getInputStream());
BufferedReader br = new BufferedReader(isr);
String line ;
while((line = br.readLine()) != null)
System.out.println(line);
int exitVal = p.waitFor();
}catch(Exception e)
{ e.printStackTrace(); }
}
It doesnt goes the same way.
Several shell commands (like sed, awk and similar commands) get skipped and donot give any output at all.
Question : Is there some way to launch this script in a new terminal using java.
PS : i've found that "gnome-terminal" command launches a new terminal in shell,
But, i'm unable to figure out, how to use the same in a java code.
i'm quite new to using shell scripting. Please help
Thanks in advance
In java:
import java.lang.Runtime;
class CLI {
public static void main(String args[]) {
String command[] = {"/bin/sh", "-c",
"gnome-terminal --execute ./myscript.sh"};
Runtime rt = Runtime.getRuntime();
try {
rt.exec(command);
} catch(Exception ex) {
// handle ex
}
}
}
And the contents of the script are:
#!/bin/bash
echo 'hello!'
bash
Notes:
You'll do this in a background thread or a worker
The last command, in the shell script, is bash; otherwise execution completes and the terminal is closed.
The shell script is located in the same path as the calling Java class.
Don't overrwrite your entire PATH...
pb.environment().put("PATH", "OtherPath"); // This drops the existing PATH... ouch.
Try this instead
pb.environment().put("PATH", "OtherPath:" + pb.environment().get("PATH"));
Or, use the full directories to your commands in your script file.
You must set your shell script file as executable first and then add the below code,
shellScriptFile.setExecutable(true);
//Running sh file
Process exec = Runtime.getRuntime().exec(PATH_OF_PARENT_FOLDER_OF_SHELL_SCRIPT_FILE+File.separator+shellScriptFile.getName());
byte []buf = new byte[300];
InputStream errorStream = exec.getErrorStream();
errorStream.read(buf);
logger.debug(new String(buf));
int waitFor = exec.waitFor();
if(waitFor==0) {
System.out.println("Shell script executed properly");
}
This worked for me on Ubuntu and Java 8
Process pr =new ProcessBuilder("gnome-terminal", "-e",
"./progrm").directory(new File("/directory/for/the/program/to/be/executed/from")).start();
The previous code creates a new terminal in a specificied directory and executes a command
script.sh Must have executable permissions
public class ShellFileInNewTerminalFromJava {
public static void main(String[] arg) {
try{
Process pr =new ProcessBuilder("gnome-terminal", "-e", "pathToScript/script.sh").start();
}catch(Exception e){
e.printStackTrace();
}
}
}
I am trying to execute the C code from Java code which is already compiled and executed, but, I am not getting any output from the executable file. Can anyone help me to complete this task?
Code is as follows.
public class Test {
public static void main(String args[]) {
try {
Process processCompile = Runtime.getRuntime().exec("e:/Sample.exe");
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
Try this:
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(processCompile .getInputStream()));
// read the output from the command
System.out.println("EXE OUTPUT");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
This method would work only if you run the java program with admin privileges.
If you have privileges, then can you try running your process under "cmd" shell (Which is forked by your java process). An implementation do so this is done here "LinuxInteractor" ( But is in linux). Just minor change needed to port to Windows version.
Finding hard and soft open file limits from within jvm in linux (ulimit -n and ulimit -Hn)