我的印象是,操作系统上的过程有三个标准流: stdin, stdout, and stderr. 。我还认为文本编辑器像VIM作品一样,通过输入 stdin 并发送ANSI逃生角色 stdout. 。但是,我对命令行解释者如何在这种情况下没有坚持的看法:

当我运行命令时 C:\cygwin\bin\bash.exe, ,我被提示:

Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Users\masson>C:\cygwin\bin\bash.exe
bash-3.2$ 

...但是,当我使用以下片段在Java中运行它时,stdin流是空的:

ProcessBuilder pb = new ProcessBuilder("C:\\cygwin\\bin\\bash.exe");
pb.redirectErrorStream(true);
Process proc = pb.start();
final InputStream in = proc.getInputStream();

new Thread(new Runnable() {
  public void run() {
    // Blocks forever...
    in.read(new byte[1024]);
  }
}).start();

这里发生了什么?有人告诉我bash.exe正在交互式模式下运行。这是否意味着未使用标准流?我仍然如何处理这些程序,最终如何实现自己的cmd.exe版本?我认为我不了解有关命令行的工作方式的基本知识...

(对讨论相关主题的文章的任何链接都将不胜感激。我没有太多运气搜索。哦,最后一个问题,标准流在Windows中的处理方式与大多数类似Unix的操作系统有所不同吗?)

有帮助吗?

解决方案

处于交互式模式并不意味着未使用标准流。但是在这种情况下,bash最有可能运行 - 相互作用的模式(它检测到它不是直接与终端应用程序交谈,因此假设它是通过编程方式使用的,因此不打印欢迎横幅)。在这种情况下,仍然使用标准流,只是什么都没有输出。

正如Ergosys指出的那样,您不能真正依靠 in.read(new byte[1024]) 在阅读完整的1024个字节之前返回,尽管可以假设它可能可以 - 但是,它肯定不会在阅读至少一个字节之前返回,我认为这是问题所在 - 您甚至没有得到输出的一个字节。

尝试将“ -i”传递给bash以使其以交互式模式运行。

其他提示

使用C标准库的任何程序都可以判断它是否正在使用function iSatty()与TTY设备(又称命令行)交谈。 Bash可能检测到它是在与管道而不是TTY交谈,并且不会输出提示。

我比一个爪哇人更重要(所以我告诉你的一切都是javadoc的猜测),但是看来您正在设置一个多进程的僵局。

in.read(new byte[1024]); 直到读取1024字节的数据和 bash.exe 在停止等待输入之前,不会输出整个1024字节。 (为此,使用 proc.getOutputStream() 并给它提供一些响应的命令。)

结果,您会让Java等待Bash做出反应和bash等待Java做出反应,并且都完全满足于等到宇宙死亡而不会感到无聊或疲倦。

我的建议是使用 in.available() 在每次打电话之前 in.read() 避免阻塞。这样,您可以在馈送数据之间来回切换并将其拉出而不会被卡住。

实际上,将其包裹在一个 BufferedReader.

评论更新: 同样,当bash等工具检测到stdin不是终端时(请参阅ISATTY系统调用), 他们缓冲 在巨大的(4K或更多)块中,假设输入是非交互的。我不确定是否会有所帮助,但是尝试使用-i标志开始bash。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top