相关好文章推荐
欲知文件描述符,必先知终端及重定向
终端设备(tty,pts,pty)
终端设备与文件描述符(file description,fd)及重定向的关系
Linux中一切皆文件,有文件就必有路径,有路径就必有如何来,如何回的指向。因此文件描述符与重定向为此而生。(成语:礼尚往来)
所有的存在都以文件的形式示现,而文件描述符专用于系统调用文件时使用,为打开的文件打上标识(通俗的讲就是上班穿工作服,回家后脱工作服)。
终端设备与文件描述符及重定向[ >,< ](注意不是追加重定向)不是单独存在,而是相辅相成。
重定向主要的作用将数据源流向到相应的设备中。(磁盘上的所有类型文件,在概念上都属于设备文件,因为文件都是保存在磁盘中,对文件的操作,其本质上就是对磁盘操作。)
终端设备一般含有计算机的五大部件中的输入设备和输出设备(这与计算机发展历史相关,输入设备可以是键盘或其他能输入数据的设备,输出设备可以是显示器或其他能接收数据的设备)。
每个终端设备接入Linux系统,系统为该终端的输入功能绑定为0的文件描述符,输出功能绑定为1的文件描述符,在处理终端设备发送过来的指令出现错误时,错误提示绑定为2的文件描述符。
终端设备 | 文件描述符 | 文件描述符对应的文件 | 重定向(箭头所指就是流动的方向) | 数据的流向 | 打开文件即产生该文件的文件描述符 |
输入功能 | 0 | /dev/stdin | >(输出) 数据源 (输出)>设备 | ls >a.txt | 3 ~ 65535 |
输出功能 | 1 | /dev/stdout | <(输入) 命令 < (输入)数据源 | cat <a.txt | |
2 | /dev/stderr |
终端设备与文件描述符及重定向的默认行为
默认情况下:系统会帮用户默认补全输入及输出的重定向路径。所以一般情况下,手工写上重定向时,就是修改系统默认的输入与输出的路径。
对所爱,要重复大声说:trust me , I love you
Linux中一切皆文件,有文件就必有路径,有路径就必有如何来,如何回的指向。因此文件描述符与重定向为此而生。(成语:礼尚往来)
磁盘上的所有类型文件,在概念上都属于设备文件,因为文件都是保存在磁盘中,对文件的操作,其本质上就是对磁盘操作。磁盘属于存储设备。
比如:[root@server01 ~]# cat a.txt # 等效 cat 0<a.txt 1>/dev/pts/0
处理方法 | 输入设备(0)负责为处理的方法提供数据源(数据源在磁盘设备上的a.txt里面) 要加工的数据在哪里来 | 处理完的结果由输出设备(1)将数据送给下一个设备接收 加工完的数据往哪里去 | |||||
用户输入 | cat | a.txt | |||||
系统自动补全 | cat | 0 | < | a.txt | 1 | > | /dev/pts/0 |
输入设备 可理解cpu获取数据入口 | 数据源设备 | 发送设备 可理解cpu输出数据的出口 | 接收设备 |
概念图
语法格式:命令(不同的命令对接收数据源有所不同) [ 输入设备文件描述符 重定向(<) 数据源设备] [ 输出设备的文件标识符 重定向(>) 接收设备文件(或文件名)或&文件描述符 ]
比如:[root@server01 ~]# ls 1>a.txt 2>/dev/null #等效 ls >a.txt 2>/dev/null
ls | 1 | > | a.txt | 2 | > | /dev/null |
命令产生数据源 | 系统的输出设备的文件描述符 | 重定向 | 接收设备 | 系统的错误输出设备的文件描述符 | 接收设备 |
比如:[root@server01 ~]# ls
处理方式 | 系统接收数据入口 | < | 提供数据源的设备 | 系统返回数据出口 | 接收的设备 | ||
用户输入 | ls | ||||||
系统自动补全 | ls | ls命令根据参数而处理,而不是对数据源处理 | 1 | > | /dev/pts/0 |
比如:[root@server01 ~]# cat 0<a.txt #等效 cat <a.txt
命令处理方式 | 系统接收数据入口 | 流入 | 提供数据源的设备 | 结果出口 | 流入 | 终端设备 | 错误出口 | 流入 | 终端设备 | |
用户输入 | cat | a.txt | ||||||||
系统自动补全 | cat | 0 | < | a.txt | 1 | > | /dev/pts/0 | 2 | > | &1 |
图解修改系统为命令行自动补全的路径
常规的书写格式 | 自动补全结果返回路径 |
[root@server01 ~]# lsanaconda-ks.cfg a.txt install.log install.log.syslog[root@server01 ~]# | [root@server01 ~]# ls 1>/dev/pts/0 2>/dev/pts/0anaconda-ks.cfg a.txt install.log install.log.syslog[root@server01 ~]# |
1 终端(输入设备)提交命令到服务端 2 ls产生了数据源 3 结果从服务器的输出设备 > 终端
文件描述符与重定向的默认等价关系(修改默认重定向及文件描述符的变化流程如下图) ls 1>a.txt 2>a.txt 等价 ls >a.txt 2>a.txt # >a.txt 默认等价 1>a.txt 等价 ls >a.txt 2>&1 # 2>&1 其中&1表示/dev/stdout,2指向1了。 等价 ls &>a.txt # |
文件描述符参与系统的/dev/stdin,/dev/stdout,/dev/stderr设备与每个终端设备的绑定关系
文件描述符(0,1,2)成为系统的输入设备,输出设备,错误输出设备与终端设备的纽带,命门就在此处。
pts/0 | pts/1 |
[root@server01 ~]# ll /dev/std*lrwxrwxrwx 1 root root 15 Sep 29 2018 /dev/stderr -> /proc/self/fd/2lrwxrwxrwx 1 root root 15 Sep 29 2018 /dev/stdin -> /proc/self/fd/0lrwxrwxrwx 1 root root 15 Sep 29 2018 /dev/stdout -> /proc/self/fd/1[root@server01 ~]# ll /proc/self/fdtotal 0lrwx------ 1 root root 64 Sep 29 18:15 0 -> /dev/pts/0lrwx------ 1 root root 64 Sep 29 18:15 1 -> /dev/pts/0lrwx------ 1 root root 64 Sep 29 18:15 2 -> /dev/pts/0lr-x------ 1 root root 64 Sep 29 18:15 3 -> /proc/26143/fd[root@server01 ~]# | [root@server01 ~]# ll /dev/std*lrwxrwxrwx 1 root root 15 Sep 29 2018 /dev/stderr -> /proc/self/fd/2lrwxrwxrwx 1 root root 15 Sep 29 2018 /dev/stdin -> /proc/self/fd/0lrwxrwxrwx 1 root root 15 Sep 29 2018 /dev/stdout -> /proc/self/fd/1[root@server01 ~]# ll /proc/self/fd/total 0lrwx------ 1 root root 64 Sep 29 18:15 0 -> /dev/pts/1lrwx------ 1 root root 64 Sep 29 18:15 1 -> /dev/pts/1lrwx------ 1 root root 64 Sep 29 18:15 2 -> /dev/pts/1lr-x------ 1 root root 64 Sep 29 18:15 3 -> /proc/26145/fd[root@server01 ~]# |
pts/0 终端设备 | pts/1 终端设备 |
[root@server01 ~]# lsanaconda-ks.cfg a.txt install.log install.log.syslog[root@server01 ~]# [root@server01 ~]# whoroot pts/0 2018-09-29 12:02 (192.168.6.1)root pts/1 2018-09-29 14:34 (192.168.6.1)[root@server01 ~]# ll /dev/fd/total 0lrwx------ 1 root root 64 Sep 29 15:42 0 -> /dev/pts/0lrwx------ 1 root root 64 Sep 29 15:42 1 -> /dev/pts/0lrwx------ 1 root root 64 Sep 29 15:42 2 -> /dev/pts/0lr-x------ 1 root root 64 Sep 29 15:42 3 -> /proc/25919/fd[root@server01 ~]# ls 1>/dev/pts/1 2>/dev/pts/1[root@server01 ~]# echo "pts/1,我的显示在你那边吗?" 1>/dev/pts/1 [root@server01 ~]# 若是手机充值给我就好了 | [root@server01 ~]# whoroot pts/0 2018-09-29 12:02 (192.168.6.1)root pts/1 2018-09-29 14:34 (192.168.6.1)[root@server01 ~]# ll /dev/fd/total 0lrwx------ 1 root root 64 Sep 29 16:30 0 -> /dev/pts/1lrwx------ 1 root root 64 Sep 29 16:30 1 -> /dev/pts/1lrwx------ 1 root root 64 Sep 29 16:30 2 -> /dev/pts/1lr-x------ 1 root root 64 Sep 29 16:30 3 -> /proc/25968/fd[root@server01 ~]# anaconda-ks.cfg a.txt install.log install.log.syslog pts/1,我的显示在你那边吗? [root@server01 ~]# echo "若是手机充值给我就好了" >/dev/pts/0 |
查看文件的描述(file description,fd)
一旦打开文件,系统就会自动产生对该文件的文件描述符,表示在内存地址指向该文件资源(可以理解文件描述符类似变量名)
pts/0 | pts/1 |
[root@server01 ~]# tail -f a.txt 123 | [root@server01 ~]# lsof -n | grep 'a.txt' |column -ttail 26107 root 3r REG 8,3 4 133213 /root/a.txt[root@server01 ~]# |
3 :表示tail 打开a.txt的文件所产生的文件描述符,3与a.txt就形成关联 r:tail以读的方式访问a.txt w:可写 u:可写可读 |
文件描述符与文件操作进程的关系
& 的快速理解 | [root@server01 ~]# echo "I am a" >a.txt [root@server01 ~]# [root@server01 ~]# a='hi'[root@server01 ~]# echo $ahi[root@server01 ~]# cat >&1
|
常用方式 | [root@server01 ~]# cat a.txt here is a[root@server01 ~]# >b.txt [root@server01 ~]# lsanaconda-ks.cfg a.txt b.txt install.log install.log.syslog[root@server01 ~]# ls c.txt >a.txt 2>b.txt #正确的结果放入a.txt,错误结果放入b.txt[root@server01 ~]# cat a.txt #为什么a.txt没有数据,没有结果,文件描述符1默认输出为空。[root@server01 ~]# cat b.txt ls: cannot access c.txt: No such file or directory[root@server01 ~]# |
常用方式 | [root@server01 ~]# >a.txt[root@server01 ~]# echo "here is b">b.txt [root@server01 ~]# ls a.txt >a.txt 2>b.txt [root@server01 ~]# cat a.txt a.txt[root@server01 ~]# cat b.txt #为什么b.txt没有了,道理同上[root@server01 ~]# |
& 的作用 | [root@server01 ~]# ls >&1 #&在重定向后面(必须是数字),其作用就是对文件描述符对应的文件(设备文件)操作方式anaconda-ks.cfg a.txt install.log install.log.syslog[root@server01 ~]# |
& 的文件操作-只读 | [root@server01 ~]# exec 5 |
& 的文件操作-只写 | [root@server01 ~]# exec 5>a.txt #打开文件描述符为5的a.txt文件操作进程,操作模式为只写。[root@server01 ~]# cat <&5cat: -: Bad file descriptor[root@server01 ~]# echo 'haha' >>&5-bash: syntax error near unexpected token `&'[root@server01 ~]# echo 'haha' >&5[root@server01 ~]# cat a.txt haha[root@server01 ~]# exec 5>&- #5>&- 关闭文件描述符为5的文件操作进程[root@server01 ~]# |
& 的文件操作-读写 | [root@s01 ~]# cat a.txt anaconda-ks.cfga.txtinstall.loginstall.log.syslogddr[root@s01 ~]# exec 5<>a.txt #打开文件描述符为5的a.txt文件操作进程,操作模式可读可写。[root@s01 ~]# read -n 5 <&5 #从文件的第一个位置开始读取5个字节,并游标到第5个位置[root@s01 ~]# echo xxx >&5 #在游标第5个位置插入 xxx 及 换行符[root@s01 ~]# cat <&5 #从在当下游标的位置显示到文件尾ks.cfga.txtinstall.loginstall.log.syslogddr[root@s01 ~]# exec 5<&- [root@s01 ~]# exec 5>&-[root@s01 ~]# cat a.txt anacoxxx #这个就是修改的地方了。从第5个字符开始替换,替换了3个字符1个换行符共4个字符ks.cfga.txtinstall.loginstall.log.syslogddr[root@s01 ~]# |