织梦网站默认密码忘记家居装修风格图片大全
一、文件描述符
文件描述符是一个非负整数。它是一个索引值,指向进程打开的文件。
Linux 程序在执行任何形式的 I/O 操作时,都是在读取或者写入一个文件描述符。
每个文件描述符会与一个打开的文件相对应
 不同的文件描述符也可能指向同一个文件
  
在Linux中,每一个进程打开时都会自动获取3个文件描述符0、1和2,分别表示标准输入、标准输出、和标准错误,如果要打开其他文件,则文件描述符必须从3开始标识。
| 文件描述符 | 文件名 | 类型 | 指向硬件 | 
|---|---|---|---|
| 0 | /dev/stdin | 标准输入文件 | 键盘 | 
| 1 | /dev/stdout | 标准输出文件 | 显示器 | 
| 2 | /dev/stderr | 标准错误输出文件 | 显示器 | 
 $ ll /dev/std*
 lrwxrwxrwx 1 root root 15 Apr 2 07:57 /dev/stderr -> /proc/self/fd/2
 lrwxrwxrwx 1 root root 15 Apr 2 07:57 /dev/stdin -> /proc/self/fd/0
 lrwxrwxrwx 1 root root 15 Apr 2 07:57 /dev/stdout -> /proc/self/fd/1
 $ ll /proc/self/fd/
 total 0
 lrwx------ 1 root root 64 Apr 6 03:53 0 -> /dev/pts/2
 lrwx------ 1 root root 64 Apr 6 03:53 1 -> /dev/pts/2
 lrwx------ 1 root root 64 Apr 6 03:53 2 -> /dev/pts/2
 lr-x------ 1 root root 64 Apr 6 03:53 3 -> /proc/14038/fd
 二、重定向
重定向分为两种,一种输入重定向,一种是输出重定向;从字面上理解,输入输出重定向就是「改变输入与输出的方向」的意思。可以把重定向理解为指向。
(一)输出重定向
输出重定向是指命令的结果不再输出到显示器上,而是输出到其它地方,一般是文件中。
这样做的最大好处就是把命令的结果保存起来,当我们需要的时候可以随时查询。
1.标准输出重定向
command 1>file 以覆盖的方式,把 command 的正确输出结果输出到 file 文件中。
command 1>>file 以追加的方式,把 command 的正确输出结果输出到 file 文件中。
2.标准错误重定向
command 2>file 以覆盖的方式,把 command 的错误信息输出到 file 文件中。
command 2>>file 以追加的方式,把 command 的错误信息输出到 file 文件中。
3.标准输出与标准错误同时重定向
command 1>file1 2>file2 以覆盖的方式,把正确的输出结果输出到 file1 文件中,把错误信息输出到 file2 文件中。
command 1>>file1 2>>file2 以追加的方式,把正确的输出结果输出到 file1 文件中,把错误信息输出到 file2 文件中。
command 1>file 2>file 以覆盖的方式,把正确输出和错误信息同时保存到同一个文件(file)中。
command 1>>file 2>>file 以追加的方式,把正确输出和错误信息同时保存到同一个文件(file)中。
【不推荐】这两种写法会导致 file 被打开两次,引起资源竞争,所以 stdout 和 stderr 会互相覆盖
注意
 1.输出重定向的完整写法是fd>file或者fd>>file,其中 fd 表示文件描述符,如果不写,默认为 1,也就是标准输出文件。
 当文件描述符为大于 1 的值时,比如 2,就必须写上。
 2.fd和>之间不能有空格,否则 Shell 会解析失败;>和file之间的空格可有可无。为了保持一致,我习惯在>两边都不加空格。
 4.用法举例
(1)
$ echo "菜鸟教程:www.runoob.com" > users
$ cat users
菜鸟教程:www.runoob.com
$ echo "菜鸟教程:www.runoob.com" >> users
$ cat users
菜鸟教程:www.runoob.com
菜鸟教程:www.runoob.com
(2)
$ ls java #先预览一下错误信息
 ls: 无法访问java: 没有那个文件或目录
 $ ls java 2>err.log #重定向
 $ cat err.log #查看文件
 ls: 无法访问java: 没有那个文件或目录
(3)
 $ ls -l >out.log 2>&1
 $ ls java >>out.log 2>&1
 $ cat out.log
 总用量 12
 drwxr-xr-x. 2 root root 21 7月 1 2016 abc
 -rw-r--r--. 1 mozhiyan mozhiyan 399 3月 11 17:12 demo.sh
 -rw-rw-r--. 1 mozhiyan mozhiyan 278 3月 16 17:17 main.c
 -rw-rw-r--. 1 mozhiyan mozhiyan 0 3月 22 17:39 out.log
 -rwxr-xr-x. 1 mozhiyan mozhiyan 187 3月 22 17:16 test.sh
 ls: 无法访问java: 没有那个文件或目录
  
5./dev/null 文件
 如果你既不想把命令的输出结果保存到文件,也不想把命令的输出结果显示到屏幕上,干扰命令的执行,那么可以把命令的所有结果重定向到 /dev/null 文件中。如下所示:ls -l &>/dev/null
 大家可以把 /dev/null 当成 Linux 系统的垃圾箱,任何放入垃圾箱的数据都会被丢弃,不能恢复。
 (二)输入重定向
输入重定向就是改变输入的方向,不再使用键盘作为命令输入的来源,而是使用文件作为命令的输入。
命令必须能以标准输入作为参数。
1.command 0<file 将 file 文件中的内容作为 command 的输入。
2.command 0<<END 从标准输入(键盘)中读取数据,直到遇见分界符 END 才停止(分界符可以是任意的字符串,用户自己定义)。
这种方式也叫here document。
Here Document
 Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。
 它的基本的形式如下:
 command << delimiter
 document
 delimiter它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command(不包括分界符本身)。而不使用 Ctrl+D 键。
注意:
- 结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。
 - 开始的delimiter前后的空格会被忽略掉。
 
  
输入重定向的完整写法是fd<file,其中 fd 表示文件描述符,如果不写,默认为 0,也就是标准输入文件。
 3.用法举例
(1)
统计文档中有多少行文字。
 我们需要统计 users 文件的行数,执行以下命令:
 $ wc -l users
 2 users也可以将输入重定向到 users 文件:
 $ wc -l < users
 2 注意:上面两个例子的结果不同:第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容。 
 (2)逐行读取文件内容。#!/bin/bash
 while read str; do
 echo $str
 done <readme.txt运行结果:
 C语言中文网
 http://c.biancheng.net/
 成立7年了
 日IP数万
 这种写法叫做代码块重定向,也就是把一组命令同时重定向到一个文件。
 (3)
 在命令行中通过 wc -l 命令计算 Here Document 的行数:
 $ wc -l << EOF
 欢迎来到
 菜鸟教程
 www.runoob.com
 EOF
 3
 我们也可以将 Here Document 用在脚本中,例如:
 #!/bin/bash
 # author:菜鸟教程
 # url:www.runoob.com
 cat << EOF
 欢迎来到
 菜鸟教程
 www.runoob.com
 EOF执行以上脚本,输出结果:
 欢迎来到
 菜鸟教程
 www.runoob.com
 (三)输入和输出同时重定向
 command 0<file1 1>file2 将 file1 作为 command 的输入,并将 command 的处理结果输出到 file2。 
(四)文件描述符复制
文件描述符的复制表示将一个文件描述符指向另一个文件描述符指向的文件。使用”&”进行复制。
- n<&m:n指向m指向的文件。作为输入
 - n>&m:n指向m指向的文件。作为输出
 
例如,3>&1表示3指向1指向的文件,1指向的文件是/dev/stdout,3也重定向到/dev/stdout,以后进程将数据写入3的时候,将直接输出到屏幕。这里的3>&1等价于3>/dev/stdout。如果后面改变了1的输出目标(如file1),由于3的目标仍然是/dev/stdout,所以可以拿3来还原1使其目标变回/dev/stdout。
为什么不用n<m与n>m呢?
因为<与>后面必须是文件名,不支持文件描述符。如果使用2>1,它会把1解释成文件名。所以就有了&,专门用来处理两个文件描述符的重定向。
command 1>file 2>&1 以覆盖的方式,把正确输出和错误信息同时保存到同一个文件(file)中。
command 1>>file 2>&1 以追加的方式,把正确输出和错误信息同时保存到同一个文件(file)中。
command &> file 以覆盖的方式,把正确输出和错误信息同时保存到同一个文件(file)中。
command &>> file 以追加的方式,把正确输出和错误信息同时保存到同一个文件(file)中。
&>是一种特殊写法,&>file等价于>file 2>&1.
 (五)重定向的执行顺序
重定向顺序很重要:>file 2>&1和2>&1 >file是不同的。
>file 2>&1。这里分两个过程:先将1重定向到file文件;之后再将2指向1,1此时已经重定向到file文件上,因此2也重定向到file。所以,最终的结果是标准输出重定向到file,标准错误也重定向到file。
2>&1 >file。这里也分两个过程:先将2指向1,而此时1重定向的文件是默认的/dev/stdout,所以2也重定向到/dev/stdout;之后再将1重定向到file文件。也就是说,这里的标准错误和标准输出仍然是分开输出的。所以,最终的结果是标准错误输出到/dev/stdout,即屏幕上,而标准输出将输出到file文件中。
可以使用下面的命令来测试2>&1 >file。第一个ls命令是正确的,结果输出到/tmp/a.log中,第二个ls命令是错误的,结果将直接输出到屏幕上。
$ ls /boot 2>&1 >/tmp/a.log
 $ ls sjdfk 2>&1 >/tmp/a.log
 ls: cannot access sjdfk: No such file or directory
