I have a perl script that needs 2 arguments to be run. I am currently using Ubuntu and I managed to execute the perl script from terminal by changing directory to where the perl script exists and by writing
perl tool.pl config=../mydefault.config file=../Test
However, when I am trying to run the perl script from my java program (I am using eclipse), It always gives me the message Command Failure. This is the code :
Process process;
try {
process = Runtime.getRuntime().exec("perl /home/Leen/Desktop/Tools/bin/tool.pl config=../mydefault.config file=../Test");
process.waitFor();
if(process.exitValue() == 0) {
System.out.println("Command Successful");
} else {
System.out.println("Command Failure");
}
} catch(Exception e) {
System.out.println("Exception: "+ e.toString());
}
So please what is wrong in my code?
You should be separating the command from it's arguments in the call to exec(), such as:
Runtime.getRuntime().exec(new String[] {"perl", "/home/Leen...", "config=...", "file=..."});
With what you currently have, Runtime is looked for a command literally named perl /home/Leen/Desktop..., spaces and all.
When you run the whole command from the Terminal, your shell is smart enough to realize that a space delimits the name of the command (perl) from the arguments that should be passed to it (/home/Leen/Desktop..., config=..., file=...). Runtime.exec() is not that smart.
Related
I've created a java GUI using NetBeans v.8.2. Very new to Java.
One of the buttons in the GUI launches a shell script (I am aware that this is not ideal Java practice, but it is appropriate for my use case) using arguments gathered from other buttons/text fields in the GUI:
```
private void RunMacActionPerformed(java.awt.event.ActionEvent evt) {
String command[] = {scriptDirStr + "/./Master_run.sh",
projDirStr+"/",
DestDirStr+"/",
ECnonNormStr,
ECnormStr,
ProjID.getText(),
scriptDirStr +"/"};
System.out.print(Arrays.toString(command));
ProcessBuilder pb = new ProcessBuilder(command);
try {
Process p = pb.start();
} catch (IOException ex) {
Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
```
So, the idea is to launch Master_run.sh with a bunch of arguments.
Master_run.sh runs other R and python scripts, e.g.:
python2 $script_Path/array_data_extractor.py $spath >>$spath/masterOutput.txt 2>>$spath/masterErrors.txt
and
Rscript $script_Path/1_APS_generator_master.R $spath $dpath $APS_src_filename $project_ID $APS_norm_src_filename >>$spath/masterOutput.txt 2>>$spath/masterErrors.txt
and ends with
cat $spath/masterErrors.txt| mail -s $Project_title" done" myEmailAddress#gmail.com
I know the script gets launched because I get an email with the following errors:
"...line 14: python2: command not found"
and
"...line 16: Rscript: command not found"
When I run Master_run.sh with the same exact arguments from within the terminal, there are no such errors. Does anybody know what might be going wrong and/or how to fix it?
To rephrase the problem, it seems I am getting different behavior launching the same commands from within java vs. directly onto the command line.
Your shell environment is clearly different from java's environment. Try specifying the full path to python2 and Rscript. For example
/usr/local/bin/python2 $script_Path/array_data_extractor.py ...
Am trying to pop up a CMD then execute some Commands such as:
echo SOMETHING && echo SOMETHING && mkdir....etc
i managed to open the CMD but JAVA doesnt seem to recognize "&" inside string
the first command which before the "&" is the only being executed
any tips ?
try {
// Execute command
String command = "cmd /c start echo hello baby & echo the world";
Process child = Runtime.getRuntime().exec(command);
// Get output stream to write from it
} catch (IOException e) {
}
}
}
It's &&, not &.
A double ampersand is a logical "and", a single ampersand means "put the (first!) process into the background".
PS: By "cmd", do you mean the good ol' Windows cmd.exe? If yes, I don't know if those ampersands are working there. Try the PowerShell instead if so.
I have a problem with this code:
try {
String cmd = "C:\\Program Files\\MySQL\\MySQL Server 5.5\\bin\\mysqldump.exe -uroot -proot foo_db -rC:\\backup.sql";
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(cmd);
} catch(Exception e) {}
It doesn't get any error, pratically it doesn't DO anything: no backup and no execution of the cmd. Where's the problem?
It's strange, because the cmd-text is correct... i've tried to do it with 'Execute' command in windows and it works, but in java no.
Thanks in advance.
Your first problem was, as #pcalcao pointed out, that you are not reporting the exception. You really should never do this. At the very least you should do:
} catch(Exception e) {
e.printStackTrace();
}
java.io.IOException: Cannot run program "C:\Program": CreateProcess error=193, %1 isn't a Win32 valid application
That says that you have a problem with your application path. By default, if exec() is called with a single argument, then it will break the arguments up by spaces. Since you have spaces in your path you need to pass an array of strings to exec(). Something like:
try {
String cmd =
"C:\\Program Files\\MySQL\\MySQL Server 5.5\\bin\\mysqldump.exe";
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(new String[] { cmd, "-uroot", "-proot", "foo_db",
"-rC:\\backup.sql" });
// wait for it to finish
proc.waitFor();
} catch(Exception e) {
e.printStackTrace();
}
The first argument in the string array passed to exec() is then the full path to the command -- this can have spaces. Each of the other array elements is an argument to the command.
Lastly, you will need to wait for the process to finish otherwise it will execute in the background. That's what the waitFor() does.
You need to escape the whitespace with \, exec is trying to execute "C:\Program", from what you've showed in your answer to my previous comment.
NEVER leave a catch clause empty.
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
I tried to run a shell script from java code, but I am facing problem. The script is in batchstart.sh file -
#!/bin/ksh
export DISPLAY=:0.0
Now the script is run with a dot on the command line -- . batchstart.sh
How do I run it from java? My java code is below. It throws the following exception -
java.io.IOException: .: not found
at java.lang.UNIXProcess.forkAndExec(Native Method)
at java.lang.UNIXProcess.<init>(UNIXProcess.java:102)
at java.lang.ProcessImpl.start(ProcessImpl.java:65)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:451)
at java.lang.Runtime.exec(Runtime.java:591)
at java.lang.Runtime.exec(Runtime.java:429)
at SetDisplay.main(SetDisplay.java:12)
import java.io.*;
public class SetDisplay {
public static void main(String[] args) {
File wd = new File("/myhomedir/");
System.out.println("Working Directory: " +wd);
Process proc = null;
try {
proc = Runtime.getRuntime().exec(". batchstart.sh", null, wd);
} catch (Exception e) {
e.printStackTrace();
}
}
}
How do I make the shell script run ?
I tried the following code as well, but that too doesn't work.
File wd = new File("/bin");
System.out.println(wd);
Process proc = null;
try {
proc = Runtime.getRuntime().exec("/bin/bash", null, wd);
}
catch (IOException e) {
e.printStackTrace();
}
if (proc != null) {
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())), true);
out.println("cd /home/");
out.println(". batchstart.sh");
out.println("exit");
try {
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
proc.waitFor();
in.close();
out.close();
proc.destroy();
}
catch (Exception e) {
e.printStackTrace();
}
}
When run from the command line, using a dot at the start of a script indicates that the script should be run in the current environment, instead of spawning a new subshell and using a new copy of the current environment. This allows you to export a new value of an environment variable to be used by commands run later from the same interactive shell.
Obviously, this technique only works if you are running your batchstart.sh script from an actual shell. Java does not know how this mechanism works and so the dot means nothing to it. A script cannot modify the environment of the Java process it was called from.
If your goal is to change the value of the DISPLAY environment variable for other commands run by your Java process, consider using the ProcessBuilder class to specify a new environment for the child process. Java does not contain a built-in way to modify variables in its own environment.
The source command (".") is a shell built-in. You have to explicitly run /bin/ksh, passing your script name as the argument (followed by any script arguments).
You have a larger problem if you need to source the script. That usually means that environment changes happen in the context of the current shell, not a subshell.
This won't work with Java since Java's not a shell. You'll need to figure out how to change the environment with Java.
Of course, if I'm wrong and there's more to that script that just setting DISPLAY, it may work as suggested.
The method you're going to have to use depends on what you're trying to achieve(as in "Are you running other programs using exec() that rely on DISPLAY being set?" or "Does your Java program need DISPLAY to be set?").
If, as you state in your comment, it's only your Java program that needs DISPLAY set, just set it outside before your program runs. Create a cmd (or bash) file which sets the DISPLAY variable then calls the JRE to run your program.
#/bin/ksh
export DISPLAY-:0.0
/usr/bin/jre/java your_program blah.blah.blah
I would also modify your main() to check that it's set to something and exit gracefully if not:
if (System.getenv ("DISPLAY") == null)
// doesn't exist, exit gracefully.
The period "." is a shell built-in, and executes the script "in-place", analogous to #include in C/C++. Using "." outside of a shell-script has no meaning.
If you want to run the script from Java, you have to execute the script interpreter (/bin/ksh):
Runtime.getRuntime().exec("/bin/ksh batchstart.sh", ...)
but note that this is not semantically equivalent, since you're executing batchstart.sh as a sub-process instead of sourcing it.