什么是进程替换
先看 WIKI 的解释:
In computing, process substitution is a form of inter-process communication that allows the input or output of a command to appear as a file.
在计算中,进程替换是进程间通信的一种形式,允许命令的输入或输出作为文件出现;
进程替换的语法
cmd1 >(cmd2)
将 cmd1 输出发送给 cmd2
cmd1 <(cmd2)
将 cmd2 的输出发送给 cmd1
在这里:>(cmd2)或者<(cmd2)等价于一个内容为 cmd2 输出的文件。这么说可能不明白,请看下面“进程替换的机制”;
进程替换的机制
题外话: 如果你不会英语,你真的会错过很多东西;
进程替换的实现有两种:
- 在支持 /dev/fd 的系统上(大多数都支持),通过 pipe()系统调用实现。pipe()系统调用会为匿名管道返回一个文件描述符$fd,然后用字符串 /dev/fd/$fd 替换命令行上的>(cmd2)或者<(cmd2);
- 对于不支持 /dev/fd 的系统上,Bash 使用新临时文件名调用 mkfifo 来创建一个命名管道,然后使用此文件名作为替代;
为了演示所涉及的步骤,思考如下命令:
diff file1 <(sort file2)
shell 的执行步骤如下(对于支持 /dev/fd 的系统):
- 创建一个新的匿名管道。这个管道可以通过像 /dev/fd/63 这样的东西访问;你可以用echo <(true)命令看到它;
- 在后台执行替代命令(当前为 sort file2),将输出输送到匿名管道;
- 执行主命令,使用匿名管道的路径替换替带命令。在这个例子中,完整的命令可能扩展为:diff file1 /dev/fd/63
- 当执行结束时,关闭匿名管道;
对于命名管道(不支持 /dev/fd 的系统),唯一不同的地方在于管道的创建和删除:使用 mkfifo 创建;使用 unlink 删除。其他方面一样的;
进程替换的示例
#!/bin/sh echo <(ls) # 输出: # /dev/fd/63
对于cmd1 >(cmd2),当 Bash 在执行进程替换的时候,Bash 会将 cmd2 的标准输出
参考文献
http://teliute.org/linux/abs-3.9.1/process-sub.html
https://en.wikipedia.org/wiki/Process_substitution