1. 管道基础
管道是为了解决进程间通信问题而存在 , 它可以让两个进程之间的数据进行传递 , 将一个进程的输出数据传递给另一个进程作为其输入数据。管道左边是数据给予方 , 管道右边是数据接收方。
echo "abcd" | passwd --stdin username : 表示将进程echo的输出结果abcd作为进程passwd的输入数据。
[root@centos7 ~]# ps aux | grep ssh
root 3455 0.0 0.1 112756 4320 ? Ss Aug23 0:00 /usr/sbin/sshd -D
root 4026 0.0 0.1 157152 6084 ? Ss Aug23 0:00 sshd: root@pts/0
root 4071 0.0 0.1 157148 6088 ? Ss Aug23 0:00 sshd: root@pts/1
root 4793 0.0 0.1 161364 6052 ? Ss 10:13 0:00 sshd: root@pts/2
root 5156 0.0 0.0 112708 976 pts/2 S+ 15:09 0:00 grep --color=auto ssh管道实现的是进程间通信 , 两个进程之间存在交叉 , 在运行ps进程后开始收集进程信息 , grep也已经开始并处于等待接收数据状态 , 当ps收集到任何数据后都将输出放入内存由管道传递给grep进行筛选。
管道其本质是数据传递 , 管道左边的输出数据放入内存 , 由管道右边的进程读取。假如内存不足以完全存放输出数据 , 则管道左边的进程将一直等待 , 直到管道右边取出内存中一部分的数据以让管道左边的进程继续输出 , 而管道右边的进程在管道左边的进程启动后也立刻启动了 , 但是它一直处于等待状态 , 等待接收管道传递来的数据。也就是说 , 管道左右两边的进程运行几乎是没有先后顺序的。
ps aux | grep "ssh"避免结果中出现grep自身的进程,方法有二:
#方法一
ps aux | grep "ssh" | grep -v "grep"
#方法二
ps aux | grep "ss[h]"方法一是应用grep的-v特性 , 方法二是应用正则表达式的特性。
在使用匿名管道的过程中 , 可能已经发现管道两边的进程是同属一个进程组的 , 也就是说管道左方的数据只能传递给管道右方的进程 , 其他任何进程都没法读取此数据。但除了匿名管道 , 还有命名管道 , 命名管道是将一个进程的数据存储到一个管道文件(fifo)中 , 其他进程可以读取该管道文件来读取其中的数据 , 也就是说不再限制数据读取方。
注意 : 管线符号
|仅能处理经由前面一个指令传来的正确信息 , 也就是standard output ( STDOUT )的信息, 对于stdandard error并没有直接处理的能力。
在管线命令当中 , 常常会使用到前一个指令的stdout作为这次的stdin , 某些指令需要用到文件名称 (例如tar) 来进行处理时 , 该stdin 与stdout 可以利用减号 -来替代*。举例来说:
$ tar -cvf - /home/test | tar -xvf -2. 重定向和管道的区别
乍看起来 , 管道也有重定向的作用 , 它也改变了数据输入输出的方向 , 那么 , 管道和重定向之间到底有什么不同呢?
简单地说 , 重定向操作符>将命令与文件连接起来 , 用文件来接收命令的输出 ; 而管道符|将命令与命令连接起来 , 用第二个命令来接收第一个命令的输出。如下所示:
command > file
command1 | command1有些读者在学习管道时会尝试如下的命令 , 我们来看一下会发生什么:
command1 > command2答案是 , 有时尝试的结果将会很糟糕。这是一个实际的例子 , 一个 Linux 系统管理员以超级用户 (root 用户 ) 的身份执行了如下命令:
cd /usr/bin
ls > less第一条命令将当前目录切换到了大多数程序所存放的目录 , 第二条命令是告诉 Shell 用 ls 命令的输出重写文件 less。因为 /usr/bin 目录已经包含了名称为 less (less 程序 ) 的文件 , 第二条命令用 ls 输出的文本重写了 less 程序 , 因此破坏了文件系统中的 less 程序。
这是使用重定向操作符错误重写文件的一个教训 , 所以在使用它时要谨慎。
参考链接