![如何检查stdin是否有数据而不阻塞IO(docker)?](https://linux22.com/image/223347/%E5%A6%82%E4%BD%95%E6%A3%80%E6%9F%A5stdin%E6%98%AF%E5%90%A6%E6%9C%89%E6%95%B0%E6%8D%AE%E8%80%8C%E4%B8%8D%E9%98%BB%E5%A1%9EIO%EF%BC%88docker%EF%BC%89%EF%BC%9F.png)
如果我执行echo this | docker run -i alpine cat
,我就会得到this
。
如果我执行docker run -i alpine cat
,我会被阻止终端,因为cat
读取标准输入,但那里什么也没有。
我可以检查打开的文件描述符。如果我运行docker run -i alpine ls -lA /proc/1/fd
,我会在标准输出中得到以下内容:
lr-x------ 1 root root 64 Aug 9 13:45 0 -> pipe:[10289389]
l-wx------ 1 root root 64 Aug 9 13:45 1 -> pipe:[10289390]
l-wx------ 1 root root 64 Aug 9 13:45 2 -> pipe:[10289391]
lr-x------ 1 root root 64 Aug 9 13:45 3
这在标准错误中:
ls: /proc/1/fd/3: cannot read link: No such file or directory
一切echo this | docker run -i alpine ls -lA /proc/1/fd
都是一样的(除了pipe:[these numbers]
)。
如果我不-i
从 中删除docker run
,有什么方法可以检查 stdin 中是否有任何数据而不需要 IO 块?test -t 0
根本不起作用,因为 stdin fd 始终打开。
我想创建一个docker run mycommand
从 stdin 读取并输出到 stdout 的 CLI 命令(通过 )(stdout 很简单,没有什么有趣的)。所以,我希望echo data | docker run mycommand
它能够根据输入数据打印出不同的内容。但如果我要这样做,docker run mycommand
应该说我“需要向标准输入提供数据”才能工作。
答案1
是的,您可以在 shell 中确定是否有任何数据要读取。我保存了大量有关 shell 输入读取的信息。
https://antofthy.gitlab.io/info/shell/input_reading.txt
你的问题...“有什么方法可以检查 stdin 中是否有任何数据而不需要 IO 块吗?”
您基本上是在要求“民意调查”(无读)测试......
read -r -t 0 var
这实际上并没有读取任何内容。如果有要读取的内容,则其退出状态为 0(真),否则返回 1;如果没有或为 EOF,则返回假。
另请注意,这仅告诉您是否有数据。在您尝试读取之前,它不会告诉您输入是否位于“文件结尾”(EOF)。它也不会告诉您输入是否是完整的行(带有换行符)。
要在不阻塞的情况下读取可用数据...
read -r -t 0.00001 line
请记住,大多数内容都会读取整行,并且通常会阻塞输入,直到获得换行符或 EOF。如果没有可用的换行符,上面的代码将返回错误退出 142 和空行,即使对于后面跟有 EOF 的不完整行也是如此。
要读取所有数据,甚至是否可用换行符(将包括任何换行符)...
while IFS= read -r -s -d '' -t .01 data
do [ $? -ge 128 ] && break
printf "$data"
done
在读取中添加 -n1 将一次读取一个字符!
我建议您仔细阅读上述文档的各个部分,以找出您想要的内容。根据任何其他编程语言的怪癖,所有这些都同样适用于该语言。
额外的
您可能还想查看我编写的名为“shell_select”的 perl 脚本,它允许您检查列出的文件描述符是否已准备好从 shell 读取或写入!
https://antofthy.gitlab.io/software/#shell_select
我用它来处理多个输入流(来自原始“bc”数学计算器的 stdout 和 stderr),而不会挂在(阻塞)一个或另一个文件句柄上,同时仍然保持输入完全独立。