Linux服务器中最强大的shell操作符之一就是pipe。在本文中,我们将看到常规pipe和命名pipe的工作原理,如何使用它们以及它们之间的区别。
竖条符号|表示pipe。由于pipe的存在,你可以将一个命令的输出作为输入,并将其送至另一个命令。换句话说,pipe是一种重定向的形式,在Linux中用于将一个程序的输出送到另一个程序中进行进一步处理。
pipe或未命名的pipe命令的语法是任意两个命令之间的|字符。
command1 | command2 | … | commandN
为了了解pipe是如何工作的,让我们来看看下面的例子。
假设我们有一个目录,里面有很多不同类型的文件,我们想知道这个目录中某一类型的文件有多少。我们想知道这个目录中有多少个特定类型的文件。我们可以使用ls很容易地得到一个文件列表。
ls
为了区分我们感兴趣的文件类型,我们将使用grep。我们要找到名字或文件扩展名中含有 “txt “的文件。
我们将使用特殊的shell字符|来引导ls的输出到grep。
ls | grep txt
ls的输出没有被发送到终端窗口。因此,结果并没有显示在屏幕上,而是被重定向到grep命令的输入端。我们在上面看到的输出来自grep,它是这个链中的最后一条命令。
现在,让我们开始扩展我们的链。我们可以通过添加wc命令来计算 “txt “文件。我们将在wc中使用-l选项(行数)。
ls | grep txt | wc -l
grep不再是链中的最后一条命令,所以我们看不到它的输出。grep的输出被输入到wc命令中,我们在终端窗口中看到的输出来自wc。我们在终端窗口中看到的输出来自于wc。wc报告说,在目录中有2个文件 “txt”。
顾名思义,这些都是有名字的pipe。普通pipe和命名pipe的一个关键区别是,命名pipe在文件系统中是存在的。也就是说,它们以文件的形式出现。
命名pipe是一种使用被赋予特定名称的pipe将信息从一个计算机进程传递到另一个计算机进程的方法。命名pipe也被称为FifO,即First In, First Out的意思。
你可以通过文件权限部分的p位来判断一个文件是否是一个命名的pipe。
ls -l mypipe
命名pipe实际上是文件系统本身的文件。与标准pipe不同,命名pipe是作为文件系统的一部分被访问的,就像其他类型的文件一样。
命名pipe的内容驻留在内存中,而不是写入磁盘。只有当pipe的两端都被打开时,它才会被传递。而且在pipe的另一端被打开并读取之前,你可以多次向pipe写入内容。通过使用命名pipe,你可以建立一个进程,在这个进程中,一个进程向一个pipe写入,另一个进程从一个pipe读取,而不必太过担心尝试时间或仔细协调它们的交互。
为了了解命名pipe是如何工作的,让我们来看看下面的例子。首先,让我们创建一个命名pipe。
mkfifo mypipe
现在让我们用这个pipe来消耗消息。
tail -f mypipe
打开另一个终端窗口,给这个pipe写一条信息。
echo “hi” >> mypipe
现在在第一个窗口中你可以看到打印出来的 “hi”。
因为是pipe,消息已经被消耗掉了,如果我们检查文件大小,可以看到还是0。
ls -l mypipe
由于命名的pipe只是一个文件,要删除一个文件,我们可以使用rm命令。因此,要删除我们在前面的例子中创建的pipe,我们将运行以下命令
rm mypipe
何时使用常规或命名pipe
使用常规pipe而不是命名pipe取决于我们要寻找的特性。其中一些可以是持久性,双向通信,有一个文件名,创建一个过滤器,以及限制访问权限等等。
例如,如果我们想多次过滤一个命令的输出,使用匿名pipe似乎是最合适的选择。另一方面,如果我们需要一个文件名,而又不想把数据存储在磁盘上,我们要找的是一个命名pipe。