管道与文件描述符 #
基本概念 #
- I/O 重定向通常与文件描述符 fd 有关,shell 的 fd 通常为10个,即0~9;
- 0 是
<
的默认值,因此<
与0<
是一样的;同理,>
与1>
一样; - 在 I/O 重定向中,stdout 和 stderr 的管道会先准备好,才会从 stdin 读取数据;
- 管道
|
(pipe line) 上一个命令的 stdout 接到下一个命令的 stdin; - tee 命令是在不影响原本 I/O 的情况下,将 stdout 复制一份写入到文件中;
- bash 执行命令过程:分析命令 - 变量替换 - 命令替换 - 重定向 - 通配符展开 - 确定路径 - 执行命令;
(...)
将 command group 置于 sub-shell 中去执行,也称 nested sub-shell,它有一个重要的特性是:继承父 shell 的文件描述符;- exec 命令常用来代替当前 shell 并重新启动一个 shell,而对文件描述符进行操作的时候不会覆盖当前 shell 环境。
文件描述符的操作 #
>&n
使用系统调用 dup/dup2 复制文件描述符 n 并把结果用作 stdout;<&n
复制文件描述符 n 作为 stdin;<&-
关闭 stdin;>&-
关闭 stdout;n<&-
关闭文件描述符 n 的输入;n>&-
关闭文件描述符 n 的输出;- 文件描述符的输入/输出被关闭后,继续对其进行读/写会产生错误;
- 当存在多个文件描述符的操作时,按照从左往右的顺序依次执行;
- 在交互式 shell 中,关闭 stdin 结果会退出 shell。
创建命名管道 #
sh
mkfifo /tmp/t.fifo
- 管道文件已存在时,报错
mkfifo: cannot create fifo '/tmp/t.fifo': File exists
重定向操作 #
sh
# 打开文件描述符用于读写
exec 3<>/tmp/t.fifo
# 打开文件描述符用于读取
exec 3</tmp/t.fifo
# 打开文件描述符用于写入
exec 3>/tmp/t.fifo
# 关闭文件描述符的输入
exec 3<&-
# 关闭文件描述符的输出
exec 3>&-
# 输出重定向
cat /tmp/a.log >&3
# 输入重定向
read var <&3 # 相当于: read -u 3 var
- 文件描述符与重定向符号
<>
之间不能有空格。 - 关闭输入输出需要分别进行。
>/dev/null
表示丢弃标准输出,而>&-
表示关闭标准输出,继续输出将产生错误。