Bash IO 重定向,打开和关闭“fd”,有人可以解释一下吗?

Bash IO 重定向,打开和关闭“fd”,有人可以解释一下吗?

多年来我一直试图理解这个概念,但目前对此的了解并不完整。

这里的任何人都可以制作一种教程或很好的解释,并举例说明如何

  • 打开一个新的fd
  • 读自fd
  • 使用fd
  • 关闭fd

我读过了https://www.gnu.org/software/bash/manual/html_node/Redirections.htmlman bash,但是不清楚,根本没有具体的、可以理解的例子。

如果有人能很好地解释它,这将是一个有价值的答案,不仅对我而言。语法大多数时候都有点混乱。
有时需要exec,有时不需要。

答案1

Bourne-like shell 的一些翻译:

系统调用 外壳接口 贝壳 评论
open("file", O_RDONLY) exec 3< file 全部 此处在 fd 3 打开
open("file", O_RDONLY) exec {fd}< file zsh ksh93 bash fd 在$fd²内返回
open("file", O_WRONLY|O_TRUNC|O_CREAT) exec 3> file 全部 立方
open("file", O_WRONLY|O_APPEND|O_CREAT) exec 3>> file 全部 4
open("file", O_RDWR|O_CREAT) exec 3<> file 全部
open("file", ...) sysopen ... 桀骜 在 zsh/系统模块中
dup2(4, 5) exec 5>&4 全部 与...一样exec 5<&4
dup(4) exec {fd}>&4 zsh ksh93 bash fd 返回$fd
write(4, data, length) print -rnu4 -- "$data" 克什兹什 bashprint还有一个可加载的内置示例5
write(...) syswrite ... 桀骜 在 zsh/系统模块中
read(4, var...) sysread -i 4 ... var 桀骜 zsh/system模块中
read(4, var...) IFS= read -ru4 ... var ksh zsh bash 读取一行。谨防限制。5
close(4) exec 4>&- 全部 或者exec 4<&-
lseek(4, 123, SEEK_SET) exec 4>#((123)) 克什93
lseek(4, 123, SEEK_CUR) exec 4>#((CUR + 123)) 克什93
lseek(4, 123, SEEK_END) exec 4>#((EOF + 123)) 克什93
lseek(...) sysseek ... 桀骜 在 zsh/系统模块6中
pipe() exec 4>>|5 亚什 fd 4 写端,5 读端
fstat(4, var) zstat -f 4 -H var 桀骜 在 zsh/stat 模块中
select(...) zselect ... 桀骜 在 zsh/zselect 模块中

zsh 还具有一些zsh/net/socket, zsh/net/tcp,zsh/zpty模块来创建操作其他类型的 fd。

使用exec更改 shell 进程的文件描述符。然而,大多数时候,您只想更改其他命令的文件描述符,例如仅在 fd 1 (stdout) 上打开ls -l dir/ > file(缩写)或一段代码:ls -l dir/ 1> filefilels

{
  echo Some Header
  ls -l dir/
} 1> file 2>> error.log

foo | bar在并发进程中执行pipe()7后跟一些dup2()s 或等效项和close()s,因此将运行的进程的 fd 1foo转到管道的写入端,而 fd 0 或bar转到读取端。其他使用或可能使用管道的 shell 结构包括命令替换 ( var=$(cmd), var=`cmd`)、类似 Korn 的 shell 进程替换 ( foo <(bar) >(baz))、协同进程、yash 的进程重定向。


¹ 在 ksh93 和 bash 中,如果file/dev/tcp|udp/host/port,它不会执行真正的打开,而是创建一个网络套接字。

² 其他>, >>, <>,> 运算符也可以这样做

³ 如果noclobber打开该选项,O_EXCL如果目标是常规文件,则添加 a,可以使用>|>!运算符绕过,具体取决于 shell

4在 Bourne shell 中,没有O_APPEND,但是 shell 在 open 后求到底

5在其他 shell 中,您始终可以执行printf %s "$var" >&4.这不会写入 fd 4,而是写入 fd 1,经过一段时间后dup2(4, 1)实际上达到了相同的目标。同样对于IFS= read -r line <&4.

6另请参阅systell(fd)返回 fd 位置的数学函数,它是另一个接口lseek()

7socketpair()某些使用s 而不是管道的系统上的 ksh93 除外。对于其他一些使用管道的结构也是如此。

相关内容