1 基础知识
1.1 管道的介绍
– 管道为Pipeline的翻译
– 管道是类Unix系统使用极其广泛的进程通讯机制
– 管道是将标准输入和标准输出链接起来的进程
– 管道把前一个进程的输出作为下一个进程的输入
– 管道由道格拉斯·麦克罗伊为Unix命令行而发明
– 管道因为与物理管道相似而得名
1.2 管道的分类
1.2.1 匿名管道
– 匿名管道是计算机进程间的一种先进先出通讯机制(不支持异步读写操作)
– 匿名管道两个可以实现全双工通讯
– 匿名管道可由父进程创建,然后由其创建的多个子进程继承
– 匿名管道由于没有名称,所以只能用于本地计算机通讯不能用于网络通讯
– 匿名管道生存期不超过创建管道进程的生存期
1.2.2 命名管道
– 命名管道是计算机进程间的一种先进先出通讯机制(不支持异步读写操作)
– 命名管道是类Unix系统传统管道(匿名管道)的扩展
– 命名管道生存期可以与操作系统运行期一样长
1.2.3 网络管道
– 命令“netcat”和“socat”可以将管道链接到TCP/IP套接字
2 最佳实践
2.1 匿名管道的使用
2.1.1 简单的使用
ls /etc/ | grep init.d
范例解析,
前进程“ls”列出“/etc”目录的内容
后进程“grep”根据关键字“init.d”过滤前进程列表后得到想要的结果
2.1.2 合并错误流
ls cmdschool.org | grep "No such file or directory"
上例,命令“ls”找不存在的文件而报错(错误流),如想用管道传递错误会失败,正确方式是把标准错误流合并到标准输出流中再传递,详细如下,
ls cmdschool.org 2>&1 | grep "No such file or directory"
2.1.3 Pipemill
ls -l /tmp/ | while read var1 var2 var3 var4 var5 var6 var7 var8; do echo "$var1 $var2 $var3 $var4 $var5 $var6 $var7 $var8" done
注:Pipemail中文翻译为“制管机”,用法是管道配合“while”循环以及“read”读取管道传递的多个变量并利用。
2.2 命名管道的使用
2.2.1 从命令管道中压缩数据
mkfifo my_pipe
以上创建命名管道“my_pipe”,然后我们使用gzip压缩传给管道“my_pipe”的数据,范例如下,
gzip -9 -c < my_pipe > out.gz
然后,我们使用另一个shell独立地发送数据到管道“my_pipe”
cat file > my_pipe
使用完成后,我们可以使用如下命令清理命名管道,
rm my_pipe
2.2.2 解压数据到命名管道
mkfifo -m 0666 /tmp/myPipe gzip -d < file.gz > /tmp/myPipe
然后从命令管道中读取,
LOAD DATA INFILE '/tmp/myPipe' INTO TABLE tableName;
2.2.3 循环获取命名管道
mkfifo -m 0666 /tmp/myPipe
以上创建命令管道,然后使用如下循环监视命令管道,
#!/bin/bash myFifo="/tmp/myPipe" while true; do if read line; then echo $line fi sleep 0.001s done < "$myFifo"
然后,我们用另外一个shell往命名管道中写入数据可以观察到效果,
ls /tmp/* >> /tmp/myPipe
注:使用“sleep”语句防止CPU过高,请根据实际情况调整暂停时间。
2.2.4 命名管道控制线程高并发执行
#!/bin/bash thread=3 fifoFile="/tmp/$$.fifo" mkfifo $fifoFile exec 9<>$fifoFile rm -f $fifoFile for ((i=0;i<$thread;i++)); do echo >&9 done for ((;;)); do read -u 9 { echo "$$ infinite loops [ hit CTRL+C to stop]" sleep 1s echo >&9 } & done wait exec 9>&-
脚本解析如下,
– 变量“thread”,定义每次并发的线程数
– 命令“mkfifo”,创建命名管道文件(命名管道具有先进先出的特性,且每一行读取后就自动删除)
– 命令“exec”,即第一个执行使用文件描述符(FD)“9”关联创建的管道问题,后面可以使用文件描述符直接访问
– 命令“rm”,删除创建的命名管道文件(不删除也可以,非必须操作)
– 命令“for”,即第一个循环根据变量“thread”的定义通过文件描述符往管道中写入相应的空行,范例为3个空行
– 命令“for”,即第二个循环无限地执行循环内的代码
– 命令“read”,配合“{}&”并发地读取命名管道中每行,由于范例管道只有3行,所以3行同时读取后只能等待新的写入
– 命令“echo”,即第一个打印代表执行代码,范例只输出“脚本名称”加“infinite loops [ hit CTRL+C to stop]”提示
– 命令“sleep”,暂停1秒(可以不暂停),范例暂停的目的只为脚本演示效果明显且易于理解
– 命令“echo”,即第二个打印空行到命名管道(透过关联的文件描述符),否则管道中没有新行则命令“read”只能等待
– 命令“wait”,等待前面的命令“for”完全结束
– 命令“exec”,即第二个执行解除文件描述符“9”和变量“fifoFile”定义的管道文件的关联
注:
– 文件描述符可以使用的数量取决于Linux系统“ulimit”的定义设置(可以修改,理论上可以定义无限)
– 命令“exec”原则上支持关联“0~9”的文件描述符,但由于“0~2”被标准输入、标准输出和标准错误流占用因此无法使用。
参阅文档
==================
管道
———-
https://zh.wikipedia.org/wiki/%E7%AE%A1%E9%81%93_(Unix)
匿名管道
————
https://zh.wikipedia.org/wiki/%E5%8C%BF%E5%90%8D%E7%AE%A1%E9%81%93
命令管道
—————
https://zh.wikipedia.org/wiki/%E5%91%BD%E5%90%8D%E7%AE%A1%E9%81%93
没有评论