In Java, send commands to another command-line program
Asked Answered
W

4

10

I am using Java on Windows XP and want to be able to send commands to another program such as telnet. I do not want to simply execute another program. I want to execute it, and then send it a sequence of commands once it's running. Here's my code of what I want to do, but it does not work: (If you uncomment and change the command to "cmd" it works as expected. Please help.) This is a simplified example. In production there will be many more commands sent, so please don't suggest calling "telnet localhost".

    try
    {
        Runtime rt = Runtime.getRuntime();

        String command = "telnet";
        //command = "cmd";
        Process pr = rt.exec(command);

        BufferedReader processOutput = new BufferedReader(new InputStreamReader(pr.getInputStream()));
        BufferedWriter processInput = new BufferedWriter(new OutputStreamWriter(pr.getOutputStream()));

        String commandToSend = "open localhost\n";
        //commandToSend = "dir\n" + "exit\n";

        processInput.write(commandToSend);
        processInput.flush();

        int lineCounter = 0;
        while(true)
        {
            String line = processOutput.readLine();
            if(line == null) break;
            System.out.println(++lineCounter + ": " + line);
        }

        processInput.close();
        processOutput.close();
        pr.waitFor();
    }
    catch(Exception x)
    {
        x.printStackTrace();
    }
Witchcraft answered 20/5, 2010 at 20:37 Comment(2)
So you want an inter process communication solution for java?Flinger
It seems to me like telnet is writing its output to something other than the process's input stream, and java isn't capturing it. Is the Process.getInputStream() the only method to read what a process is outputting?Witchcraft
D
3

That looks OK, as it won't be producing that much output, but you should really read and write in separate threads so it doesn't fill up the buffer and block waiting you to read before you reach the next step.

So if it's reaching the point where you flush the command you send to it, find out whether the Windows telnet client supports receiving commands from standard input rather than a console by piping the text you're sending to its standard input to it in a command prompt.

For example, echo dir c:\ | cmd causes cmd to run, list the c: drive contents and exit, much the same behaviour as if you typed dir c:\ into the console. But echo open localhost | telnet causes telnet to clear the screen then exit, rather than behaving the same way as if you typed it into the console. As telnet needs to mask user input for passwords, it's quite likely that it's using the console API rather than reading from standard input. It's help doesn't list any command arguments to tell it to read from standard input, so maybe you need to use a telnet implementation which is better suited to scripting.

Derrick answered 20/5, 2010 at 20:48 Comment(3)
I agree. This is a simplified example to show my problem, so i kept it single threaded. Can you please explain what you mean by standard input vs. console and piping the text?Witchcraft
@Witchcraft Well, echo open localhost | telnet doesn't work but echo dir c: | cmd does, so I suspect strongly that Windows telnet client is using the console API to detect keypresses rather than reading its input stream.Derrick
I see this now. This is obviously the problem i'm running into. Do you have any idea how i can write to an application's console instead of the input stream?Witchcraft
S
3

It's not directly an answer to your question, but...

Instead of using Runtime.exec() you should use a ProcessBuilder and redirect stderr to stdout (ProcessBuilder.redirectErrorStream(true)). Otherwise your process could block if it writes something to stderr (Windows doesn't like it when the output of a process isn't read).

Saveall answered 20/5, 2010 at 20:46 Comment(3)
This is pretty close to a "direct answer" - you can start the process and read output from Process.getOutputStream() and write commands to Process.getInputStream()Dissonant
I tried this, and I get the same problem. The output from telent is not read. Program executes without printing anything.Witchcraft
A small correction to what D.Shawley wrote, from the point of view of your code in Java, you actually read from Process.getInputStream() and write to Process.getOutputStream()... the naming is confusing, they were apparently named from a different point of view...Alienism
D
3

That looks OK, as it won't be producing that much output, but you should really read and write in separate threads so it doesn't fill up the buffer and block waiting you to read before you reach the next step.

So if it's reaching the point where you flush the command you send to it, find out whether the Windows telnet client supports receiving commands from standard input rather than a console by piping the text you're sending to its standard input to it in a command prompt.

For example, echo dir c:\ | cmd causes cmd to run, list the c: drive contents and exit, much the same behaviour as if you typed dir c:\ into the console. But echo open localhost | telnet causes telnet to clear the screen then exit, rather than behaving the same way as if you typed it into the console. As telnet needs to mask user input for passwords, it's quite likely that it's using the console API rather than reading from standard input. It's help doesn't list any command arguments to tell it to read from standard input, so maybe you need to use a telnet implementation which is better suited to scripting.

Derrick answered 20/5, 2010 at 20:48 Comment(3)
I agree. This is a simplified example to show my problem, so i kept it single threaded. Can you please explain what you mean by standard input vs. console and piping the text?Witchcraft
@Witchcraft Well, echo open localhost | telnet doesn't work but echo dir c: | cmd does, so I suspect strongly that Windows telnet client is using the console API to detect keypresses rather than reading its input stream.Derrick
I see this now. This is obviously the problem i'm running into. Do you have any idea how i can write to an application's console instead of the input stream?Witchcraft
P
3

If you want to control a telnet session programatically from Java, you might be able to use this Java telnet library... you can do the same things (open connections, send username/password, send commands and receive results) but without actually spawning a separate process.

Piccalilli answered 20/5, 2010 at 20:54 Comment(1)
The telent was simply for an example. I need this to be generic so i can execute any executable and write commands to itWitchcraft
D
1

You may take a look at the Telnet Ant task you can call it directly in your code with out having to use a build.xml file.

You can also take a look at the source code and see how they do it.

Dis answered 20/5, 2010 at 20:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.