繁体   English   中英

命令行解释器如何工作?

[英]How do command-line interpreters work?

我一直认为操作系统上的进程有三个标准流: stdin, stdout, and stderr 我还认为像vim这样的文本编辑器通过在stdin并在stdout发送ANSI转义字符来工作。 但是,我对命令行解释器如何在这一案例中没有提到的观点如下:

当我运行命令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操作系统中的处理方式不同?)

任何使用c标准库的程序都可以使用函数isatty()来判断它是否正在与tty设备(也就是命令行)进行通信。 Bash可能检测到它正在与管道而不是tty通话,并且不会输出提示。

我更像是一个Python人而不是Java人(所以我告诉你的一切都是来自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。

处于交互模式并不意味着不使用标准流。 但在这种情况下,Bash最有可能以交互模式运行(它检测到它不直接与终端应用程序通信,因此它假设它以编程方式使用,因此不会打印欢迎横幅)。 在这种情况下,仍然使用标准流,只是没有输出任何内容。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM