时间:2021-05-19
前言
Linux将所有内核对象当做文件来处理,系统用一个size_t类型来表示一个文件对象,比如对于文件描述符0就表示系统的标准输入设备STDIN,通常情况下STDIN的值为键盘,如read命令就默认从STDIN读取数据,当然STDIN的值是可以改变的,比如将其改成其他文件,这样的话想read等命令就会默认从相应的文件读取数据了。
简单地说,一个文件描述符可以和一个文件挂钩,一旦挂钩就可以通过取地址运算符&获得该文件的句柄,比如&0就可以获得STDIN设备在内存中的句柄(设备在系统中也被当做文件处理),可以这样理解,如果是一个shell中的普通变量var,可以通过$var的形式获得该变量所代表的值,而对于一个文件描述符fd,则可以通过&fd的形式获得文件描述符指向的文件的句柄,而这个句柄可以简单地理解成该文件的路径。
在 Shell 编程里经常会用到重定向操作, 它本质上是对文件描述符进行操作, 本文会对 Shell 脚本里的文件描述符做一个详细的介绍.
默认标准文件描述符
每个进程启动时默认都会有三个标准的文件描述符:
这三个描述符默认是对应同一个 tty 设备, 这样我们便可以在终端中输入数据和获取进程的输出.
默认的文件描述符也是可以被替换的, 例如我们可以替换掉 stdout 到一个文件, 这样命令的输出就不是打印到终端, 而是被输出到文件中:
在上面的 demo 中, 我们先是通过 exec 1 > /tmp/stdout 把 stdout 指向了文件 /tmp/stdout, 紧接着我们执行了两条命令 ls 和 pwd, 可以看到此时终端已经没有了命令的输出. 当我们通过 exec 1 >&2 恢复 stdout 后, 可以发现文件 /tmp/stdout 里存储了之前命令的输出.
其中 exec 是一个 bash 内置命令, 不同于在终端中执行命令时会 fork 一个子进程, 通过 exec 执行的命令会直接修改当前的 shell 进程, 可以通过它执行命令来修改当前 shell 的 context.
如果你想使坏的话可以在别人的 ~/.bashrc 里加入 exec 1 > /tmp/stdout, 这样新开的所有的终端窗口里都看不到命令的输出, 要是因此被打概不负责 :) .
文件描述符的操作
Shell 中对文件描述符的操作由三部分组成: (Left, Operation, Right):
当存在多个文件描述符的操作时, 会按照从左往右的顺序依次执行. 例如通过命令 cmd 3>&1 1>&2 2>&3 3>&- 就可以交换 stdin 和 stdout.
我们通过下面的例子来验证上面的文件描述符交换是否生效:
让我们来开始实验吧:
➜ test exec 2> /tmp/stderr➜ test lsa.txt➜ test ls 3>&1 1>&2 2>&3 3>&-➜ test cat /tmp/stderra.txt和我们的预期时一致的!
一些示例
用文件重载 stdin :
➜ test cat 0< a.txthello➜ test cat < a.txt # same with last commandhello把 stderr 和 stdout 都过滤掉
ls not_exist 1> /dev/zero 2>&1# another wayls not_exist &> /dev/zero处理上一个命令的错误输出:
➜ blog git:(hexo) ls not_exist 2>&1 | sed 's/not_exist/error/g'ls: error: No such file or directory# another way➜ blog git:(hexo) ls not_exist |& sed 's/not_exist/error/g'ls: error: No such file or directory把标准输出转入到错误输出上: echo hello 1>&2
Process Substitution
在 bash 中提供了两个特殊的操作, 它们都可以被直接当成文件名使用:
示例
利用 <(cmd) 来验证一对公私钥是否匹配:
➜ blog git:(hexo) diff <(ssh-keygen -y -e -f ~/.ssh/id_rsa) <(ssh-keygen -y -e -f ~/.ssh/id_rsa.pub)➜ blog git:(hexo)利用 >(cmd) 来对错误信息进行处理, 同时保证错 stderr 信息不回变成 stdout:
➜ blog git:(hexo) ls not_exist 2> >(sed 's/not_exist/keep_error/g')ls: keep_error: No such file or directory➜ blog git:(hexo)总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
References
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
本文研究的主要是Linux中文件描述符fd与文件指针FILE*互相转换的相关内容,具体介绍如下。1.文件描述符fd的定义:文件描述符在形式上是一个非负整数。实际
描述符描述符是你添加到那些定义中来改变他们的意思的关键词。Java语言有很多描述符,包括以下这些:可访问描述符不可访问描述符应用描述符,你可以在类、方法、变量中
在Linux下默认的文件描述符大小为1024,可以通过下面的命令查看:[root@localhost~]#ulimit-n某些特殊情况,可能需要修改文件描述符的
FileDescriptor介绍FileDescriptor是“文件描述符”。FileDescriptor可以被用来表示开放文件、开放套接字等。以FileDes
Lua中I/O库用于读取和处理文件。有两种类型的文件操作,在Lua即隐含文件的描述符和明确的文件描述符。对于下面的例子中,我们将使用一个示例文件test.lua