0

Im using java to start a GNOME terminal process in linux and redirecting its input and output to my code. Below is a code.

        public static void main(String[] args) throws InterruptedException
    {
        // TODO Auto-generated method stub  /usr/bin/telnet
        try
        {
            String line, commandInput;
            Scanner scan =  new Scanner(new File("/home/Ashutosh/Documents/testfile"));
            ProcessBuilder telnetProcessBuilder = new ProcessBuilder("/bin/bash");///home/Ashutosh/Documents/tempScript");
            telnetProcessBuilder.redirectErrorStream(true);
            Process telnetProcess = telnetProcessBuilder.start();
            //Process telnetProcess = Runtime.getRuntime().exec("xterm");///home/Ashutosh/Documents/tempScript");
            BufferedReader input = new BufferedReader(new InputStreamReader(telnetProcess.getInputStream()));
            BufferedWriter output = new BufferedWriter(new OutputStreamWriter(telnetProcess.getOutputStream()));
            while(scan.hasNext())
            {
                commandInput = scan.nextLine();
                output.write(commandInput);
/*              if(commandInput.trim().equals("exit"))
                {
                    output.write("exit\r");
                }
                else
                {
                    output.write("((" + commandInput + ") && echo --EOF--) || echo --EOF--\r");
                }
*/              output.flush();
                line = input.readLine();
                while(line != null && !line.trim().equals("--EOF--"))
                {
                    System.out.println(line);
                    line = input.readLine();
                }
                if(line == null)
                    break;
            }
/*          Thread.sleep(500);
            output.write("/home/Ashutosh/Documents/testfile\r");
            Thread.sleep(500);
            output.flush();

            while((line = input.readLine())!= null)
                System.out.println(line);
            telnetProcess.destroy();
*/          //String s = input.readLine();
            //System.out.print(s + "\r\n");
            //s = input.readLine();
            //System.out.print(s + "\r\n");
        }

the contents of testfile which is bash script is

#!/bin/bash

ls -l
pwd
date
exit

and i also tried the following interactive script which takes input from user which i want to redirect from java code is given

#! /bin/bash
echo "Input any number form 0-3:"
read num
case $num in
  0) echo "You are useless";;
  1) echo "You are number 1";;
  2) echo "Too suspecious";;
  3) echo "Thats all man, got to go...!";;
  *) echo "Cant't u read english, this is wrong choice";;
esac
read
exit

my code stops at input.readLine(); im not sure but i think i am not able to redirect the output stream

output.write(commandInput);

command is executing well but did not write i intended to on the process redirected input, that is why it hangs at readLine();. If somebody have already solved please let me know the solution. From following link i tried to solve the issue but still no luck:

Java Process with Input/Output Stream

Thanks

Ashutosh

Community
  • 1
  • 1
Ashutosh
  • 397
  • 1
  • 7
  • 20

3 Answers3

2

readLine() read the contents of a line, without the newline at the end.

write() writes just the text, it doesn't add a new line.

Perhaps you want to add write("\n"); or use PrintStream or PrintWriter.

I imagine, your script is being sent as

#!/bin/bashls -lpwddateexit

which is a comment without a newline.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • hi Peter, even after adding "\n" or "\r" after reading command in string, nothing changes, im not sure what can be the problem? – Ashutosh Apr 27 '11 at 12:01
1

EDIT: Huge error, not adding the command to the ProcessBuilder!!

Why are you not just running your script as a Linux script? That is,

ProcessBuilder builder = new ProcessBuilder();
LinkedList<String> command = new LinkedList<String>();
command.add("/bin/bash");
command.add("/home/Ashutosh/Documents/testfile");
builder.command(command);

Process myProc = builder.start();

Also, I notice the variable is named 'telnetProcess' yet there is no invocation of telnet anywhere that I can see. Perhaps this is the problem?

EDIT: Added my suggestion below for the interactive script.

ProcessBuilder builder = new ProcessBuilder();
LinkedList<String> command = new LinkedList<String>();
command.add("/bin/bash");
command.add("/path/to/interactiveScript");
builder.command(command);

final Process myProc = builder.start();

// Java input goes to process input.
Thread inputParser = new Thread() {
  public void run() {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(myProc.getOutputStream()));
    String line = "";
    while(line != null) {
      line = br.readLine();
      bw.write(line);
      bw.newLine();
    }
  }
}.start();

// Process output must go to Java output so user can see it!
Thread outputParser = new Thread() {
  public void run() {  
    BufferedReader br = new BufferedReader(new InputStreamReader(myProc.getInputStream()));
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    String line = "";
    while(line != null) {
      line = br.readLine();
      bw.write(line);
      bw.newLine();
    }
  }
}.start();
  • i know its stupid name for object, but that has nothing to do with telnet, its just a plain simple test application where i want to test java process IO. In one of my application i need user to just call this java app which does all script running and getting all output to user without user intervention. – Ashutosh Apr 27 '11 at 11:37
  • In your code above, you are running /bin/bash from your Java application and sending stuff on your output stream in the hope that bash will read it from stdin and process it. I think first you should try the simpler option of what I suggested before, where you use the command "/bin/bash /home/Ashutosh/Document/testfile" to run the script and print out its output. Once this is done you can play around with bash's stdin processing. –  Apr 28 '11 at 02:56
  • Your second interactive script also needs to be handled differently. You have two effective threads of execution for the interactive script. First is the input from the user which Java has to pass down into its child process. To do this, you need to take input from System.in() and push it to Process.getOuputStream(). The same is for the reverse, when the child process prints something the Java program needs to read it in from Process.getInputStream() and output to System.out(). –  Apr 28 '11 at 02:59
1

hi guys sorry for late response, after some trials i got it working. I am simply letting the process completing its process and exit normally rather than forcefully and then the BufferedReader and BufferedWriter keeps the string buffers in RAM which i can read now after process exit with code 0.

public static void main(String[] args) throws InterruptedException
{
    // TODO Auto-generated method stub
    try
    {
        String line, commandInput;
        ProcessBuilder telnetProcessBuilder = new ProcessBuilder("/bin/bash");
        telnetProcessBuilder.redirectErrorStream(true);
        Process telnetProcess = telnetProcessBuilder.start();
        BufferedReader input = new BufferedReader(new InputStreamReader(telnetProcess.getInputStream()));
        BufferedWriter output = new BufferedWriter(new OutputStreamWriter(telnetProcess.getOutputStream()));
        commandInput = "ls -l\n";
        output.write(commandInput);
        output.flush();
        commandInput = "pwd\n";
        output.write(commandInput);
        output.flush();
        commandInput = "whoami\n";
        output.write(commandInput);
        output.flush();
        commandInput = "exit\n";
        output.write(commandInput);
        output.flush();
        while((line = input.readLine())!= null)
            System.out.println(line);
    }
}
Ashutosh
  • 397
  • 1
  • 7
  • 20