多年来我一直试图理解这个概念,但目前对此的了解并不完整。
这里的任何人都可以制作一种教程或很好的解释,并举例说明如何
- 打开一个新的
fd
- 读自
fd
- 使用
fd
- 关闭
fd
我读过了https://www.gnu.org/software/bash/manual/html_node/Redirections.html和man 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> file
file
ls
{
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 除外。对于其他一些使用管道的结构也是如此。