Fork me on GitHub

Linux I/O重定向

文件描述符(File Descriptor)

维基百科:文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。

Linux 的shell命令,可以通过文件描述符来引用一些文件,通常使用到的文件描述符为0,1,2,即:

文件 文件描述符 操作符
输入文件—标准输入(stdin) 0(默认是键盘,为0时是文件或者其他命令的输出) < 或 <<
输出文件—标准输出 (stdout) 1(默认是屏幕,为1时是文件) >, >>, 1> 或 1>>
错误输出文件—标准错误(stderr) 2(默认是屏幕,为2时是文件) 2> 或 2>>

输出重定向

命令 描述
Command > filename 把标准输出重定向到一个新文件中
Command >> filename 把标准输出重定向到一个文件(追加)
Command > filename 2>&1 把标准输出和错误一起重定向到一个文件中
Command &> filename 同上
Command >> filename 2>&1 把标准输出和错误一起重定向到一个文件中(追加)
Command &>> filename 同上
Command 2> filename 把标准错误重定向到一个文件中
Command 2>> filename 把标准错误重定向到一个文件中(追加)
Command 1> filename 2> filename1 把标准输出和标准错误分别重定向到两个不同新的文件中
Command 1>> filename 2>> filename1 把标准输出和标准错误分别重定向到两个不同的文件中(追加)
Command tee filename 让标准输出在屏幕显示,同时重定向一个新的文件
Command | tee -i filename 同上,但是不接受中断信号,只能Ctrl+D结束,不能用Ctrl+C
Command | tee -a filename 让标准输出在屏幕显示,同时重定向一个文件(追加)
Command 2>&1 | tee filename 让标准输出和标准错误在屏幕显示,重定向到一个新的文件中
Command 2>&1 | tee -a filename 让标准输出和标准错误在屏幕显示,重定向到一个文件中(追加)

1、Linux下还有一个特殊的文件/dev/null,它就像一个无底洞,所有重定向到它的信息都会消失得无影无踪。这一点非常有用,当我们不需要回显程序的所有信息时,就可以将输出重定向到/dev/null,例如:

ls xxx 1>/dev/null 2>/dev/null 或 ls >/dev/null 2>&1

2、使用操作符 > 或 >> 时,默认为标准输出1重定向, 所以 >filename 就是 1>filename 的省写,1与>之间不能有空格
3、>操作符,判断右边文件是否存在,若存在先删除,再创建新文件。不存则创建。 无论左边命令执行是否成功。右边文件都会变为空。
4、>>操作符,判断右边文件是否存在,若不存在,则先创建。以添加方式打开文件,会分配一个文件描述符[不特别指定,默认为1]然后,与左边对应的输出绑定。
5、管道 (“|”, pipe line),把上一个命令的 stdout 接到下一个命令的 stdin;
6、tee 命令的作用是在不影响原本 I/O 的情况下,将 stdout 复制一份到档案去;

例如:执行 who 命令,将命令的完整的输出重定向在文件中(/tmps/users),即:

who > /tmp/users

使用 cat 命令查看文件内容:

$ cat users
jason    console  Jan 11 09:05 
jason    ttys000  Jan 11 09:06 
jason    ttys001  Jan 11 09:06 
jason    ttys006  Jan 11 09:45

输入重定向

命令 描述
Command < filename Command 命令以 filename 文件作为标准输入
Command < filename > filename1 Command以 filename 文件作为标准输入,以 filename1 作为标准输出
Command << delimiter 从标准输入中读入,直到遇到 delimiter 分界符(以 delimiter 为开始/结束符)

以上述who命令为例:
1、输入重定向到 users 文件,即:

$ wc -l < users
4  

2、Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。 它的基本的形式如下:

command << delimiter
    document
delimiter

它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。

注意:
结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。
开始的delimiter前后的空格会被忽略掉。

例如:

$ wc -l << EOF
    jason
    jake
    jacky
EOF
3 # 输出结果为 3 行            

绑定重定向

命令 描述
Command m>&n 把输出到文件描述符m的信息重定向到文件描述符n上。如 exec 6>&1
Command m<&n 把文件描述符n的信息输入到文件描述符m上。如 exec 6<&0
Command n<&- 关闭输入文件描述符n。如 0<&-, <&- 关闭标准输入
Command n>&- 关闭输出文件描述符n。如 1>&-, >&- 关闭标准输出,2>&- 关闭标准错误输出

0、1、2为shell保留文件描述符,可以自定义文件描述符,对其进行读写,用户自定义文件描述符用exec命令进行创建。用户可以自定义文件描述符围是:3~MAX,
这个最大数字,跟用户的:ulimit –n 定义数字有关系,不能超过最大值。

附:Mac下文件描述符的链接关系:

$ ls -al /dev/std* /dev/fd/*
crw--w----  1 jason  tty     16,   7 Jan 11 15:18 /dev/fd/0
crw--w----  1 jason  tty     16,   7 Jan 11 15:18 /dev/fd/1
crw--w----  1 jason  tty     16,   7 Jan 11 15:18 /dev/fd/2
lr-xr-xr-x  1 root   wheel         0 Jan 11 09:05 /dev/stderr -> fd/2
lr-xr-xr-x  1 root   wheel         0 Jan 11 09:05 /dev/stdin -> fd/0
lr-xr-xr-x  1 root   wheel         0 Jan 11 09:05 /dev/stdout -> fd/1
轻轻的我走了,正如我轻轻的来