对于任何一个进程,在启动时,都会打开三个流:stdin(标准输入), stdout(标准输出), stderr(标准错误输出)。Stdout,stderr是process与Display之间,stdin是process与keyboard之间。也就是说系统的标准输入输出,是进程与设备间交流的桥梁。linux
可是在不少状况下,咱们的程序数据并不来自于标准输入,咱们在使用标准输出时,也不但愿写到显示器上,多是文件,网络,打印机等。这时候就须要IO Redirect来做用了。还有,为了方便使用等,咱们但愿将写到Stdout的数据做为另一个进程的输入,其实这也是IO redirect的一种,不过它有个特殊的名字——pipe。网络
操做系统内核会为每个进程分配不少file handler(也叫 File Description),其中初始时会分配3个handle,用数字0,1,2来表示,分别分配给了stdin, stdout, stderr。其余的则是随着须要分配的。app
这样一来,就能够直接使用0,1,2来表示Stdio了。操作系统
在linux上使用lsof -p pid查看一个进程打开了哪些文件。下面是一个查看运行中的top命令的状况:code
< 将标准输入(stdin, 0)重定向,也就是说数据来源不是键盘,而是其余,例如文件等。blog
> 将标准输出(stdout, 1)重定向,也就是说数据再也不写到显示器,而是其余地方。进程
其中在 >,< 操做符的左边,只能是FD,右边多是file,也能够是FD等。此外, <等价于 <1, >等价于1>,因此2> 就是将标准错误输出(stderr, 2)重定向。ip
IO redirect的本质是什么呢?在我看来本质是FD的赋值。怎么理解呢?pip
默认状况下一个,一个进程(例如:ls)是这样的:io
对于一个进程而言: #0 = keyboard #1 = display #2 = display
ls >a:表明了 fd1=a #0 = keyboard #1 = a #2 = display
Ls 3>a :表明了fd3=a
sort<file.txt :表明了fd0=file.txt
若是但愿在多个FD之间进行赋值运算,那么就用>&或者<&。
那么理解上仍是 >时赋值运算符,&则是dup2系统调用了。
2>&1的意思就是 对 FD1执行dup2,获得FD1的拷贝,而后赋值给FD2,也就是说FD1指向了谁,FD2也去指向谁。
例如:
3>file.txt 2>&3 表明了:FD3-->file.txt,那么FD2--->file.txt
须要注意的是:>自己不要求文件必须是存在的,可是通过了上述复制并赋值操做和后,启动进程之初就要准备好相应的流,此时就须要文件file.txt必须是存在的。
若是将stdout或者stderr 重定向到一个文件,但文件里已经有内容,会是什么结果呢?使用 > file时,文件中已有的内容会被truncate掉,也就是文件内容被清除了。
若是想要保留文件内容怎么办呢?
有一个变体操做符:>> 以append的方式重定向。
若是但愿将输出内容,直接做为另一个程序的输入,这种技术成为Pipe,可以进行Pipe的进程,必须是父子进程。用“|” 来表示管道。Pipe也是进程间通讯的一种技术。
例如:lsof -p pid | grep xxx ,父进程是 lsof, 子进程是grep。
本篇内容适用于 Windows,Linux,Unix等操做系统。