文件描述符和 shell 脚本

文件描述符和 shell 脚本

我很难理解如何在 shell 脚本中使用文件描述符。

我知道一些基础知识,例如

exec 5 > /tmp/foo

所以 fd 5 附加到 foo 上进行写入。

exec 6 < /tmp/bar

……为了阅读。

exec 5>&-

…关闭fd。

现在这有什么作用呢?

#!/bin/bash

exec 5 > /tmp/foo 
exec 6 < /tmp/bar 

cat <&6 | while read a
do
     echo $a >&5
done

据我了解&5关闭 fd,那么每次调用后输出如何仍被成功重定向?

这是一份意大利面复制品:这里

它声称使用这个而不是简单的echo $a > file会使其更快,但我无法理解。我将不胜感激任何像样的教程的链接。我的谷歌力量似乎让我失望了。

答案1

首先,请注意关闭的语法是5>&-or 6<&-,具体取决于文件描述符是用于写入还是读取。该博客文章中似乎存在拼写错误或格式错误。

这是注释的脚本。

exec 5>/tmp/foo       # open /tmp/foo for writing, on fd 5
exec 6</tmp/bar       # open /tmp/bar for reading, on fd 6
cat <&6 |             # call cat, with its standard input connected to
                      # what is currently fd 6, i.e., /tmp/bar
while read a; do      # 
  echo $a >&5         # write to fd 5, i.e., /tmp/foo
done                  # 

这里没有关闭。因为在这个简单的示例中所有输入和输出都到达同一位置,所以不需要使用额外的文件描述符。你可以写

cat </tmp/bar |
while read a; do
  echo $a
done >/tmp/foo

当您想要依次写入多个文件时,使用显式文件描述符会变得很有用。例如,考虑一个将数据输出到数据输出文件并将数据记录到日志文件以及可能的错误消息的脚本。这意味着三个输出通道:一个用于数据,一个用于日志,一个用于错误。由于只有两个标准输出描述符,因此需要第三个。您可以调用exec打开输出文件:

exec >data-file
exec 3>log-file
echo "first line of data"
echo "this is a log line" >&3
if something_bad_happens; then echo error message >&2; fi
exec >&-  # close the data output file
echo "output file closed" >&3

当您在循环中进行重定向时,就会出现有关效率的评论,如下所示(假设文件一开始是空的):

while …; do echo $a >>/tmp/bar; done

在每次迭代中,程序都会打开/tmp/bar、查找文件末尾、附加一些数据并关闭文件。一次性打开文件效率更高:

while …; do echo $a; done >/tmp/bar

当在不同时间发生多个重定向时,调用exec执行重定向而不是在重定向中包装块变得有用。

exec >/tmp/bar
while …; do echo $a; done

你会发现其他几个通过浏览io-redirection本网站标签进行重定向的示例

答案2

每个打开的文件都会分配一个文件描述符,stdin 的文件描述符是 0 stdout 是 1
stderr 是 2 对于打开其他文件,还保留描述符 3 到 9。

举个例子

exec 3>&1 4>&2
exec 1>  /proc/1/fd/1 2>&1

3>&1创建一个新的文件描述符并将其重定向到 1(STDOUT) 4>&2也是新的文件描述符并将其重定向到 2(STDERR)

1> /proc/1/fd/1使用套接字文件描述符 2>&1还将从此文件描述符中的所有内容重定向到 1(即 STDOUT)

我最近也学到了这一点,所以请随时指出我是否遗漏了什么

使用 exec 和使用文件描述进行重定向的参考 https://www.linuxtopia.org/online_books/advanced_bash_scripting_guide/x13082.html

相关内容