我是Bash的初学者,但我正试图学习这个工具,以便在这些日子里找到一份计算机工作。
我正在努力自学文件描述符。让我分享一些我的实验:
#!/bin/bash
# Some dummy multi-line content
read -d '' colours <<- 'EOF'
red
green
blue
EOF
# File descriptor 3 produces colours
exec 3< <(echo "$colours")
# File descriptor 4 filters colours
exec 4> >(grep --color=never green)
# File descriptor 5 is an unlimited supply of violet
exec 5< <(yes violet)
echo Reading colours from file descriptor 3...
cat <&3
echo ... done.
echo Reading colours from file descriptor 3 again...
cat <&3
echo ... done.
echo Filtering colours through file descriptor 4...
echo "$colours" >&4
echo ... done. # Race condition?
echo Dipping into some violet...
head <&5
echo ... done.
echo Dipping into some more violet...
head <&5
echo ... done.
当我看到来自上面的输出时,脑海中浮现出一些问题:
yes
开始执行时?在fd宣言?以后?yes
停止(CTRL-Z
或其他)并在需要更多紫罗兰时重启?yes
的PID?yes
只会在我exec 5>&-
?>&-
或<&-
我暂时停在这里。
谢谢!
PS:部分(编号)的答案很好..我会把自己不同的部分放在一起..(虽然一个人的综合答案会令人印象深刻!)
答案 0 :(得分:15)
fd3似乎在“消费”后“耗尽”,是否在首次使用后自动关闭?
不,它没有关闭。这是由于exec
的工作方式。在您使用exec
(不带参数)的模式中,它的功能是按照指定给自己的I / O重定向()的要求排列shell自己的文件描述符,然后将它们保留为< / strong>直到脚本终止或稍后再次更改。
稍后,cat
在其标准输入(文件描述符0)上接收此文件描述符3的副本。当cat
退出时,cat
的标准输入会被隐式关闭(或者,尽管不太可能,但cat
在它存在之前将其关闭,但这并不重要)。此文件的原始副本(shell的文件描述符3)仍然存在。虽然实际文件已达到EOF,但不会从中读取任何内容。
fd3与命名管道有何不同? (我已经看过的东西)
shell的<(some command)
语法(不是标准的bourne shell语法,我相信只在zsh
和bash
中可用,顺便说一下)实际上可能是使用命名管道实现的。它可能不在Linux下,因为有更好的方法(使用/dev/fd
),但它可能在其他操作系统上。
因此,从这个意义上说,这种语法可能也可能不是设置命名管道的帮助器。
命令是什么时候开始执行?在fd宣言?以后?
评估<(yes violet)
构造时(在评估exec 5< <(yes violet)
时会发生这种情况)。
是否停止(CTRL-Z或其他)并在需要更多紫罗兰时重新启动?
不,它不会停止。但是,当它开始产生的输出比读取管道另一端正在消耗的任何东西时,它将很快阻止。换句话说,管道缓冲区将变满。
我怎样才能获得“是”的PID?
好问题!在$!
执行后,yes
似乎立即包含它。然而,似乎有一个中间子shell,你实际上得到了该子shell的pid。请尝试<(exec yes violet)
以避免中间过程。
我可以获得“活跃”fds的列表吗?
不是来自shell。但是,如果您使用的是具有/proc
的Linux操作系统,则可以咨询/proc/self/fd
。
通过fd4过滤非常有趣的竞争条件,可以避免吗?
为避免这种情况,您可能希望在继续执行脚本之前等待grep
进程完成。如果您获得该流程的流程ID(如上所述),我认为您应该能够wait
。
只有当我执行5&gt;&amp; - ?
时才会停止
是。接下来会发生的是yes
将继续尝试永久产生输出,但当文件描述符的另一端关闭时,它将获得写入错误(EPIPE
)或信号({ {1}})默认情况下是致命的。
我是否关闭&gt;&amp; - 或&lt;&amp; - ?
是否重要?
没有。两种语法都是为了保持一致。