Executing Shell Scripts from Java, Shell scripts having read operation - java

I have a Shell Scripts that read the Input
#!/bin/bash
echo "Type the year that you want to check (4 digits), followed by [ENTER]:"
read year
echo $year
I'm executing this shell scripts using JAVA APi
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "/junk/leaptest.sh");
final Process process = pb.start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
System.out.println("Program terminated!");
In the Java Console I can see the Output
Type the year that you want to check (4 digits), followed by [ENTER]:
Now the Actual Problem in How to pass the values to the Shell Scripts in my scripts how the varialble "year" can be read
I have edited the code as per the suggestion but doesn't work where we correct it
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", "/junk/leaptest.sh");
final Process process = pb.start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
/*
* OutputStream os = process.getOutputStream(); PrintWriter pw = new
* PrintWriter(os);
*/
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
while ((line = br.readLine()) != null) {
System.out.println(line);
// pw.println("8999");
bw.write("2012");
}
System.out.println("Program terminated!");

You can use the OutputStream of the Process class:
OutputStream os = process.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.println("1997");
What you write to this output stream will become the input stream of the shell script. So read year will read 1987 to the year variable.
EDIT:
I also tried it out and I've managed to find the problem. The 1997 string hasn't reached the script, beacuse PrintWriter buffers the data that was written to it. You either have to flush the PrintWriter stream after the println() with pw.flush() or you have to set the auto-flush property to true upon creation:
PrintWriter pw = new PrintWriter(os, true);
Here is the complete code that was working fine for me:
leaptest.sh:
#!/bin/bash
echo "Type the year that you want to check (4 digits), followed by [ENTER]:"
read year
echo $year
Test.java:
import java.io.*;
class Test {
public static void main(String[] args) {
try {
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "leaptest.sh");
final Process process = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
PrintWriter pw = new PrintWriter(process.getOutputStream());
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
pw.println("1997");
pw.flush();
}
System.out.println("Program terminated!");
} catch(Exception e) {
e.printStackTrace();
}
}
}
Output:
$ java Test
Type the year that you want to check (4 digits), followed by [ENTER]:
1997
Program terminated!

To pass values from java program that executes script to the script use command line arguments. If you want to send information back from script to java program print the value in script, read the script's STDOUT in java program and parse it.
You really almost there. Now you are reading the script output (into while loop) but you are just printing it. Parse the output and do what you need with it.

Think you should parse input stream is to extract your values. Parse it by lines.

You want to set up an OutputStream using getOutputStream aswell, to be able to write data from your Java program into the process.
public abstract OutputStream getOutputStream()
Gets the output stream of the subprocess. Output to the stream is piped into the standard input stream of the process represented by
this Process object.

I think this should work. You need to handle your subprocess' output stream. Read the docs.
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
bw.write("2012");

Related

BufferedReader print input while reading in realtime

my java method looks like this:
private String executeCommand(String command) {
StringBuffer output = new StringBuffer();
String line = "";
Process proc;
try {
proc = Runtime.getRuntime().exec(command);
InputStream inputStream = proc.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
proc.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
If I send small commands like "ls -l" it executes the command and print the results. But I need this function to read the output from an application wich will run for days and it will print frequently output while running. So I can't wait until the application is "done", I need the output in realtime. Anyone knows how to print the output without delay? thanks for help..
The simplest way is to redirect the output of the command directly to a file:
ls -l > ./ls.output
In this case you don't need to wait the end of the command. It will be the operating system to handle the output redirection to a file.
If you need also to write the output for the error you need a command like the following:
ls -l > ./ls.output 2> ./ls.err
where ./ls.output is the normal output and ./ls.err is the output for errors

Why does BufferedReader fail if BufferedWriter is still open?

I am trying to run a .exe file from a java application and would like to be able to use it (for now) like a terminal where i can write to the .exe then read back from it before writing it again.
My issue is that the code only works when the writer is closed before the reader attempts to read from the inputstream.
String line = "", prev = "";
Scanner scan = new Scanner(System.in);
ProcessBuilder b = new ProcessBuilder("myexe");
b.redirectErrorStream(true);
Process p = b.start();
OutputStream stdin = p.getOutputStream();
InputStream stdout = p.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
System.out.println ("->");
while (scan.hasNext()) {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
String input = scan.nextLine();
if (input.trim().equals("exit")) {
writer.write("C");
} else {
writer.write(input);
}
writer.flush();
//writer.close();
while ((line = reader.readLine ()) != null) {
System.out.println ("[Stdout] " + line);
if (line.equals(prev)){
break;
}
prev = line;
}
reader.close();
}
So my question is, am i doing something wrong with the ProcessBuilder? I have read about not reading the output correctly can cause the system to hang. But this doesnt explain why it hangs when the writer is still open?
The issue was actually with my C compiled .exe. When it was running, the application was printing an output, therefore working in cmd terminal however i had not flushed the buffer after each command sent. Once i had done this, the java application would recognise each command as they were sent.

How to input the password while executing cmd through java

I want to write a java program to retrieve the status of all the services running on different servers (approx 20). For this i am using SC command, i am able to do so using the java program. But now i am stuck in a situation where i want to run the SC command as a different user by using RUNAS, the problem that i am facing is that i am not able to input the password once the command has been executed for the first time. Following is the code that i am using :-
String[] command = new String[3];
command[0] = "cmd";
command[1] = "/c";
command[2] = "runas /noprofile /user:domain\\admin \"sc \\\\serverName queryex type= service state= all\"";
Process p = Runtime.getRuntime().exec(command);
PrintWriter writer = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(p.getOutputStream())), true);
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = reader.readLine();
while (line != null) {
new PrintWriter(p.getOutputStream(),true).println("AdminPassword");
System.out.println(line);
line = reader.readLine();
}
BufferedReader stdInput = new BufferedReader(newInputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
String Input;
while ((Input = stdInput.readLine()) != null) {
System.out.println(Input);
}
String Error;
while ((Error = stdError.readLine()) != null) {
System.out.println(Error);
}
But i am not been able to print the states of all the services. I am not not sure after providing the password whether i need to capture some other stream or else??
Any help on this?
Thanks
In your while (line != null) loop you open a new PrintWriter for each line you read. You print the admin password to these writers, but never close or flush them.
Try the PrintWriter writer you created above, and flush() it after writing the password, otherwise it will still be in the buffer.
You also create several BufferedReader on the inputStream of the Process, which might interfere with each other.
So: create only one reader resp. writer for the inputStream, errorStream and outputStream of the Process.

Running an interactive shellscript using java

I am writing a javacode to call a interactive shellscript and using process builder for calling shellscript. I know that to pass parameters to this shell script i have to take its inputstream to check it's output and need to use output stream to pass command to it. My question is that how would I know using Input Stream that it's prompting for entering values ?
My code :
ProcessBuilder pb2=new ProcessBuilder("/home/abhijeet/sample1.sh","--ip="+formobj.getUpFile().getFileName(),"--seqs="+seqs);
script_exec = pb2.start();
OutputStream in = script_exec.getOutputStream();
InputStreamReader rd=new InputStreamReader(script_exec.getInputStream());
pb2.redirectError();
BufferedReader reader1 =new BufferedReader(new InputStreamReader(script_exec.getInputStream()));
StringBuffer out=new StringBuffer();
String output_line = "";
while ((output_line = reader1.readLine())!= null)
{
out=out.append(output_line+"/n");
System.out.println("val of output_line"+output_line);
//---> i need code here to check that whether script is prompting for taking input ,so i can pass it values using output stream
}
Is there any way to know directly that script is waiting for an input from user?
Read the process output stream and check for the input prompt, if you know the input prompt, then put the values to process inupt stream.
Otherwise you have no way to check.
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectErrorStream(true);
BufferedReader b1 = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedWriter w1 = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
String line = "";
String outp = "";
while ((line = b1.readLine()) != null) {
if (line.equals("PLEASE INPUT THE VALUE:")) {
// output to stream
w1.write("42");
}
outp += line + "\n";
}
...
UPD: for your code it should be something like that
ProcessBuilder pb2=new ProcessBuilder("/home/ahijeet/sample1.sh","--ip="+formobj.getUpFile().getFileName(),"--seqs="+seqs);
script_exec = pb2.start();
OutputStream in = script_exec.getOutputStream();
InputStreamReader rd=new InputStreamReader(script_exec.getInputStream());
pb2.redirectError();
BufferedReader reader1 =new BufferedReader(new InputStreamReader(script_exec.getInputStream()));
StringBuffer out=new StringBuffer();
String output_line = "";
while ((output_line = reader1.readLine())!= null)
{
out=out.append(output_line+"/n");
System.out.println("val of output_line"+output_line);
//---> i need code here to check that whether script is prompting for taking input ,so i can pass it values using output stream
if (output_line.equals("PLEASE INPUT THE VALUE:")) {
// output to stream
in.write("42");
}
}

How I run a console application from a java console?

I am messing with Runtime.getRuntime(), but I don't think it really what I want.
I want something that has both user input, and output that goes to stdout. I would like a whole seperate program to get launched, basically.
Grae
Doing this:
Process process = Runtime.exec( "somecommand.exeorwhatever" );
Will run a completely separate process. Then you can use:
InputStream in = process.getInputStream();
InputStream err = process.getErrorStream();
OutputStream out= process.getOutputStream();
You can use Process created with ProcessBuilder.start() method and use its input and output streams.
Here is simple example:
public static void main(String[] args) throws Exception {
String[] processArgs = new String[]{"ping","google.com"};
Process process = new ProcessBuilder(processArgs).start();
BufferedReader in = new BufferedReader(new InputStreamReader(
//I'am using Win7 with PL encoding in console -> "CP852"
process.getInputStream(), "CP852"));
String line;
while ((line = in.readLine()) != null)
System.out.println(line);
in.close();
System.out.println("process ended");
}

Categories

Resources