i have imported a certain library which executes the following command
Runtime.getRuntime().exec("svd");
Now in my bash shell, i can execute svd as it points to installed folder "/usr/local/bin/svd". However my java programs are unable to execute "svd" and eclipse returns with error "Cannot run program "svd": error=2, No such file or directory"
I have added the following to my environment variables in run configurations of eclipse.
$PATH = /usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/bin/svd
svd = /usr/local/bin/svd
However eclipse still says its unable to run program "svd". Is there any way to fix this other than manually writing the full path?
e.g Runtime.getRuntime().exec("/usr/local/bin/svd");
It's not eclipse who cannot run the svd program but the jvm, because it cannot find svd's path on the system.
You should put your svd program on $PATH variable so that when the JVM runs your program and finds a call to svd, it should know where this svd program is located so it may call it.
For how to configure your $PATH variable on OSX, check here : Setting environment variables in OS X?
I also noticed you use Runtime to run external programs in your java program. That is an ancient way to run external programs in java. You should consider using the ProcessBuilder instead. It's much more flexible, and is considered the best choice to run external programs now:
ProcessBuilder pb = new ProcessBuilder("svd");
Process p = pb.start();
//You could also read the error stream, so that when svd is not correctly set on the running system, you may alert the user.
BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
int retCode = p.waitFor();
if(retCode == 2){
//alert the user that svd is not correctly set on PATH variable.
LOGGER.error(sb);
System.out.println("ERROR!! Could not run svd because it's not correctly set on PATH variable");
}
Related
I am using intellij IDEA to develop an AndroidStudio Plugin. The function of the plugin is to create a flutter plugin.
I have written a shell script, which uses flutter create to create a flutter plugin. Then I wrote the code to call the script in intellij IDEA, and everything worked here. What I mean is that using Runtime.getRuntime().exec can call shell scripts normally, and it can also meet my expectations.
public static class ShellUtil {
public static String runShell(String shStr) throws Exception {
Process process;
String[] command = new String[] {"bash","-c",shStr};
process = Runtime.getRuntime().exec(command);
process.waitFor();
BufferedReader read = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
String result = "";
while ((line = read.readLine())!=null){
result+=line;
}
return result;
}
}
But after I compiled it into a jar package and installed it in AndroidStudio, everything changed. The PATH I printed out was only /usr/bin:/bin:/usr/sbin:/sbin, I can be sure that I added flutter to the PATH of bash_profile. I searched a lot of information, and it seems to be saying that java has opened a new shell process, and this process cannot get all the environment variables of bash_profile.
My question is: How can I get the environment variables in bash_profile in the java shell process?
Latest development: I execute source ~/.bash_profile at the beginning of the shell file, and I can get the environment variables I want. But it does not mean that my PATH is not effective. Before adding, I restarted the computer and run intellij IDEA to ensure that the environment variables in bash_profile are all effective.
Although I can execute export PATH before executing the script in java, this is not what I want, because the path for installing flutter is different for everyone, and I hope to get the result of which flutter.
I'm attempting to run a Python script using Java code in Intellij IDEA:
String commandString = "python /home/.../mypythonscript.py arg1 arg2";
try {
Process process = Runtime.getRuntime().exec(commandString);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
} catch(IOException e) {
System.out.println(e.getMessage());
The Python script outputs a single String, and works great when I run it from my Ubuntu Linux terminal. However, using the above Java to run the Python script returns an error message:
Failed to run Python Script: Cannot run program "python": error=2, No such file or directory.
The file path is correct (the path and arguments I give are identical to what I used to run the Python script in the terminal), and I've set the script permissions to 777. In Intellij, I've also gone to File>Settings>Appearance & Behavior>Path Variables and added a path to the folder that contains the Python script (it's being held in a folder for Pycharm projects). However, I'm still getting the error.
Any help would be much appreciated!
A more experienced Java developer friend of mine who doesn't have an account figured out the problem, the solution to which I'm posting here for anyone encountering a similar issue in the future:
The script was written in Python3, but the code I used:
String commandString = "python /home/.../mypythonscript.py arg1 arg2";
is for Python 2. It should have been written:
String commandString = "python3 /home/.../mypythonscript.py arg1 arg2";
I've written a Java program that runs a script on my Mac:
Runtime rt = Runtime.getRuntime();
String cmdString = "./load_test.sh";
System.out.println(cmdString);
Process pr = rt.exec(cmdString);
BufferedReader input = new BufferedReader(new InputStreamReader(
pr.getErrorStream()));
String line = null;
while ((line = input.readLine()) != null)
{
System.out.println(line);
}
int exitVal = pr.waitFor();
The load_test script does this:
wget -O/dev/null --load-cookies cookies-$1.txt 'http://demo.mycompany.co.uk/userhome'
Even though I've run load_test.sh on my Mac from many different locations, the output of this Java program is:
./pcm_load_test.sh: line 2: wget: command not found
So, it seems that when spawned from Java, wget can't be called from a script?
I thought this might be a user-access issue so I tried:
sudo chmod a+rwx /usr/local/bin/wget
but this had no effect.
Any ideas why wget won't run from the script called from a Java program?
As mentioned by Elliott Frisch, and based on my own experience with running scripts on multiple OS via an application:
When executing a script via java code, you must make sure that the command you are trying to execute can be found. This generally requires the usage of one of two options:
Using a global environment path variable - when running a script programmatically, your code opens a shell instance and executes your script. The new shell instance has no preconfigured global environment path variable, which means you should add this configuration to the start of your script:
export PATH=${PATH}:/path/to/your/used/bin
Use the absolute path to your command - simply explicitly call your command with its full path in your script: /usr/local/bin/wget ........
As a side note - the error message in the OP states that the wget command cannot be found. An attempt to provide full read/write/execute permissions via chmod will, indeed, have no effect since the permissions do not help with providing a path to the command.
References:
PATH to WGET
Where to Set Environment Variables in Mac OS X
How to execute shell command from Java
I have a very simple ruby script that looks like this:
puts "Running test program"
ENV["TEST"] = "foo"
puts ENV["TEST"]
When I run this script from the command line it works as expected:
C:\Temp\rb-test>ruby foo.rb
Running test program
foo
What I need to do is to launch this script from a Java program. The Java program looks like this:
Path path = FileSystems.getDefault().getPath("c:", "temp", "rb-test");
ProcessBuilder pb = new ProcessBuilder("ruby.exe", "foo.rb").directory(path.toFile()).redirectErrorStream(true);
Process process = pb.start();
process.waitFor();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = bufferedReader.readLine();
while (line != null) {
System.out.println(line);
line = bufferedReader.readLine();
}
When I run the Java program from Eclipse I get the following output:
foo.rb:2:in `[]=': Invalid argument - ruby_setenv (Errno::EINVAL)
from foo.rb:2:in `<main>'
Running test program
In reality I am calling a larger Ruby script from a third party product (Vagrant), why changing the Ruby script is not an option.
Why is this happening? Can I get around it by modifying my Java code somehow?
Ruby version: ruby 1.9.3p0 (2011-10-30) [i386-mingw32]
Update: The java code actually works if I run it from a cmd window. It does not work when I run it from within Eclipse. Unfortunately this does not help much since I am working on a tool we will run from within Eclipse.
Update 2: If I start a cmd window from Eclipse, I get the same problem when I run the ruby script from within this cmd window. This leads me to believe there is some kind of permission issue. However, I cannot see any permission differences between the cmd I start through the start menu and the one started through Eclipse. Both are run as the same user and all security properties I can see for the process are identical.
Update 3: Tried the latest version of Ruby (2.0.0p247 (2013-06-27) [i386-mingw32]). Same behavior.
The problem was that when I started the Ruby script from Eclipse I had a different environment. Specifically, I had a CLASSPATH environment variable that looked really strange. I think the cause of this is the size of the CLASSPATH variable. It is really really long before being passed on to my sub process but within the sub process it is truncated and looks broken.
I am suspecting I am running into problems with the max size of the Windows environment block (see details here: http://blogs.msdn.com/b/oldnewthing/archive/2010/02/03/9957320.aspx). I will not investigate this further but have fixed my code to remove the CLASSPATH variable before starting the process.
Path path = FileSystems.getDefault().getPath("c:", "temp", "rb-test");
ProcessBuilder pb = new ProcessBuilder("ruby.exe","foo.rb").directory(path.toFile()).redirectErrorStream(true);
pb.environment().remove("CLASSPATH");
Process process = pb.start();
process.waitFor();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = bufferedReader.readLine();
while (line != null) {
System.out.println(line);
line = bufferedReader.readLine();
}
Had a similar issue running vagrant as part of this Wocker installation:
http://wckr.github.io/
The problem was my system environment PATH was too long. I trimmed out a load of cruft from it and vagrant (based on ruby) runs up fine.
I have a number of scripts that I run on Windows through cygwin.
These script files always require manual editing whenever I take a new sandbox.
Thus, I was thinking of writing a little Java UI app that will edit the scripts automatically based on a users UI settings.
I've read a few other posts regarding running a script file from Java but didn't see any on how to run them on Windows through cygwin.
Has anyone else done this or know of a previous post that they could refer me to?
If cygwin is on your path, you can execute it like any other external program from Java.
Note: You have to read the streams from parallel threads in real code! This is just a proof of concept for running a bash script through cygwin on windows!
Process process = Runtime.getRuntime().exec("bash -c ./script.sh");
InputStream inputStream = process.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
If you execute the Cygwin.bat file found in the Cygwin install directory you will see your session turns into a Cygwin session and you can then run all the commands you can in a cygwin session.
If you then add the cygwin/bin directory to your path, you can execute commands directly like a linux environment.
In my case I added the following to the end of my PATH system variable C:\cygwin64\bin, and I can now run bash and other commands directly like a normal session.