Basically I have 2 commands I need to execute via a java program the way you would if you were just typing it into terminal.
so like
cd /Users/nameOfUser/Desktop/someFolder/someSubFolder
and then another command I want to execute within that directory. Currently I am doing this:
Process navigate = Runtime.getRuntime().exec("cd /Users/nameOfUser/Desktop/someFolder/someSubFolder");
Process doSomething = Runtime.getRuntime().exec("commandInThatDirectory");
Which doesn't work, it doesn't throw an exception but the second process doesn't seem to take place in the directory specified before it. I am new to processes and runtimes so please bear with me :P.
Is their a way to execute the commands back to back within the same instance of terminal or at least a format for 1 command where you can specify the directory for another command to take place in? I'm a linux user so I don't know mac terminal very well sorry.
It can be done something like this. you can run any command by by placing a semicolon between the commands.
public class Main {
public static void main(String[] args) throws IOException {
ProcessBuilder pb1 = new ProcessBuilder(
"bash",
"-c",
"cd /Users/nameOfUser/Desktop/someFolder/someSubFolder;commandInThatDirectory");
pb1.redirectErrorStream(true);
Process p = pb1.start();
}
}
Related
Below is a python script that executes a linux bash command "echo Hello World > ./output"
import os
os.system("bash -c \"echo Hello World > ./output\"");
I am trying to do the same with Java. Below is my best effort, following the instructions I found here: Want to invoke a linux shell command from Java
import java.io.IOException;
public class callCommand {
public static void main(String[] args) {
try {
Process p = Runtime.getRuntime().exec(
new String[]{"bash","-c",
"\"echo Hello World > ./output\""});
} catch(IOException e) {
e.printStackTrace();
}
}
}
It compiles without issue, and runs without complaint, but no output file is generated.
The extra quotes around echo ... should be removed:
Process p = Runtime.getRuntime().exec(new String[]{
"bash", "-c",
"echo Hello World > ./output"
});
The python version needs extra quotes to tell the underlying system that echo Hello World > ./output is a single argument. The java version explicitly specifies arguments as separate strings, so it doesn't need those quotes.
Also, your version doesn't "run without complaint", you just don't see the complaints, because you don't read the error stream of the created process.
The standard input, output and error streams to/from a system process started from Java are accessed through the methods getOutputStream(), getInputStream() and getErrorStream() of Process.
I recommend you to get the error output produced by your system process:
Process p = Runtime.getRuntime().exec(...);
InputStream input=p.getErrorStream();
do
{
n=input.read(...);
}
while (n>=0);
Be careful: For your actual problem, this would be enough. But for a process which produces a longer error/output, you need to perform the reading of the standard error/output in a separate thread. If not, the system process would block when the error/output buffer is full, and wait till it is externally consumed, and if you place the reading loop just after the process is executed, it will never execute and so, the program will get into a deadlock.
I was successfully using AutoIt to execute commands but I was thinking I could get a more stable implementation via Runtime. That way I know the commands will always be executed and won't get thrown by Interruption exceptions, and other random crap. Is there something about Runtime that I don't know which won't allow for continuous execution of commands? Does it not have a memory for the outputs of previous commands, i.e. is it not running in a persistent command line?
The following commands navigate to a folder and execute a Maven script. How would I get this to work? If there were 10+ more commands that follow, would they execute within in the same process?
sendCommand("cmd.exe cd homepath/plugins");
sendCommand("mvn archetype:generate -DarchetypeCatalog=file://homepath/.m2/repository");
private static void sendCommand(String text) throws IOException {
Runtime.getRuntime().exec(text);
}
Runtime.exec() returns a Process instance. Call waitFor() on this object to wait until it is complete before running a next command. You can communicate with a Process via its getInputStream()/getOutputStream() methods.
Also read the Javadoc. For Runtime.exec it says "Executes the specified string command in a separate process."
A few things.
You should use Process and ProcessBuilder instead.
The commands have to be split up and tokenized according to arguments.
The way you have it written, those two commands will not be executed in the same process.
Fortunately for you, ProcessBuilder supports changing the working directory of the command anyway.
As an example:
sendCommand("homepath/plugins", "mvn", "archetype:generate", "-DarchetypeCatalog=file://homepath/.m2/repository");
private static void sendCommand(String workingDirectory, String... command) throws IOException {
Process proc = new ProcessBuilder(command).directory(new File(workingDirectory)).start();
int status = proc.waitFor();
if (status != 0) {
// Handle non-zero exit code, which means the command failed
}
}
Notice how a) the command has been split up, and b) that the working directory is passed in and set using ProcessBuilder.directory(File). This will get your desired behavior, but note that each command will still be a separate process, and there's no way to combine them with Java. You'd have to use Maven's features to get them all to run at once by specifying multiple build targets.
So I'm creating a Java program and I want to make it so that you can ask it to open a program.
But, here's the catch, I want the program it opens to be taken from the user input, right now I'm trying to change this
try{Process p = Runtime.getRuntime().exec("notepad.exe");}
catch(Exception e1){}
Into something that opens a program that you asked it to open.
Here's an example of what I want:
User: Can you open chrome?
Program: Of course, here you go!
chrome opens
Could anyone tell me how I would be able to do this?
You can do it in two ways:
1.By Using Runtime:
Runtime.getRuntime().exec(...)
So, for example, on Windows,
Runtime.getRuntime().exec("C:\application.exe -arg1 -arg2");
2.By Using ProcessBuilder:
ProcessBuilder b = new ProcessBuilder("C:\application.exe", "-arg1", "-arg2");
or alternatively
List<String> params = java.util.Arrays.asList("C:\application.exe", "-arg1", "-arg2");
ProcessBuilder b = new ProcessBuilder(params);
or
ProcessBuilder b = new ProcessBuilder("C:\application.exe -arg1 -arg2");
The difference between the two is :
Runtime.getRuntime().exec(...)
takes a single string and passes it directly to a shell or cmd.exe process. The ProcessBuilder constructors, on the other hand, take a varargs array of strings or a List of strings, where each string in the array or list is assumed to be an individual argument.
So,Runtime.getRuntime.exec() will pass the line C:\application.exe -arg1 -arg2 to cmd.exe, which runs a application.exe program with the two given arguments. However, ProcessBuilder method will fail, unless there happens to be a program whose name is application.exe -arg1 -arg2 in C:.
You can try it with like. Pass whole path of where you install chrome.
try{
Process p = Runtime.getRuntime().exec("C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe");
}
catch(Exception e1){
}
When using exec, it is essentially the same as if you were using the command line on windows. Open Command Prompt, type open, and see if it gives details as to how it opens files. If not, find the opener. Usually when dealing with command line operations, there are multiple parameters that are required for opening files/applications. An example of this would be for opening the "TextEdit.app" application on a mac.
Process p = Runtime.getRuntime().exec("open -a TextEdit.app");
Terminal(for mac) would open the app using the -a flag, meaning "application." You could open a file doing:
Process p = Runtime.getRuntime().exec("open filename.file_ext -a TextEdit.app");
The second one will tell the computer to find the application named <app_name>.app and open the file filename.file_ext
I know this is not going to work for a windows machine, but it's only to show how to use the command line operations for opening files and applications. It should be similar for windows though.
Hope this helps
public static void main(String args[]) throws IOException
{
Process p = Runtime.getRuntime().exec("java E:/workspace/JNIProgram/src/JNIProgram.class");
}
so I have this code and am trying to run the JNIProgram.class file however the program gets terminated instantly without doing its job (which is to create a new txt file and write to it)
So what am I doing wrong
The java command expects a Java class name, not a filename.
So the command java E:/workspace/JNIProgram/src/JNIProgram.class is wrong. If you try this manually from a command prompt window you'll get an error message.
The command should be something like this:
java -cp E:\workspace\JNIProgram\src JNIProgram
Note: What's after the -cp option is the classpath, and after that the fully-qualified class name (which is just JNIProgram, if the class is not in a package).
First make sure that you can run the command manually from the command line before you make it work from another Java program.
I am facing a weird issue with executing a system command from JAVA code.
Actually i want to get the Mac OSX system information from my JAVA App.
For that im using
Runtime.getRuntime().exec("system_profiler -detailLevel full");
This is working fine.If i print the output,it is cool.
But i want to write this information to a plist file for future use.For that im using the -xml argument of system_profiler.like,
String cmd = "system_profiler -detailLevel full -xml > "+System.getProperty( "user.home" )+"/sysinfo.plist";
Process p = Runtime.getRuntime().exec(cmd);
Basically this should create a plist file in the current users home directory.
But this seems to be not writing anything to file.
Am i missing something here ?
My Java is more than rusty, so please be gentle. ;-)
Runtime.exec() does not automatically use the shell to execute the command you passed, so the IO redirection is not doing anything.
If you just use:
"/bin/sh -c system_profiler -detailLevel full > path/file.plist"
Then the string will be tokenized into:
{ "/bin/sh", "-c", "system_profiler", "-detailLevel", "full", ">", "path/file.plist" }
Which also wouldn't work, because -c only expects a single argument.
Try this instead:
String[] cmd = { "/bin/sh", "-c", "system_profiler -detailLevel full > path/file.plist" };
Process p = Runtime.getRuntime.exec(cmd);
Of course, you could also just read the output of your Process instance using Process.getInputStream() and write that into the file you want; thus skip the shell, IO redirection, etc. altogether.
Christian.K is absolutely correct. Here is a complete example:
public class Hello {
static public void main (String[] args) {
try {
String[] cmds = {
"/bin/sh", "-c", "ls -l *.java | tee tmp.out"};
Process p = Runtime.getRuntime().exec (cmds);
p.waitFor ();
System.out.println ("Done.");
}
catch (Exception e) {
System.out.println ("Err: " + e.getMessage());
}
}
}
If you weren't using a pipe (|) or redirect (>), then you'd be OK with String cmd = "ls -l *.java", as in your original command.
If you actually wanted to see any of the output in your Java console window, then you'd ALSO need to call Process.getInputStream().
Here's a good link:
Running system commands in Java applications