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
Related
I am having a bash script file which I am calling using the source command in a shell and is setting a number of environment variables. Then I can use all the tools the environment variables are setting.
Now I want to do the same in Java by the use of:
static Runtime run = Runtime.getRuntime();
Process pr = run.exec(command);
pr.waitFor();
I know that source is an internal command and I can not call it from Java.
Is there any other way to set the enviroment variable in that file from java in order to be able to use them in my code later for calling other commands?
Thank you in advance!
Process pr = new ProcessBuilder("/bin/bash", "-c", ". env.sh; " + command).start();
Try something like this, where you both source the script and execute a subsequent command in the same shell process. Effectively you source the script every time you want to execute a command.
I'm beginner at java and have some problems. I've read several topics about this theme but none of them worked for me. Here is my code:
try
{
Console console = System.console();
String command;
while(true)
{
command = console.readLine("Enter input:");
Process proc = Runtime.getRuntime().exec(command);
// Read the output
BufferedReader reader =
new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = "";
while((line = reader.readLine()) != null) {
System.out.print(line + "\n");
}
proc.waitFor();
}
}
catch(Exception e) {}
So what I'm trying is to make a java program and run terminal commands in it(I'm using linux). This program works with commands like "ls" "ps ef" and others but it doesn't work when I type "cd". I know that cd makes different process and should be used this way: "Runtime.exec(String command, String[] envp, File dir)". My questions is:
How to make my program run all kinds of terminal commands? Sorry if question sound silly. Thank you.
The cd command is a shell built-in command. There is no shell when you run a command via exec(...). Indeed, if you try to find a cd command in any of your system's bin directories, you won't find one ... because it is impossible to implement as a regular command.
If you are trying to use cd to change the current directory for the JVM itself, that won't work because a command can only change the current directory of itself and (after that) commands that it launches itself. It can't change its parent processes current directory.
If you are trying to use cd to change the current directory for subsequent commands, that won't work either. The context in which you set the current directory ends when the command finishes.
In fact, the right way to change the directory for a command run using exec is to set it via the ProcessBuilder API itself.
How to make my program run all kinds of terminal commands?
You can't. Some of the "terminal commands" only make sense as shell commands, and that means you need a shell.
I suppose, you could consider emulating the required behaviour in your Java code. That would work for cd ... but other commands are likely to be more difficult to cope with.
(For what it is worth, it is possible to implement a POSIX compatible shell in Java. It is just a LOT of work.)
you've actually got to run the console you want to use (ie sh, csh, bash, etc) and then use the process OutputStream to feed in commands
I think the Problem is not your Code, the command is the problem...
what do you want to see if your command is cd ??
In Background it changes the path but you get nothing back.
Changing the Directory is not processing any output.
This worked for me:
Runtime.getRuntime().exec(new String[]{ "/system/bin/sh", "-c", "ls -l" } );
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.
I want to create database import using .sql file with java then I found a code something like this
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec(new String[]{"/bin/bash","-c","mysql -p -h localhost test < "+fileName.toString()});
I'm using netbean to run my desktop app. then I got this error message
java.io.IOException: Cannot run program "/bin/bash": CreateProcess error=2, The system cannot find the file specified
my question is where can i find /bin/bash path? or what should i do...
should I configure something like env variable path?
I'm running this on windows
solution is replacing /bin/bash with cmd.exe and -c to /c, but when I execute the program I got this message appear on my console
'mysql' is not recognized as an internal or external command,
operable program or batch file.
though I already setup mysql directory in PATH environment variable of Windows
/bin/bash doesn't exist on Windows. Try replacing /bin/bash with cmd.exe, and replacing the switch -c with /c.
EDIT: if your Java program appears to complete successfully but no data has been written, it is quite possible that your Java program didn't wait for the mysql process to complete. Try adding pr.waitFor();.
Alternatively, mysql could be reporting an error message or writing something to its standard output or standard error streams. If this is the case, you'll need to either:
read the offending stream(s), or
if you're sure you can ignore it, redirect the offending stream(s) to NUL.
You can redirect standard output to NUL by adding >NUL to the command line, and redirect standard error to NUL by adding 2>NUL.
I woudn't recommend discarding the output/error messages. If there's an error, how will you know about it? However, it's difficult to properly handle the standard output and standard error streams of processes generated using Runtime.getRuntime().exec(...). Instead, I would use a ProcessBuilder. A ProcessBuilder allows you to redirect the mysql process's standard error into the standard output, which makes reading the output from both streams a bit easier (you don't need two separate threads).
ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "mysql -p -h localhost test < "+fileName.toString());
builder.redirectErrorStream(true);
Process pr = builder.start();
// Get mysql process's standard output/error.
InputStream is = pr.getInputStream();
// Now read from it and write it to standard output.
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
}