前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >linux17-详说linux的重定向与文件描述符

linux17-详说linux的重定向与文件描述符

作者头像
北野茶缸子
发布2022-05-19 11:49:55
1.6K0
发布2022-05-19 11:49:55
举报
文章被收录于专栏:北野茶缸子的专栏

前言

上一节中 [[16-linux程序后台执行指西]],我们提到了,重定向操作,对于后台执行命令来说,很有用,这一节来详细说说。

部分内容参考:Linux 基础入门(新版) - 实验楼[1]

1-linux的输入与输出

Linux 默认提供了三个特殊设备,用于终端的显示和输出,分别为stdin(标准输入,对应于你在终端的输入),stdout(标准输出,对应于终端的输出),stderr(标准错误输出,对应于终端的输出)。

2-文件描述符

文件描述符在形式上是一个非负整数。本质上是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。

当程序打开一个现有文件或者创建一个文件时,内核会向进程返回一个文件描述符。

默认情况下,使用终端的标准输入作为命令的输入和标准输出作为命令的输出。比如,标准输入(standard input)的文件描述符是 0,标准输出(standard output)是 1,标准错误(standard error)是 2。

3-重定向输入、输出

我们可以将结果从屏幕重定向到某个文件。

我们可以分别处理,或直接用&

代码语言:javascript
复制
# 将标准错误重定向到标准输出,再将标准输出重定向到文件,注意要将重定向到文件写到前面
$ cat Documents/test.c hello.c >somefile  2>&1
# 或者只用bash提供的特殊的重定向符号"&"将标准错误和标准输出同时重定向到文件
$ cat Documents/test.c hello.c &>somefilehell

因为shell 中标准输出与标准错误不同,上面的文件描述符,二者对应的也并不相同,因此需要对它们分别处理。

代码语言:javascript
复制
❯ cat unname.txt > /dev/null
❯ cat 123 > /dev/null
cat: 123: No such file or directory
❯ cat 123 2>/dev/null

有时候,我们可能并不想覆盖文件的原有内容。则可以通过>> 进行追加数据:

代码语言:javascript
复制
$ who >> test6
$ cat test6
Thu Jun 11 12:23:05 CST 2020
mugpeng  console  Jun  2 13:36 
mugpeng  ttys000  Jun  6 10:21

输入重定向将文件的内容重定向到命令。command < inputfile

记忆方法:输入重定向与输出重定向符号相反。在命令行上,命令在左,文件在右,重定向符号指向数据流动的方向。

此外,还有一种内联输入重定向inline input redirection。该重定向无需对命令指定文件,但需要指定一个文本标记来划分输入数据的开始与结尾,使用内联输入重定向,shell 会使用次提示符来提示输入数据。符号为<<。注意开始和结尾都使用了一致的文本标记test。

代码语言:javascript
复制
$ wc << test
> I
> am
> happy.
> test
       3       3      12

4-永久重定向

有的时候,我们可能希望脚本中的某些内容永久的重定向到某个文件中,比如操作的日志。这时候可以使用 exec 。

代码语言:javascript
复制
# 先开启一个子 Shell
$ zsh
# 使用exec替换当前进程的重定向,将标准输出重定向到一个文件
$ exec 1>somefile
# 后面你执行的命令的输出都将被重定向到文件中,直到你退出当前子shell,或取消exec的重定向
$ ls
$ exit
$ cat somefile

4-自定义文件描述符

在 Shell 中有 9 个文件描述符。上面我们使用了也是它默认提供的 0,1,2 号文件描述符。另外我们还可以使用 3-8 的文件描述符,只是它们默认没有打开而已。

你可以使用下面命令查看当前 Shell 进程中打开的文件描述符:

代码语言:javascript
复制
$ ls -Al /dev/fd/
total 0
lrwx------ 1 yzpeng yzpeng 64 Apr 30 12:59 0 -> /dev/pts/0
lrwx------ 1 yzpeng yzpeng 64 Apr 30 12:59 1 -> /dev/pts/0
lrwx------ 1 yzpeng yzpeng 64 Apr 30 12:59 2 -> /dev/pts/0
lr-x------ 1 yzpeng yzpeng 64 Apr 30 12:59 3 -> /proc/70349/fd

ps:mac 与linux 下结果可能有所不同。

我们还可以创建自定义的新的文件描述符。

通过exec 还设定:

代码语言:javascript
复制
# 进入新的zsh
$ zsh
$ exec 4>somefile
# 先进入目录,再查看,否则你可能不能得到正确的结果,然后再回到上一次的目录
$ cd /dev/fd/;ls -Al;cd -
# 注意下面的命令>与&之间不应该有空格,如果有空格则会出错
$ echo "this is test" >&4
$ cat somefile
$ exit

如果需要永久设定,也可以添加到rc 文件中。

同样,你也可以通过exec,强制覆盖默认的文件描述符的指向。不过,并不推荐。

当我们设定的文件描述符不想使用时,还可以关闭它们:

代码语言:javascript
复制
$ exec 4>&-
$ cd /dev/fd;ls -Al;cd -

5-屏蔽输出

在上一节我们也说过,/dev/null 有时候很有用。

在 Linux 中有一个被称为“黑洞”的设备文件,所有导入它的数据都将被“吞噬”—— /dev/null 。它叫做空设备,是一个特殊的设备文件,它通常被用于丢弃不需要的输出流,或作为用于输入流的空文件,这些操作通常由重定向完成。读取它则会立即得到一个 EOF。

如果将标准输出重定向到这个“黑洞”,则就会完全得不到任何的输出结果了。

代码语言:javascript
复制
$ cat Documents/test.c 1>/dev/null 2>&1

6-tee命令

如果我们想要将结果同时输出到屏幕与文件,我们可以使用tee命令:

代码语言:javascript
复制
echo 5 | tee test2.txt

cat test2.txt
5

不过需要注意的是,如果想要实现>> 追加的效果,需要使用参数 -a:

代码语言:javascript
复制
$ for i in {1..5}; do echo $i | tee -a test2.txt; done
1
2
3
4
5

$ cat test2.txt 
1
2
3
4
5

另外,我们还可以将输出同时保存到多个文件,类似执行完输出重定向操作,又对生成的重定向输出文件做了一个cp 命令:

代码语言:javascript
复制
$ for i in {1..5}; do echo $i | tee -a test3.txt test33.txt; done
1
2
3
4
5

$ ls test3*
test3.txt  test33.txt

参考资料

[1]

Linux 基础入门(新版) - 实验楼: http://demo.erdangjiade.com/modals/8/856/demo/courses/show.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 北野茶缸子 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1-linux的输入与输出
  • 2-文件描述符
  • 3-重定向输入、输出
  • 4-永久重定向
  • 4-自定义文件描述符
  • 5-屏蔽输出
  • 6-tee命令
    • 参考资料
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档