数据流重定向

来源:互联网 发布:数据库服务器选择 编辑:程序博客网 时间:2024/05/17 02:22

         对于内核而言,所有打开的文件都是通过文件描述符引用。文件描述符是一个非负整数,当进程打开或创建一个文件时,内核向进程返回一个文件描述符。当读写文件时,文件描述作为一个标志,标识该文件(如系统调用read和write函数)。

        UNIX系统shell把文件描述符0与进程的标准输入相关联,把文件描述符1与进程的标准输出相关联,把文件描述符2与进程的标准错误关联。这些描述符被宏定义为符号常量。在/usr/include/unistd.h中可以查找到宏定义,如下:

/* Standard file descriptors.  */#defineSTDIN_FILENO    0/* Standard input.  */#defineSTDOUT_FILENO1/* Standard output.  */#defineSTDERR_FILENO2/* Standard error output.  */

        有时候我们也许会看STDIN,STDOUT,STDERR。这些和上述所说的引用相同,但这些是由C标准库stdio.h提供的,而上述的是系统调用函数库unistd.h提供的。一般Linux命令行的输入输出(就是键盘输入,终端显示)是由系统调用实现的。

        数据流重定向是将某个命令执行后,将结果显示在屏幕的数据传输到其他地方,将由键盘输入的数据,替代为从某个文件读入数据。

       执行一个命令,通常它是按如下方式进行:




         当执行一个命令时,命令从文件有标准输入读取,经过处理,若命令执行所回传正确的信息,由标准输出显示到终端。若命令执行失败,回传的错误信息由标准错误输出到终端。


Standard Output,Standard Error

        我们不能将错误和正确的信息都传送到屏幕,因此采用数据流输出重定向功能,可以将标准输出,标准错误分别传送到不同的文件和设备中。重定向采用的符号如下:

1、 标准输入(STDIN_FILENO)    使用<或<< ;

2、 标准输出(STDOUT_FILENO)  使用>或>>(1>或1>>) ;

3、 标准错误(STDERR_FILENO)    使用2>或2>> ;

注:上面提到,0与标准输入关联,1与标准输出关联,2与标准错误关联。使用>或>>,1>或1>> 表示标准输出重定向。

列出当前桌面所有文件

kernel@Ubuntu:~/Desktop$ lsC++ UNIX

请留意现在桌面文件

将输出的信息重定向到一个当前不存在的文件夹中

kernel@Ubuntu:~/Desktop$ ls > file kernel@Ubuntu:~/Desktop$

现在终端什么也没有输出,因为已经将本来应该显示到屏幕的数据重定向到file文件中。查看刚才将数据重定向的文件内容

kernel@Ubuntu:~/Desktop$ cat file C++file

为什么会多出一个刚才重定向的文件?若重定向的文件(本例为file)不存在,系统会自动创建该文件。所以将ls执行后所输出的数据就多了file这个文件。

再一次向file文件重定向一个不同于上次的数据,结果会如何?

kernel@Ubuntu:~/Desktop$ ll C++/ > file kernel@Ubuntu:~/Desktop$ cat file总用量 36drwxrwxr-x 3 kernel kernel  4096  4月 14 13:39 ./drwxr-xr-x 5 kernel kernel  4096  5月 19 21:16 ../-rw-rw-r-- 1 kernel kernel     0  4月 12 20:10 Client.cpp-rw-r--r-- 1 kernel kernel 12288  4月 14 13:41 .Client.cpp.swpdrwxrwxr-x 2 kernel kernel  4096  5月  8 23:58 HTTP/-rw-r--r-- 1 kernel kernel 12288  4月 12 17:51 .server.cpp.swp

File文件的内容被第二次重定向的数据给覆盖,所以> 或1> 下一次的数据会覆盖原先的数据。如果想要数据只是叠加而不是覆盖原先数据,使用>> 或 1>> 。

刚才的处理只是将正确的数据重定向到文件,如果出现错误,依旧会显示在终端。因此可以将标准输出与标准错误分别重定向到两个不同的文件。

kernel@Ubuntu:~/Desktop$ find /home -name .bashrc/home/kernel/.bashrcfind: `/home/kernel/.gvfs': 权限不够find: `/home/kernel/.cache/dconf': 权限不够/home/kernel/Desktop/.bashrc
现在把上面出现的正确数据与错误数据重定向到两个文件。

kernel@Ubuntu:~/Desktop$ find /home -name .bashrc > list_right 2> list_errorkernel@Ubuntu:~/Desktop$ cat list_right/home/kernel/.bashrc/home/kernel/Desktop/.bashrckernel@Ubuntu:~/Desktop$ cat list_error find: `/home/kernel/.gvfs': 权限不够find: `/home/kernel/.cache/dconf': 权限不够

现在两个文件分别存储了正确和错误的数据。

我的理解是这样的:可以把标准输出和标准错误当作两条输出数据的管道(我理解的标准错误其实也可以当作标准输出,不过它输出的是错误信息)。两条管道在没有重定向之前是在命令执行完成之后,将管道的数据默认传送到终端。在重定向后,相当于把管道输出的端口指向文件或其他设备。

如果要把标准输出与标准错误重定向一个文件,是不是可以按照上面的做法来实现呢?

kernel@Ubuntu:~/Desktop$ find /home -name .bashrc > list 2> listkernel@Ubuntu:~/Desktop$ cat listfind: `/home/kernel/./home/kernel/Desktop/.bashrcome/kernel/.cache/dconf': 权限不够
结果只有标准出错。那是不是就意味着标准输入和标准输出同时进行覆盖重定向的时候,只有标准出错? 答案是否定的。因为两个输出同时重定向一个文件很类似于fork()函数生成的子进程与父进程之间执行的竞争关系,所以重定向之后文件的数据是很不确定的,两条数据交叉写入文件时,可能造成次序混乱。因此可以采用以下方法:

kernel@Ubuntu:~/Desktop$ find /home -name .bashrc >list 2>&1kernel@Ubuntu:~/Desktop$ cat list/home/kernel/.bashrcfind: `/home/kernel/.gvfs': 权限不够find: `/home/kernel/.cache/dconf': 权限不够/home/kernel/Desktop/.bashrc

这个可以这样理解,现在有标准输出和标准错误两条管道,现在将标准错误的管道插到标准输出的管道中,现在标准输出的管道中就有标准输出和标准错误的数据。2>&1就表示将标准错误的数据重定向到标准输出。

注:一定要注意&这个符号,如果没有加上这个符号,2>1就表示标准错误重定向到文件名为1的文件中,而不是重定向到标准输出。


Standard Input

标准输入一般是指由键盘输入(STDIN_FILENO),将输入的数据写入到指定的文件。

cat命令是直接查看文件内容(当前用户可读的前提下)。若后面不加参数,将从键盘接受数据

kernel@Ubuntu:~/Desktop$ cat testingtesting# [ctrl]+d退出

输入的数据,直接显示在当前终端下,利用标准输出重定向,将输入的数据写到文件。

kernel@Ubuntu:~/Desktop$ cat > catfiletesting cat file test# [ctrl]+d退出

kernel@Ubuntu:~/Desktop$ cat catfile testing cat file test

现在应该大致理解了键盘输入是怎么一回事了吧。接下来,将键盘输入重定向到读取某个文件的内容。这次读取上一次的list文件。

kernel@Ubuntu:~/Desktop$ cat > catfile < listkernel@Ubuntu:~/Desktop$ cat catfile /home/kernel/.bashrcfind: `/home/kernel/.gvfs': 权限不够find: `/home/kernel/.cache/dconf': 权限不够/home/kernel/Desktop/.bashrc

再查看下两个文件的信息

kernel@Ubuntu:~/Desktop$ ll list catfile -rw-rw-r-- 1 kernel kernel 139  5月 19 23:39 catfile-rw-rw-r-- 1 kernel kernel 139  5月 19 23:21 list

如果对这个cat > catfile < list 不好理解,可以这样去想:可以把cat > catfile当作一个整体,catfile文件本来要接受来自键盘的输入,可是现在将标准输入的管道重定向到一个文件,于是标准输入就去读取list文件的内容并将list文件的内容经标准输出重定向到catfile文件。于是就可以理解cat catfile 与 cat < catfile的区别了。前面所说cat不加参数是等待键盘输入,那现在给它重定向到一个文件,去读取文件的内容并显示。而cat catfile是直接去显示文件内容,没有经过重定向。

标准输出与标准错误的 >> 是向重定向的文件尾继续添加数据。那标准输入也是如此吗?

kernel@Ubuntu:~/Desktop$ cat > catfile <<"EOF"> testing> stop> EOF

可以利用<<右侧的控制字符,终止输入,而不需要[ctrl]+d来退出,并且文件的内容也改变了,并没有叠加的作用。

kernel@Ubuntu:~/Desktop$ cat catfile testingstop

总结:

使用重定向可以将屏幕输出的一些重要的信息保存到文件。如果后台有程序执行并且有相应的输出,可以将输出重定向到文件,以避免干扰屏幕的正常输出。

在刚开始对重定向不好理解的时候,可以将其看作管道,不是真的那个管道命令。可以方便理解和使用重定向。现在所说的输入输出都是系统调用来完成的,是直接对内核进行操作,用来完成对磁盘的读,写操作。

                                             
1 0