考虑以下示例,模拟一个在 10 秒后给出输出的命令:exec 5< <(sleep 10; pwd)
在 Solaris 中,如果我在 10 秒之前检查文件描述符,我可以看到它的大小为 0,这告诉我它还没有填充数据。我可以简单地每秒检查一次,直到满足文件测试条件(不同于 0(,然后提取数据:
while true; do
if [[ -s /proc/$$/fd/5 ]]; then
variable=$(cat <&5)
break
fi
sleep 1
done
但是在Linux中我不能这样做(RedHat,Debian等(。所有文件描述符的大小均为 64 字节,无论它们是否保存数据。对于需要可变时间来转储其输出的各种命令,我不知道何时应该读取文件描述符。不,我不想只是等待cat <&5
完成,我需要知道我应该首先执行cat
的时间。因为我使用此机制同时发出命令并将其输出分配给相应的文件描述符。如前所述,这在 Solaris 中效果很好。
这是一个想法的骨架:
#!/bin/bash
exec 5< <(sleep 4; pwd)
while true
do
if
read -t 0 -u 5 dummy
then
echo Data available
cat <&5
break
else
echo No data
fi
sleep 1
done
来自 Bash 参考手册:
如果超时为 0,则立即返回读取,而不尝试读取和 数据。如果指定文件上的输入可用,则退出状态为 0 描述符,否则为非零。
这个想法是使用-t 0
读取(零超时(和-u 5
读取(从文件描述符 5 读取(来立即检查数据可用性。
当然,这只是一个演示概念的玩具循环。
用户 Fred 仅使用 bash 内置给出的解决方案工作正常,但由于轮询文件描述符的状态,它有点非最佳。如果调用另一个解释器(例如 Python(不是不行的,则可以使用非轮询版本:
#! /bin/bash
(
sleep 4
echo "This is the data coming now"
echo "More data"
) | (
python3 -c 'import select;select.select([0],[],[])'
echo "Data is now available and can be processed"
# Replace with more sophisticated real-world processing, of course:
cat
)
单行python3 -c 'import select;select.select([0],[],[])'
等待,直到 STDIN 准备好数据。它使用标准的select(2)
系统调用,我还没有找到直接的 shell 等效项或包装器。