管道操作符 : |
我们在Linux下经常要用到管道操作符,也就是"|",即一个竖线。 这个操作符的作用对于经常使用Linux的人来说,看上去十分直观:
不就是将前一个指令的结果交给后一个指令吗?
举个例子:
代码语言:javascript复制cat system.log | grep hello
复制代码
上面的指令可以让我们过滤出system.log
这个文件中包含hello
字符串的行,然后打印到屏幕上。
什么叫指令的结果
问题就来了,一个指令的结果是什么,这个说法十分混淆。
是指这个指令输出的日志? 是指这个指令的返回码?(有些人可能不知道这东西) 还是指啥啥啥的?
实际上,指令的结果
这个概念并没有一个严格定义,所以当我们说,一个指令的结果
的时候,经常跟业务场景有关系。比如说,一个图像处理程序的结果,就应该是一个图像,这才是合乎常理的。
如何描述 cat 指令的行为
首先我们来看一下 cat system.log
这个指令的行为。
也就是将 system.log
中的内容打印到屏幕上。
这个过程可以细说,因为将内容打印到屏幕上
实际上还是不够准确。
那么这里就不得不牵扯出Linux下文件的一些概念。
程序打开文件以及文件描述符
在 Linux 系统中,一个程序是可以打开一个文件的,这个很容易理解。
那么进程(一般正在运行的程序称之为进程
)是如何管理文件的呢?
那就是用文件描述符
这种东西,这是一个数字以及与之相关联的一堆数据。
一个进程打开一个文件,就会创建一个新的文件描述符,这个数字一般是自增的。比如说,当前的文件描述符是100。那么再打开一个新的文件,这个新的文件的描述符就是101。当然进程如果关闭文件,这个描述符是可以重复利用的。这里不多扯。
如果用图来表示这个概念,应该是下面的样子:
我们可以看出,不同的数字代表了不同的文件。
那么在哪里能列出一个进程所打开的文件呢?
在Linux下,可以先找到这个进程的PID,假设是 20000
进入如下的目录:
代码语言:javascript复制cd /proc/20000/fd
复制代码
这个目录存放的就是 20000 这个进程所打开的文件了。ls一下,如图:
正如我所描述的那样,都是数字。
一些约定俗成的描述符
从上面的图中,我们看到,描述符是从0开始的。 那么0是什么文件呢?
在Linux
下,每一个进程启动的时候,都会默认打开三个文件,用0 ,1, 2
来当做他们的描述符。
那么0, 1, 2
分别代表哪三个文件呢?
- 0 : 代表标准输入
- 1 : 代表标准输出
- 2 : 代表错误输出
也许上面的描述,还是不够清晰。
再进一步,一般来说,
- 标准输入,就是指
键盘输入
- 标准输出,就是指
输出到屏幕
- 错误输出,也是指
输出到屏幕
文件描述符的作用
如果你在Linux下,写过读取键盘输入的程序,那么就这样理解。
你读取的其实就是 0
这个描述符所代表的文件的内容:也就是键盘。
如果你使用过类似 print
这种函数,打印过日志的话,那么其实就是往 1
这个描述符所代表的文件里输出内容,对,这个内容通过屏幕展现出来了。
实际上,这种读取和写入的操作,对于所有文件来说都是一样的,至少在使用上来说,是一样的。
都是先打开一个文件,给他一个描述符,然后针对这个描述符
进行读或者写。
文件和键盘输入的关系
键盘输入这种操作,在Linux里,会变成一个文件操作,就类似普通的文件那样。
这就是Linux的设计,一切皆是文件
。不仅仅键盘操作
和屏幕打印
是文件操作。
网络连接读取数据
啥的,也都是文件操作,这些也都会产生文件描述符。
一个进程同时拥有的文件描述符是有上限的,这个上限可以设置。
如果你不信,你可以试试同时打开一万个文件,看看会不会报错,如果报错,观察一下是报的什么错。
可能是这样的错误:
代码语言:javascript复制too many opened files
复制代码
回到管道操作符 |
代码语言:javascript复制cat system.log | grep hello
复制代码
我们现在再来描述上面整个指令:
1. cat system.log
cat
这个程序打开了system.log
这个文件,将system.log
的内容,写入 1
这个文件,也就是屏幕上。
2. grep hello
grep
这个程序,试图从 0
这个文件中读取数据,然后找到包含hello
的行,然后把找到的行,写入到1
这个文件中,也就是屏幕上
3. 管道的作用
就是将前一个程序的1
绑定到后一个程序的0
。
于是,整体才会走通,要不然,cat
的结果就会打印到屏幕,而不是给了 grep
。
最后
完整源码下载地址:https://market.cloud.tencent.com/products/33396
PHP学习手册:https://doc.crmeb.com 技术交流论坛:https://q.crmeb.com