shell 重定向以及文件描述符
1.对重定向的理解
- Linux Shell 重定向分为两种,一种输入重定向,一种是输出重定向;从字面上理解,输入输出重定向就是「改变输入与输出的方向」的意思。
- 输入方向就是数据从哪里流向程序。标准输入方向是指数据从键盘流向程序,如果改变了它的方向,数据就从其它地方流入,这就是输入重定向。
- 输出方向就是数据从程序流向哪里。标准输出方向是指数据从程序流向显示器,如果改变了它的方向,数据就流向其它地方,这就是输出重定向。
2.硬件设备和文件描述符
计算机的硬件设备有很多,常见的输入设备有键盘、鼠标、麦克风、手写板等,输出设备有显示器、投影仪、打印机等。不过,在 Linux 中,标准输入设备指的是键盘,标准输出设备指的是显示器。
Linux系统中把一切都看做文件,包括普通文件-、目录文件d、字符设备文件c、块设备文件b、符号链接文件l以及标准输入设备(键盘)和标准输出设备(显示器)在内的所有计算机硬件都是文件。
文件描述符是内核为了高效管理已被打开的文件所创建的索引(一个非负整数),用于指代已被打开的文件。
Linux下所有的的I/O操作的系统调用都是通过文件描述符执行,一个文件描述符只是一个和打开的文件相关联的整数,它的背后可能是一个硬盘上的普通文件、FIFO、管道、终端、键盘、显示器,甚至是一个网络连接。例如0表示标准输入(键盘)、1表示标准输出(显示器)、2表示标准错误(显示器),文件描述符会在这个基础上递增。
stdin、stdout、stderr 默认都是打开的,在重定向的过程中,0、1、2 这三个文件描述符可以直接使用。
表1:与输入输出有关的文件描述符
| 文件描述符 | 文件名 | 类型 | 硬件 |
|---|---|---|---|
| 0 | stdin | 标准输入文件 | 键盘 |
| 1 | stdout | 标准输出文件 | 显示器 |
| 2 | stderr | 标准错误输出文件 | 显示器 |
文件描述符到底是什么
文件描述符: 在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。
一个 Linux 进程启动后,会在内核空间中创建一个 PCB 控制块,PCB 内部有一个文件描述符表(File descriptor table),记录着当前进程所有可用的文件描述符,也即当前进程所有打开的文件。
除了文件描述符表,系统还需要维护另外两张表:
- 打开文件表(Open file table)
- i-node 表(i-node table)
文件描述符表每个进程都有一个,打开文件表和 i-node 表整个系统只有一个,它们三者之间的关系如下图所示。

文件描述符表: 进程级的列表,也就是用户区的一部分,进程每打开一个文件就会新建一个文件描述符。
系统级打开文件表: 系统级的列表,对当前系统的所有进程都共享,每条条目包含文件偏移量、访问模式以及指向它的文件描述符的条目计数
文件系统索引节点表: inode索引节点表(UID、GID、ctime、mtime、atime、读写执行权限、链接数、block位置)
| 进程级文件描述符 | 系统级打开文件表 | i-node表 |
|---|---|---|
|
1.文件描述符标志 2.文件指针(open file handle) 通过文件描述符,可以找到文件指针,从而进入打开文件表 |
1.文件偏移量,也就是文件内部指针偏移量。调用 read() 或者 write() 函数时,文件偏移量会自动更新,当然也可以使用 lseek() 直接修改。 2.状态标志,比如只读模式、读写模式、追加模式、覆盖模式等。 3.i-node 表指针。 要想真正读写文件,要通过打开文件表的 i-node 指针进入 i-node 表 |
1.文件类型,例如常规文件、套接字或 FIFO。 2.文件大小。 3.时间戳,比如创建时间、更新时间。 4.文件锁。 |
对上图的进一步说明:
- 在进程 A 中,文件描述符 1 和 20 都指向了同一个打开文件表项,标号为 23(指向了打开文件表中下标为 23 的数组元素),这可能是通过调用 dup()、dup2()、fcntl() 或者对同一个文件多次调用了 open() 函数形成的。
- 进程 A 的文件描述符 2 和进程 B 的文件描述符 2 都指向了同一个文件,这可能是在调用 fork() 后出现的(即进程 A、B 是父子进程关系),或者是不同的进程独自去调用 open() 函数打开了同一个文件,此时进程内部的描述符正好分配到与其他进程打开该文件的描述符一样。
- 进程 A 的描述符 0 和进程 B 的描述符 3 分别指向不同的打开文件表项,但这些表项均指向 i-node 表的同一个条目(标号为 1976);换言之,它们指向了同一个文件。发生这种情况是因为每个进程各自对同一个文件发起了 open() 调用。同一个进程两次打开同一个文件,也会发生类似情况。
有了以上对文件描述符的认知,我们很容易理解以下情形:
- 同一个进程的不同文件描述符可以指向同一个文件;
- 不同进程可以拥有相同的文件描述符;
- 不同进程的同一个文件描述符可以指向不同的文件(一般也是这样,除了 0、1、2 这三个特殊的文件);
- 不同进程的不同文件描述符也可以指向同一个文件。
文件描述符、文件、进程之间的关系
每个文件描述符都指向一个打开的文件相对应
不同的文件描述符可能指向同一个打开的文件
相同的文件可能被不同的进程打开,也可以在被同一个进程打开多次
Linux Shell 输出重定向
输出重定向是指命令的结果不再输出到显示器上,而是输出到其它地方,一般是文件中。这样做的最大好处就是把命令的结果保存起来,当我们需要的时候可以随时查询。Bash 支持的输出重定向符号如下表所示。
在输出重定向中,>代表的是覆盖,>>代表的是追加。
注意点:
- 输出重定向的写法是
fd>file或者fd>>file,其中 fd 表示文件描述符,如果不写,默认为 1,也就是标准输出文件。即command 1>file与command >file相同,当文件描述符为大于 1 的值时,比如 2,就必须写上。 fd和>之间不能有空格,否则 Shell 会解析失败;>和file之间的空格可有可无- /dev/null 文件。如果想要将输出结果丢弃,可以将命令结果重定向到 /dev/null 文件中,即 ls -l &>/dev/null,任何放入垃圾箱的数据都会被丢弃,不能恢复。
| 命令 | 结果 | 实际执行 | |
|---|---|---|---|
1和>之间有空格 |
echo "c.biancheng.net" 1 >log.txt cat log.txt |
c.biancheng.net 1 | echo "c.biancheng.net" 1 1>log.txt |
表2:Bash 支持的输出重定向符号
| 类 型 | 符 号 | 作 用 | 举栗 |
|---|---|---|---|
| 标准输出重定向 | command >file | 以覆盖的方式,把 command 的正确输出结果输出到 file 文件中。 |
将 [c.biancheng.net]$ ls -l #先预览一下输出结果 |
| command >>file | 以追加的方式,把 command 的正确输出结果输出到 file 文件中。 |
将 echo 命令的输出结果以追加的方式写入到 demo.txt 文件中。
运行脚本,查看文件demo.txt内容,显示如下: |
|
| 标准错误输出重定向 | command 2>file | 以覆盖的方式,把 command 的错误信息输出到 file 文件中。 |
命令正确执行是没有错误信息的,我们必须刻意地让命令执行出错,如下所示: [c.biancheng.net]$ ls java #先预览一下错误信息 |
| command 2>>file | 以追加的方式,把 command 的错误信息输出到 file 文件中。 | ||
| 正确输出和错误信息同时保存 | command >file 2>&1 | 以覆盖的方式,把正确输出和错误信息同时保存到同一个文件(file)中。 |
正确输出和错误信息同时保存【实例1】把正确结果和错误信息都保存到一个文件中,例如: [c.biancheng.net]$ ls -l >out.log 2>&1 out.log 的最后一行是错误信息,其它行都是正确的输出结果。 |
| command >>file 2>&1 | 以追加的方式,把正确输出和错误信息同时保存到同一个文件(file)中。 | ||
| command >file1 2>file2 | 以覆盖的方式,把正确的输出结果输出到 file1 文件中,把错误信息输出到 file2 文件中。 | ||
| command >>file1 2>>file2 | 以追加的方式,把正确的输出结果输出到 file1 文件中,把错误信息输出到 file2 文件中。 |
上面的实例将正确结果和错误信息都写入同一个文件中,这样会导致视觉上的混乱,不利于以后的检索, 所以我建议把正确结果和错误信息分开保存到不同的文件中,也即写成下面的形式: ls -l >>out.log 2>>err.log 这样一来,正确的输出结果会写入到 out.log,而错误的信息则会写入到 err.log。 |
|
| command >file 2>file | 【不推荐】这两种写法会导致 file 被打开两次,引起资源竞争,所以 stdout 和 stderr 会互相覆盖 | ||
| command >>file 2>>file |
Linux Shell 输入重定向
输入重定向就是改变输入的方向,不再使用键盘作为命令输入的来源,而是使用文件作为命令的输入。
和输出重定向类似,输入重定向的完整写法是fd<file,其中 fd 表示文件描述符,如果不写,默认为 0,也就是标准输入文件。
表3:Bash 支持的输出重定向符号
| 符号 | 说明 | 举栗 |
|---|---|---|
| command <file | 将 file 文件中的内容作为 command 的输入。 | 统计 readme.txt 文件中有多少行文本:
[c.biancheng.net]$ cat readme.txt #预览一下文件内容 |
| command <<END |
从标准输入(键盘)中读取数据,直到遇见分界符 END 才停止 (分界符可以是任意的字符串,用户自己定义)。 输入重定向符号
|
统计用户在终端输入的文本的行数。 > 123 wc 命令会一直等待用输入,直到遇见分界符 END 才结束读取。 |
| command <file1 >file2 | 将 file1 作为 command 的输入,并将 command 的处理结果输出到 file2。 | |
|
代码块重定向 {}<file1 |
逐行读取文件内容。
#!/bin/bash while read str; do 运行结果: |
总结:
- 本来1----->屏幕 (1指向屏幕)
- 执行>log后, 1----->log (1指向log)
- 执行2>&1后, 2----->1 (2指向1,而1指向log,因此2也指向了log)
- 本来1----->屏幕 (1指向屏幕)
- 执行2>&1后, 2----->1 (2指向1,而1指向屏幕,因此2也指向了屏幕)
- 执行>log后, 1----->log (1指向log,2还是指向屏幕)
- /dev/null 代表空设备文件
- 2 表示stderr标准错误,& 表示等同于的意思,2>&1,表示2的输出重定向等同于1
- 1 表示stdout标准输出,系统默认值是1,所以">/dev/null"等同于 "1>/dev/null"
参考文献: https://www.cnblogs.com/yujianfei/p/9068472.html
shell 重定向以及文件描述符的更多相关文章
- 18 shell 重定向以及文件描述符
1.对重定向的理解 2.硬件设备和文件描述符 文件描述符到底是什么 3.Linux Shell 输出重定向 4.Linux Shell 输入重定向 5.结合Linux文件描述符谈重定向 6.Shell ...
- linux shell exec 关联文件描述符
在写shell脚本时,如果多个命令的输入或输出都是同一个文件,而这个文件的路径和名字都很长,则需要书写很多次同样的路径会很浪费时间,我们可以使用exec命令来关联一个自定义的文件描述符到一个特定的文件 ...
- Linux Shell 文件描述符 及 stdin stdout stderr 重定向
Abstract: 1) Linux Shell 命令的标准输入.标准输出.标准错误,及其重定位: 2)Linux Shell 操作自定义文件描述符: 文件描述符是与文件相关联的一些整数,他们保持与已 ...
- 自学Linux Shell14.2-在脚本中使用其他文件描述符
点击返回 自学Linux命令行与Shell脚本之路 14.2-在脚本中使用其他文件描述符 在脚本中重定向输入和输出,并布局限于以上讲的3个默认的文件描述符,shell最多可以有9个打开的文件描述符.这 ...
- exec操作文件描述符
exec命令可以用来替代当前shell:换句话说,并没有启动子shell.使用这一命令时任何环境都将被清除,并重新启动一个shell. 它的一半形式为: exec command 其中,command ...
- Unix系统编程()复制文件描述符
Bourne shell的IO重定向语法2>&1,意在通知shell把标准错误(文件描述符2)重定向到标准输出(文件描述符1).因此下列命令将把标准输出和标准错误写入result.log ...
- linux中文件描述符
:: # cat ping.txt PING baidu.com (() bytes of data. bytes from ttl= time=32.1 ms bytes from ttl= tim ...
- Shell重定向文件描述符
#!/bin/bash 最近在看shell,各种困惑,不过解决困惑的感觉还是很不错的.废话少说,linux中使用文件描述符来标识每个文件对象.文件描述符为一个非负整数,可以唯一标识会话中打开 ...
- 【Shell脚本学习指南笔记】重定向文件描述符 2>&1
如: make > results 2>&1 重定向 > results让文件描述符1(标准输出)作为文件results,接下来的重定向2>&1有两个部分.2& ...
随机推荐
- 原生基础js脚本实现--在线答题系统
全部代码在最下面----需要的直接往下翻 html方面的代码 : 正确的答案 value=s <!DOCTYPE html> <html lang="en"&g ...
- 返回给前端样式数据整合Swagger
对于前端样式整合swagger,只对接口做增强,不对接口逻辑做修改,当json样式拼接完成,我们把json转为对应的实体类即可. 前端json样式对象构造参考:https://workshops.ot ...
- noip模拟5[string·matrix·big·所驼门王的宝藏]
怎么说呢这一场考得还算可以呢 拿了120pts,主要是最后一个题灵光开窍,想起来是tarjan,然后勉勉强强拿了40pts,本来是可以拿满分的,害 没事考完了就要反思 这场考试我心态超好,从第一个题开 ...
- OpenCV读写视频文件解析
OpenCV读写视频文件解析 一.视频读写类 视频处理的是运动图像,而不是静止图像.视频资源可以是一个专用摄像机.网络摄像头.视频文件或图像文件序列. 在 OpenCV 中,VideoCapture ...
- 实时双频Wi-Fi如何实现下一代车内连接
实时双频Wi-Fi如何实现下一代车内连接 How real simultaneous dual band Wi-Fi enables next-generation in-vehicle connec ...
- 开发掉坑(一)tar命令解压文件覆盖源文件
今天在编译机上编译前端代码,报了找不到依赖的异常.检查后发现是node_modules/.bin下少了一些文件. 一开始疑惑为什么本地能成功生成软链在node_modules/.bin,服务器上面却不 ...
- Java基础知识之this关键字知识讲解
this关键字这里对java中this关键字的基础知识进行讲解,希望对热爱java的小伙伴有帮助!! /* this关键字代表了所属函数的调用者对象. this关键字的作用: 1. 如果存在同名成员变 ...
- Linux学习笔记:Linux命令之权限管理命令
权限管理命令 chmod(重要) 命令名称:chmod 英文原意:change the permissions mode of a file 执行权限:所有用户 功能描述:改变文件或目录权限 语法:c ...
- Centos 安装 Influxdb + Chronograf
安装 Influxdb 1:下载安装包 官网下载地址 https://portal.influxdata.com/downloads/# wget https://dl.influxdata.com ...
- 盘点用jQuery框架实现“for循环”的四种方式!
摘要:分享在jQuery高级开发中对元素标签体的遍历常用的几种方法. 本文分享自华为云社区<盘点用jQuery框架实现"for循环"的四种方式!>,原文作者:灰小猿 . ...