Sta*_*shr 5 linux bash cat stdin
我的脚本尝试收集执行时 STDIN 中可能存在或不存在的信息,但如果管道为空,则 cat 会挂起。如果 STDIN 中没有任何内容,如何确保我的脚本跳过此步骤?
stdin=$(cat <&0)
Run Code Online (Sandbox Code Playgroud)
请注意,我并不是专门寻找任何引用 /dev/ 的解决方案,因为我希望它可以在 chroot 中使用,无论 /dev/ 是否已安装(如果可能)。
通常,在使用管道和标准输入时,耗尽的管道没有特殊含义。新数据可能仍然会出现,直到有一个eof关闭管道为止。您按预期cat终止。eof如果之前没有数据eof,那么你才能说 stdin确实是空的。
考虑sender | receiver。sender比 ; 慢得多的情况并不罕见receiver。在这种情况下,receiver\ 的标准输入几乎总是耗尽,但您几乎不想因此而杀死整个管道。因此,在“空”(耗尽但尚未终止)stdin 上退出的工具是例外而不是标准。
在 Bash 中有read -t 0(-tPOSIX 不要求)。从help read:
\n\n\n如果
\nTIMEOUT是0,read则立即返回,而不尝试读取任何数据,仅当输入在指定的文件描述符上可用时才返回成功。
默认情况下read从标准输入读取,因此退出状态read -t 0将告诉您标准输入是否为“空”。但要小心!像这样的命令
echo 1 | read -t 0\nRun Code Online (Sandbox Code Playgroud)\n\n可能成功退出,也可能失败,因为echo和 是read同时运行的,而不是顺序运行的。为了避免这种情况,您的脚本应该sleep在read -t 0. 根据标准输入的来源,“一段时间”可能相对较长。做这样的事情:
sleep 1\nif read -t 0; then \xe2\x80\xa6 # process stdin here, you know it\'s non-empty\nRun Code Online (Sandbox Code Playgroud)\n\n您可以使用从 stdin 获取的数据填充变量。由于将二进制数据存储在变量中不是一个好主意(阅读此内容),也许您的数据只是文本。如果是这样,请read -t像这样使用:
read -r -t 5 -d $\'\\0\' stdin\nRun Code Online (Sandbox Code Playgroud)\n\n空字符(无论如何都不能存储在 Bash 变量中)作为分隔符 ( -d $\'\\0\') 将允许您将任何文本(例如换行符)读取到变量中stdin。最多 5 秒 ( -t 5) 后,命令终止,允许脚本继续。
另一种方法是使用timeout. 我的 Debian 中的一个基本示例:
timeout --foreground 5 cat | wc -c\nRun Code Online (Sandbox Code Playgroud)\n\n(替换wc -c为解析标准输入的代码;这只是一个示例)。
这应该可以很好地处理二进制数据。如果cat没有得到eof,那么 5 秒后它将被杀死,所以无论如何wc都会得到eof并且线路不会停止。问题是cat无论当前是否正在处理任何数据都会被杀死。我想你想要获取所有数据,即使只有一些数据,即使需要超过 5 秒。改良版:
{ timeout --foreground 5 dd bs=1 count=1 2>/dev/null && cat; } | wc -c\nRun Code Online (Sandbox Code Playgroud)\n\n如果第一个字节在5秒内出现,cat就会被触发。然后它将处理任何进一步的输入,直到eof,无论需要多长时间。包括第一个字节(如果有)在内的所有内容都将转到wc. eof如果5 秒内也没有任何字节,wc则只会收到eof; 生产线不会停顿。
| 归档时间: |
|
| 查看次数: |
3250 次 |
| 最近记录: |