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

Chr*_*son 2 bash file-descriptor while-loop io-redirection

我正在研究一个bash脚本,试图弄清楚它的工作方式并可能对其进行修补。有问题的脚本是这个 cryptroot从负责在开机解密块设备Debian的脚本。不能完全在家中进行bash肯定会带来挑战。

我找到了这段代码,但不确定它是做什么的。

if [ -r /conf/conf.d/cryptroot ]; then
    while read mapping <&3; do
        setup_mapping "$mapping" 3<&-
    done 3< /conf/conf.d/cryptroot
fi
Run Code Online (Sandbox Code Playgroud)

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

当我从文件中读取行时,通常会执行以下操作:

while read LINE
    do COMMAND
done < FILE
Run Code Online (Sandbox Code Playgroud)

在while循环中将的输出FILE定向到的位置readCOMMAND直到最后一行为止。

我也对重定向有所了解,例如,有时我会用它来重定向STDOUTSTDERR诸如此类/dev/null的东西。但是我不确定重定向的3含义。

根据tldp.org的介绍,在阅读了有关I / O重定向的更多知识之后,我已经接近答案了。

stdin,stdout和stderr的文件描述符分别为0、1和2。要打开其他文件,请保留描述符3到9。

因此3是“仅”对打开文件的引用,或:

...只是操作系统分配给打开文件以跟踪它的数字。考虑它是文件指针的简化类型。

因此,据我了解:

  • 3< /conf/conf.d/cryptroot打开/conf/conf.d/cryptroot读取并将其分配给文件描述符3。
  • read mapping <&3似乎是从读文件描述符3,它指向打开文件的第一行/conf/conf.d/cryptroot
  • setup_mapping "$mapping" 3<&-似乎是关闭文件描述符3,这是否意味着它再次打开在环动不动指向下一行?

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

while read mapping; do
    setup_mapping "$mapping"
done < /conf/conf.d/cryptroot
Run Code Online (Sandbox Code Playgroud)

第一个版本提供什么优势(如果有)?

Wil*_*ell 5

一个常见的问题

while read LINE
    do COMMAND
done < FILE
Run Code Online (Sandbox Code Playgroud)

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