在前一个命令写入STDOUT时在STDIN中键入另一个命令是否安全?


21

也许以前已经回答了这个问题,欢迎您链接到另一个答案...

如果我执行一个shell命令(在一个bashshell中),如下所示:

make

然后,当输出make是通过从滚动STDOUT的的make命令,如果我输入make check并按enter之前的第一个命令执行完毕,当make命令终于完成下一个命令make check将选择权并运行。

我的问题很简单:

  1. 这危险吗?
  2. 这种紧急输入是否有潜在的意外行为?
  3. 为什么这样做会起作用?

2
1.希望不是...我已经这样做好多年了!
约翰·史密斯

Answers:


20

它的工作方式与之相同,因为Unix是全双工的。正如Ritchie在UNIX分时系统:回顾中所说:

全双工终端I / O与预读功能在一起看似微不足道,但一旦使用就产生了惊人的变化。即使程序通常以行而不是单个字符与用户通信,但全双工终端I / O意味着即使系统正在回退,用户也可以随时键入,而不必担心丢失或乱写字符。使用预读功能,无需等待对每一行的响应。一位优秀的打字员在开始每一行之前都不得不暂停,这令他感到沮丧。对于任何知道他想说什么的人,如果必须逐位而不是全速输入信息,那么任何反应迟钝都会在心理上被放大。

[结束报价]

话虽这么说,有些现代程序会吃光或丢弃任何预先输入的内容。sshapt-get是两个例子。如果您在运行时键入内容,则可能会发现输入的第一部分已消失。可以想象这可能是个问题。

ssh remotehost do something that takes 20 seconds
mail bob
Dan has retired. Feel free to save any important files and then do
# ssh exits here, discarding the previous 2 lines
rm -fr *
.

因此,在bash fork()s和execs命令之后,第一个命令是否仍附加STDIN在bash shell的上?听起来答案是否定的,bash似乎正在缓冲下一条命令。那是对的吗?
111 ---

除非您告诉外壳重定向命令的标准输入,否则该命令将与外壳具有相同的标准输入。您输入的任何内容都会被读取它的第一个进程读取。在运行命令时,shell故意不尝试读取任何内容,而是等待命令停止。如果使用将命令放在后台,事情会变得更加复杂&
Mark Plotnick

那么是以STDINfifo的方式处理的吗?我猜想,除非庆典的子进程显式地关闭其继承文件句柄,STDIN那么它可能仍然附加打字看?
111 ---

是的,所有端子输入均通过FIFO处理。不确定我是否理解您的第二个问题。子进程-壳已调用的命令-通常不会明确关闭它的标准输入; Shell退出,让命令读取所需的所有内容,然后子代停止,Shell恢复读取。
Mark Plotnick

是的,您非常清楚地回答了我的两个后续问题,谢谢!
111 ---

12

您所看到的基本行为是,输入将被放置在缓冲区中直到被读取为止(好吧,如果您键入足够多,最终缓冲区将被填满,并且某些内容将丢失,尽管如此,键入还是很多)。make运行的大多数内容都不从STDIN读取,因此它保留在缓冲区中。

危险是错误的命令会读取您的输入。例如,make调用决定提示您的内容,然后它可能会读取您的下一个命令作为答案。当然,这有多危险取决于命令。(他们也可能会先刷新所有输入,只是丢弃先前的输入。)

TeX是Makefile中常用的一个命令。如果遇到错误(并且没有提供从未提示用户的标志),它将提示您如何继续。

更好的选择可能是运行:make && make check


8
  1. 好吧,显然,您不应运行依赖于第一个命令(make在您的示例中)成功完成的第二个命令。例如,make foo Enter> ./foo Enter 可能会引起问题。您可能想养成键入之类的习惯make && make check,其中仅当第一个命令成功时才执行第二个命令。
  2. 从理论上讲,第一个命令(一个或多个过程)可能会读取第二个命令的一部分,或者将其从终端输入缓冲区中删除。如果使用的前六个字符make check,您将最终执行命令heck,该命令在您的系统上可能不存在(但可能有点讨厌)。如果第一个命令是您了解并信任的良性操作,那么我不会立即发现任何问题。
  3. 它如何/为什么起作用?系统缓冲键盘输入。有点像电子邮件:您可以在短时间内向某人发送五封邮件,他们将坐在他的收件箱中,等待他阅读。同样,只要第一个命令没有从键盘读取,您键入的命令就会坐下来,等待shell绕过去读取它们。可以缓冲多少“预输入”有一个限制,但是通常是几百个字符(如果不是几千个字符)。

2
第1点,假设命令是不相关的,即lsmount例如。我试图了解如何处理缓冲的输入。感谢您的回答。
111 ---
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.