为什么在 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
。但是我不太明白,<&3
、3&-
和3</conf/conf.d/cryptroot
的意义是什么,有什么作用?
当我从文件中读取行时,我通常会这样做:
while read LINE
do COMMAND
done < FILE
FILE
的输出在 while 循环中指向 read
并执行 COMMAND
直到最后一行。
我也知道一些关于重定向的知识,例如,我有时用它来将 STDOUT
和 STDERR
重定向到 /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.
据我了解:
3< /conf/conf.d/cryptroot
打开/conf/conf.d/cryptroot
进行读取并将其分配给文件描述符3。
read mapping <&3
似乎正在读取文件描述符 3 的第一行,它指向打开的文件 /conf/conf.d/cryptroot
。
setup_mapping "$mapping" 3<&-
好像是在关闭文件描述符3,这是否意味着它在循环中的每一圈都被再次打开并指向下一行?
如果以上是正确的,我的问题是为什么要这样做而不是 "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
.
的数据的方法
我正在研究一个 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
。但是我不太明白,<&3
、3&-
和3</conf/conf.d/cryptroot
的意义是什么,有什么作用?
当我从文件中读取行时,我通常会这样做:
while read LINE
do COMMAND
done < FILE
FILE
的输出在 while 循环中指向 read
并执行 COMMAND
直到最后一行。
我也知道一些关于重定向的知识,例如,我有时用它来将 STDOUT
和 STDERR
重定向到 /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.
据我了解:
3< /conf/conf.d/cryptroot
打开/conf/conf.d/cryptroot
进行读取并将其分配给文件描述符3。read mapping <&3
似乎正在读取文件描述符 3 的第一行,它指向打开的文件/conf/conf.d/cryptroot
。setup_mapping "$mapping" 3<&-
好像是在关闭文件描述符3,这是否意味着它在循环中的每一圈都被再次打开并指向下一行?
如果以上是正确的,我的问题是为什么要这样做而不是 "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
.