使用命名管道
有时你可能希望通过一个程序输出内容并将其输入另一个程序,但不能使用标准管道。
ls -l | grep ".log"
你可以简单地写一个临时文件:
touch tempFile.txt
ls -l > tempFile.txt
grep ".log" < tempFile.txt
这适用于大多数应用程序,但是,没有人会知道 tempFile
做了什么,如果它包含该目录中 ls -l
的输出,有人可能会删除它。这是命名管道发挥作用的地方:
mkfifo myPipe
ls -l > myPipe
grep ".log" < myPipe
myPipe
在技术上是一个文件(一切都在 Linux 中),所以让我们在我们刚刚创建管道的空目录中执行 ls -l
:
mkdir pipeFolder
cd pipeFolder
mkfifo myPipe
ls -l
输出是:
prw-r--r-- 1 root root 0 Jul 25 11:20 myPipe
注意权限中的第一个字符,它被列为管道而不是文件。
现在让我们做一些很酷的事情。
打开一个终端,记下目录(或创建一个目录,以便清理很容易),并制作一个管道。
mkfifo myPipe
现在让我们把东西放进烟斗里。
echo "Hello from the other side" > myPipe
你会注意到这个悬挂,管道的另一侧仍然关闭。让我们打开管道的另一边,然后让这些东西通过。
打开另一个终端并转到管道所在的目录(或者如果你知道它,则将其添加到管道中):
cat < myPipe
你会注意到,输出 hello from the other side
后,第一个终端中的程序结束,第二个终端中的程序也就完成了。
现在反向运行命令。从 cat < myPipe
开始,然后回复一些东西。它仍然有效,因为程序会等到一些东西放入管道才终止,因为它知道它必须得到一些东西。
命名管道可用于在终端之间或程序之间移动信息。
管道很小。一旦完整,写入器就会阻塞,直到某些读取器读取内容,因此你需要在不同的终端中运行读取器和写入器,或者在后台运行一个或另一个:
ls -l /tmp > myPipe &
cat < myPipe
使用命名管道的更多示例:
-
示例 1 - 同一终端/同一 shell 上的所有命令
$ { ls -l && cat file3; } >mypipe & $ cat <mypipe # Output: Prints ls -l data and then prints file3 contents on screen
-
示例 2 - 同一终端/同一 shell 上的所有命令
$ ls -l >mypipe & $ cat file3 >mypipe & $ cat <mypipe #Output: This prints on screen the contents of mypipe.
注意显示
file3
的第一个内容然后显示ls -l
数据(LIFO 配置)。 -
示例 3 - 同一终端/同一 shell 上的所有命令
$ { pipedata=$(<mypipe) && echo "$pipedata"; } & $ ls >mypipe # Output: Prints the output of ls directly on screen
请注意,变量
$pipedata
不能在主终端/主 shell 中使用,因为使用&
会调用子 shell,而$pipedata
仅在此子 shell 中可用。 -
示例 4 - 同一终端/同一 shell 上的所有命令
$ export pipedata $ pipedata=$(<mypipe) & $ ls -l *.sh >mypipe $ echo "$pipedata" #Output : Prints correctly the contents of mypipe
由于变量的导出声明,这会在主 shell 中正确打印
$pipedata
变量的值。由于调用背景 shell(&
),主终端/主 shell 没有挂起。