为什么在 bash while 循环中使用“<&3”、“3&-”和“3</file”?它实际上做了什么?

Why use "<&3", "3&-" and "3</file" in a bash while loop? And what does it actually do?

我正在研究一个 bash 脚本,试图弄清楚它是如何工作的,并可能对其进行修补。有问题的脚本是来自 debian 的 this cryptroot 脚本,负责在启动时解密块设备。在 bash 完全不在家绝对是一个挑战。

我找到了这段代码,但不确定它的作用。

if [ -r /conf/conf.d/cryptroot ]; then
    while read mapping <&3; do
        setup_mapping "$mapping" 3<&-
    done 3< /conf/conf.d/cryptroot
fi

我的猜测是它读取 /conf/conf.d/cryptroot 中的每一行并将其传递给 setup_mapping。但是我不太明白,<&33&-3</conf/conf.d/cryptroot的意义是什么,有什么作用?

当我从文件中读取行时,我通常会这样做:

while read LINE
    do COMMAND
done < FILE

FILE 的输出在 while 循环中指向 read 并执行 COMMAND 直到最后一行。

我也知道一些关于重定向的知识,例如,我有时用它来将 STDOUTSTDERR 重定向到 /dev/null 之类的东西。但是我不确定重定向到 3 是什么意思。

在阅读了更多关于 I/O 重定向的信息后,根据 tldp.org.

,我得到了一些接近答案的东西

The file descriptors for stdin, stdout, and stderr are 0, 1, and 2, respectively. For opening additional files, there remain descriptors 3 to 9.

因此 3 是 "just" 对打开文件的引用或:

...simply a number that the operating system assigns to an open file to keep track of it. Consider it a simplified type of file pointer.

据我了解:

如果以上是正确的,我的问题是为什么要这样做而不是 "normal" 方式?例如

while read mapping; do
    setup_mapping "$mapping"
done < /conf/conf.d/cryptroot

第一个版本有什么优势(如果有的话)?

的常见问题
while read LINE
    do COMMAND
done < FILE

是人们忘记了 COMMAND 也在从 FILE 中读取,并且可能会在 while 循环的控制中消耗打算由 read 读取的数据。为了避免这种情况,一个常见的习惯用法是从不同的文件描述符中读取。这是通过 <&3 完成的。但是这样做会为 COMMAND 打开文件描述符 3。这可能不是问题,但用 3<&- 显式关闭它是合理的。简而言之,您看到的结构只是一种避免 setup_mapping 无意中读取用于 read.

的数据的方法