Can any body help me with how to compile a bash script as part of a java program. I am writing a simple java program that i want to use to invoke bash script commands.
my java code looks like the following:
try{
Process p = Runtime.getRuntime().exec("myscript.sh");
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null){
System.out.println(line);
}
}
catch(IOException e){
System.out.println(e.getMessage());
}
and the "mysrcipt.sh" file is a simple script that contains the following lines
!/bin/bash
echo "enter your input followed by [ENTER]:"
read -e choice
echo $choice
My problem is, the program waits for an input at the read command in the script even if i enter multiple lines and press enter several times.
You can use:
Process p = Runtime.getRuntime().exec("bash_script.sh");
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
// use bash script line output
}
It would be helpful to see some code showing what you're trying to accomplish.
Executing bash script in Java can be done using something like the following...
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("YOUR COMMAND STRING");
List<String> lines = IOUtils.readLines(process.getInputStream());
Runtime.exec() is what you need to execute your bash script, but be aware there are a few pitfalls. I found this to be a good article when starting to call external scripts.
It is written for a windows platform, but a lot of what is discussed is relevant to *nix as well.
See also this question.
Related
I want to run multiple commands in the linux terminal and that will be one like as follows:
1. I will run suppose torch and i wrote th command and it opened the torch promt.
2. Now if i execute next command from java then it will run in the torch promt of the linux terminal.
you can take another example like:
1. At fist i will run python in the linux terminal from java.
2. Then run 1+1 or anything in the python interpreter from java.
So here my second command is dependent on the first command. I want to run the commands in the terminal in a sequential way.
Edit: Another approach will do.Suppose i have a python interpreter running in linux terminal and now i want to execute a command from java that will run in the python interpreter of that particular opened linux terminal. Can i do that??
I have tried to to run a command using this:
String line;
try
{
String execstr= "th"; //It opens the torch promt in linux terminal.
Process p = Runtime.getRuntime().exec(execstr);
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
/*if((line= input.readLine())==null)
System.out.println("blank");*/
while ((line = input.readLine()) != null)
{
System.out.println(line);
}
input.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
But now after this command how can i run a command from java in the promt that means i want it interactively ??
So how can i save the state of the previous command and use it for the next command??
Use p.getOutputStream() to get a stream into which you can write the desired input for the program you run. (I know, the naming is a bit confusing).
Just the relevant part:
Process p = Runtime.getRuntime().exec(execstr);
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
OutputStream ops = p.getOutputStream();
ops.write("echo hello world".getBytes());
ops.close();
while ((line = input.readLine()) != null)
{
System.out.println(line);
}
input.close();
I am using cygwin to get unix environment on windows.
I have some shell script that run on cygwin to perform syncing works and other things. I want to executes these script through java code.
Also during executing of scripts on cygwin , certain information is displayed on terminal by using simple echo command.. I want to show all that information in my application.
How can I do this??
Use the Runtime class to run Cygwin. This is very brittle, and dependent upon your setup, but on my machine I would do:
Runtime r = Runtime.getRuntime();
Process p = r.exec("C:\\dev\\cygwin\\bin\\mintty.exe --exec /cygpath/to/foo.sh");
Then wait for the Process to complete, and get a handle to it's InputStream objects to see what was sent to stdout and stderror.
The first part of the command is to run cygwin, and the second is to execute some script, or command (using -e or --exec). I would test this command on the DOS prompt to see if it works first before cutting any code. Also, take a look at the options available by doing:
C:\dev\cygwin\bin\mintty.exe --help
Also from within the DOS prompt.
EDIT: The following works for me to print version information
public class RuntimeFun {
public static void main(String[] args) throws Exception {
Runtime r = Runtime.getRuntime();
Process p = r.exec("C:\\dev\\cygwin\\bin\\mintty.exe --version");
p.waitFor();
BufferedReader buf = new BufferedReader(
new InputStreamReader(
p.getInputStream()));
String line = buf.readLine();
while (line != null) {
System.out.println(line);
line = buf.readLine();
}
}
}
Unfortunately, can't seem to get it working with --exec, so you're going to have to do some more research there.
You can use something like this
String cmd = "ls -al";
Runtime run = Runtime.getRuntime();
Process pr = run.exec(cmd);
pr.waitFor();
BufferedReader buf = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = "";
while ((line=buf.readLine())!=null) {
System.out.println(line);
}
p.s. this doesn't handle errors
I need to run the Oracle EXP command through a Java program and print somewhere the command output.
The EXP command is correct, the dump file is created correctly when I execute my Java code, but I'm experiencing some issues to get the output.
This is an snippet very similar to the one I'm using to read the output:
String line;
String output = "";
try {
Process p = Runtime.getRuntime().exec(myCommand);
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
output += (line + '\n');
}
input.close();
}
catch (Exception ex) {
ex.printStackTrace();
}
System.out.println(output);
As I said, the command is correctly executed (verified through the generated dump file), but nothing appears on my console and my Java programs doesn't terminate either.
The same code works perfectly if I use another command, as "ls -l" instead of "exp ...".
Maybe exp is writing to standard error output rather than standard output.
Try to use p.getErrorStream() instead of getInputStream()
As a_horse_with_no_name said, it might be that the error stream buffer is full and thus is blocking the programm execution.
Either try to start a Thread to also read the error stream or use the ProcessBuilder class to redirect the error stream to stdout (which you already read).
I am trying to execute a program from the Java code. Here is my code:
public static void main(String argv[]) {
try {
String line;
Process p = Runtime.getRuntime().exec(new String[]{
"/bin/bash", "-c", "executable -o filename.txt"});
BufferedReader input = new BufferedReader(
new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
}
input.close();
} catch (Exception err) {
err.printStackTrace();
}
}
My OS is Mac OS X 10.6.
Now, the executable I am trying to run is supposed to spit the output to filename.txt. If I take this command and run it on the terminal, it works fine and the filename.txt gets populated also. But, from my java program the file is not created.
if instead I use executable > filename.txt then the filename.txt is created but is empty. Not sure what's wrong here. The executable I am trying to run is Xtide (if that helps).
I would really appreciate any help I can get.
Thanks,
You cannot redirect output to file and read the output in java. It's one or the other. What you want is this:
Process p = Runtime.getRuntime().exec(new String[]{
"/bin/bash", "-c", "executable -o filename.txt"});
p.waitFor();
BufferedReader input = new BufferedReader(
new InputStreamReader(new FileInputStream("filename.txt")));
while ((line = input.readLine()) != null) {
System.out.println(line);
}
The main changes are:
p.waitFor(), since process execution is asynchronous, so you have to wait for it to complete.
The data is read from the file rather than from the output of the process (since this will be empty.)
The answer from mdma works (and I voted it up), but you might also want to consider the version where you do read the output stream directly from executable:
Process p = Runtime.getRuntime().exec(new String[]{
"/bin/bash", "-c", "executable"});
p.waitFor();
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream())_;
while ((line = input.readLine()) != null) {
System.out.println(line);
}
Correct me if I am wrong, but the symptoms are as follows:
exec("/usr/bash", "-c", "executable > filename.txt") creates an empty file.
exec("/usr/bash", "-c", "executable -o filename.txt") does not create a file.
One or both of the above gives an exit code of 255 when you look at it.
When you run the command from the command line as executable -o filename.txt or executable > filename.txt it works as expected.
In the light of the above, I think that the most likely cause is that /bin/bash is not finding the executable when you launch it from Java. The fact that the first example does create an empty file means that /bin/bash is doing something. But if you try to run
$ unknown-command > somefile.txt
from a bash shell prompt you will get an error message saying that the command cannot be found and an empty "something.txt" file. (You would not see the error message in your Java app because it is being written to stderr, and you are not capturing it.) The reason that the empty "something.txt" file is created is that it is opened by the shell before it attempts to fork and exec the "executable".
If this is the problem, then the simple solution is to use the absolute pathname for the executable.
Also, if you are not doing any command line redirection or other shell magic, there is no need to run the executable in a new bash instance. Rather, just do this:
Process p = Runtime.getRuntime().exec("executable", "-o", filename.txt");
then wait for the process to complete and check the exit code before trying to read the file contents.
I need to run a couple of other programs from my own Java program, basically I need to run these command line statements.
svn log --xml -v > svn.log
and
java -jar example.jar arg1 arg2
and I need to use the text outputs written to the console from these programs in my own program. I've tried Runtime.getRuntime().exec() with the svn, but it doesn't seem to be doing anything because it doesn't make a svn.log file. Also both programs need to be called in different places, the svn line needs to be called from inside one folder and the java line needs to be called from another.
Any ideas on how to go about this? If this is not possible in Java, is there a way to do it in C#?
Thanks
Here:
ProcessBuilder processbuilder
try
{
processbuilder.directory(file);
processbuilder.redirectErrorStream(true);
process = processbuilder.start();
String readLine;
BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream()));
// include this too:
// BufferedReader output = new BufferedReader(new InputStreamReader(process.getErrorStream()));
while((readLine = output.readLine()) != null)
{
m_Logger.info(readLine);
}
process.waitFor();
}
I've used something similar. You'll actually want to do something with the readLine. I just copied and pasted from code where I didn't care what it said.
The redirection > (like the pipe |) is a shell construct and only works when you execute stuff via /bin/sh (or equivalent). So the above isn't really going to work. You could execute
/bin/sh -c "svn log --xml -v > svn.log"
and read svn.log.
Alternatively, you can read the output from the process execution and dump that to a file (if you need to dump it to a file, or just consume it directly as you read it). If you choose this route and consume stdout/stderr separately, note that when you consume the output (stdout), you need to consume stderr as well, and concurrently, otherwise buffers will block (and your spawned process) waiting for your process to consume this. See this answer for more details.
instead of piping in your command, just let it print to standard output and error output. You can access those streams from your process object that is returned from exec.
For the svn stuff use java SVNKit API.
Seeing your two commands, why don't you do it directly from Java, without executing ? You could use SVNKit for the svn part, and include directly the jars in your classpath.
Try this
public static void main(String[] args) {
try {
// Execute a command with an argument that contains a space
System.out.println(args[0]);
String[]commands = new String[]{"svn", "info", args[0]};
Process process = Runtime.getRuntime().exec(commands);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder builder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
}
String result = builder.toString();
System.out.println(result);
}catch(Exception e){
System.out.print(e);
}
}