在Java中,向另一个命令行程序发送命令

10

我在Windows XP上使用Java,希望能够向另一个程序发送命令,例如telnet。 我不想简单地执行另一个程序。我想在它运行时执行它,并发送一系列命令。 这是我想要做的代码,但是它不起作用: (如果取消对"cmd"命令的注释并将其更改为"telnet",则可以按预期工作。 请帮助我。) 这是一个简化的示例。在生产中,将发送许多更多的命令,因此请不要建议调用"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();
    }

所以你想要一个Java的进程间通信解决方案? - Justin
对我来说,看起来telnet将其输出写入了进程的输入流之外的某些地方,而Java并没有捕获它。Process.getInputStream()是读取进程输出的唯一方法吗? - bradvido
4个回答

3

这并不是直接回答你的问题,但是...

与其使用 Runtime.exec(),你应该使用ProcessBuilder 并将 stderr 重定向到 stdout (ProcessBuilder.redirectErrorStream(true))。否则,如果进程写入了一些东西到 stderr,它可能会被阻塞(Windows 不喜欢一个进程的输出没有被读取)。


这相当接近于“直接回答” - 你可以启动进程并从Process.getOutputStream()读取输出,同时将命令写入Process.getInputStream(). - D.Shawley
我尝试了这个,但是遇到了同样的问题。Telnet 的输出没有被读取。程序执行时没有打印任何内容。 - bradvido
3
从Java代码的角度来看,对于D.Shawley所写的内容,需要进行小修正,实际上您是从Process.getInputStream()读取并将数据写入Process.getOutputStream()…命名方式有点令人困惑,这似乎是从不同的角度进行命名的… - John J. Camilleri

3
那看起来还不错,因为它不会产生太多输出,但你应该真正阅读和写入分开线程,这样它就不会填满缓冲区并阻塞等待你在到达下一步之前读取。

因此,如果它达到了刷新发送给它的命令的点,请查找Windows telnet客户端是否支持从标准输入接收命令,而不是通过控制台将发送的文本管道传输到命令提示符中。

例如,echo dir c:\ | cmd会导致cmd运行,列出c:驱动器内容并退出,与您在控制台中键入dir c:\的行为相同。但是echo open localhost | telnet会导致telnet清除屏幕然后退出,而不是像在控制台中键入它那样行为相同。由于telnet需要掩盖密码的用户输入,很可能它正在使用console API而不是从标准输入读取。它的帮助没有列出任何命令参数来告诉它从标准输入读取,因此可能需要使用更适合脚本编写的telnet实现。

我同意。这只是一个简化的例子,以展示我的问题,所以我保持了单线程。您能否解释一下标准输入与控制台之间的区别以及如何通过管道传输文本? - bradvido
@bradvido 好的,“echo open localhost | telnet”不起作用,但“echo dir c: | cmd”可以,因此我强烈怀疑Windows telnet客户端正在使用控制台API来检测按键,而不是读取其输入流。 - Pete Kirkham
我现在明白了。很显然这就是我遇到的问题。你有什么办法可以将内容写入应用程序的控制台而不是输入流吗? - bradvido

3
如果你想从Java中以编程方式控制telnet会话,你可能可以使用这个Java telnet库... 你可以做同样的事情(打开连接、发送用户名/密码、发送命令并接收结果),但不需要实际上生成一个单独的进程。

这个 telnet 只是一个例子。我需要它是通用的,这样我就可以执行任何可执行文件并向其写入命令。 - bradvido

1

你可以查看一下Telnet Ant任务,你可以直接在代码中调用它,而不必使用build.xml文件。

你也可以查看一下源代码,看看他们是如何做到的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接