15

我是一个 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.

当我看到上面的输出时,我想到了一些问题:

  1. fd3在“消耗”后似乎“耗尽”了,是不是第一次使用后也会自动关闭?
  2. fd3 与命名管道有何不同?(我已经看过的东西)
  3. 命令究竟什么时候yes开始执行?在 fd 声明时?之后?
  4. 当需要更多紫罗兰色时会yes停止(或其他)并重新启动吗?CTRL-Z
  5. 我怎样才能得到 PID yes
  6. 我可以获得“活动”fds 的列表吗?
  7. 通过 fd4 过滤的非常有趣的竞争条件,可以避免吗?
  8. 只会yes在我停止exec 5>&-
  9. 我关闭>&-或有关系<&-吗?

我暂时停在这里。

谢谢!

PS:部分(编号)答案很好..我自己会把不同的点点滴滴放在一起..(尽管一个人的综合回答会令人印象深刻!)

4

1 回答 1

15

fd3在“消耗”后似乎“耗尽”了,是不是第一次使用后也会自动关闭?

不,它没有关闭。这是由于工作方式exec。在您使用的模式下exec(不带参数),它的功能是按照指定给自身的 I/O 重定向的请求排列 shell 自己的文件描述符,然后保持这种状态,直到脚本终止或再次更改它们之后。

稍后,cat在其标准输入(文件描述符 0)上接收此文件描述符 3 的副本。cat的标准输入在退出时被隐式关闭cat(或者,虽然不太可能,cat在它存在之前将其关闭,但这并不重要)。该文件的原始副本,即 shell 的文件描述符 3,仍然存在。尽管实际文件已达到 EOF,但不会再从中读取任何内容。

fd3 与命名管道有何不同?(我已经看过的东西)

shell 的<(some command)语法(它不是标准的 bourne shell 语法,我相信只能在zshandbash中使用,顺便说一句)实际上可能是使用命名管道来实现的。它可能不在 Linux 下,因为有更好的方法(使用/dev/fd),但它可能在其他操作系统上。

所以从这个意义上说,这种语法可能是也可能不是设置命名管道的助手。

命令 yes 究竟什么时候开始执行?在 fd 声明时?之后?

一旦<(yes violet)构造被评估(在评估时发生exec 5< <(yes violet))。

是否停止(CTRL-Z 或其他)并在需要更多紫罗兰色时重新启动?

不,它不会停止。但是,当它开始产生比读取管道另一端的任何内容更多的输出时,它会很快阻塞。换句话说,管道缓冲区将变满。

我怎样才能得到是的PID?

好问题!$!似乎在执行后立即包含它yes。然而,似乎有一个中间子shell,你实际上得到了那个子shell的pid。尽量<(exec yes violet)避免中间过程。

我可以获得“活动”fds 的列表吗?

不是来自壳。但是如果你使用的是像 Linux 这样的操作系统/proc,你可以咨询一下/proc/self/fd

通过 fd4 过滤的非常有趣的竞争条件,可以避免吗?

grep为了避免这种情况,您可能希望在继续执行脚本之前等待该过程完成。如果您获得该进程的进程ID(如上所述),我认为您应该能够wait获得它。

只有当我执行 5>&- 时才会停止?

是的。然后会发生什么,yes它将继续尝试永远产生输出,但是当文件描述符的另一端关闭时,它将得到一个写入错误(EPIPE)或SIGPIPE默认情况下是致命的信号()。

我用 >&- 还是 <&- 结束有关系吗?

不,为了保持一致性,两种语法都可用。

于 2013-03-25T08:53:06.140 回答