Linux系统介绍(四)IO重定向与管道

IO重定向(IO redirection)

Linux的有一个强大之处就是可以通过管道(Pipe)跟IO重定向将一系列命令的输出跟输入连接起来。IO重定向是Linux中非常重要的概念,是理解Linux命令,脚本以及Linux IO的基础。

标准输入输出

对于shell来说,有三个基础的流,标准输入流(stdin或者stream 0),标准输出流(stdout或者stream 1),标准错误流(stderr或者stream2)。

标准输入输出

举个例子,当我们用键盘在shell中执行命令的时候,可以如下图:

键盘输入输出

通常,stdout跟stderr都输出到了屏幕上,但对于Linux来说,其实是两种不同的输出。

输出重定向

可以用>大于号将stdout重定向到另一个IO,比如文件:

# echo "hello" > test.log
# cat test.log
hello

上面的命令将stdout重定向到文件test.log中,此时,如果该文件不存在则创建新文件,如果存在则覆盖已有文件。事实上,>重定向是1>的简写,1>可以更清楚的看到实际上是把stdout(stream 1)重定向。

必须注意的是,默认情况下,该重定向会覆盖已有文件,这个在有时候可能不经意间丢失重要数据。shell提供了选项使得我们可以禁止这种覆盖,set -o noclobber可以打开该选项。

# cat test.log
hello
# set -o noclobber
# echo "world" > test.log
-bash: test.log: cannot overwrite existing file

此外,在打开该选项之后,其实还是可以强制执行覆盖,可以采用>|来强制重定向到已存在的文件:

# echo "world" > test.log
-bash: test.log: cannot overwrite existing file
# echo "world" >| test.log
# cat test.log
world

追加输出

可以采用>>将输出重定向到文件并追加在文件结尾,这样就可以避免覆盖文件了。

# cat test.log
world
# echo hello >> test.log
# cat test.log
world
hello

标准错误重定向

1>一样,我们可以通过2>将stderr重定向到文件,具体行为跟stdout类似。

同时重定向stdout跟stderr

我们可以在同一行命令中同时将stdout跟stderr重定向,如:

# ls test* tttt*
ls: cannot access tttt*: No such file or directory
test.log  test2
# ls test* tttt* > stdout.log 2> stderr.log
# cat stdout.log
test.log
test2
# cat stderr.log
ls: cannot access tttt*: No such file or directory

可以看出,stdout跟stderr被分别重定向到stdout.logstderr.log文件中了。

此外,还有一个常见的用法是将stderr重定向到stdout,这样就可以将所有输出都定向在一起了。

# ls test* tttt* > stdout.log
ls: cannot access tttt*: No such file or directory
# cat stdout.log
test.log
test2
# ls test* tttt* > stdout.log 2>&1
# cat stdout.log
ls: cannot access tttt*: No such file or directory
test.log
test2

可见,通过2>&1将stderr重定向给stdout,而stdout又重定向给文件stdout.log,这样所有的输出都重定向到文件stdout.log中了。另外,还可以通过&>直接将stderr跟stdout合并:

# ls -l test* tttt* &> stdout.log
# cat stdout.log
ls: cannot access tttt*: No such file or directory
-rw-r--r--. 1 root root 12 Nov 16 01:02 test.log
-rw-r--r--. 1 root root  0 Nov 16 00:17 test2

重定向顺序

将stderr重定向给stdout的时候,请务必注意其顺序,如上面的重定向如果写成这样,结果就完全不同了:

# ls test* tttt* 2>&1 > stdout.log
ls: cannot access tttt*: No such file or directory
# cat stdout.log
test.log
test2

可以看出,stderr其实并没有被重定向到文件stdout.log中,可见顺序是非常重要的。那么,如果理解这种不同呢?咱们可以这么样来理解:

  • >看作是shell中的赋值操作=
  • 将stdout跟stderr看作是变量,但对其引用采用&,这样&1表示对stdout变量的引用
  • 假定stdout跟stderr变量的初始值是屏幕,将屏幕记为/dev/tty
  • shell从左到有扫描解释命令,并对stdout跟stderr分别赋值
  • 查看stdout跟stderr的最终值即可知道分别被重定向到哪里了

还是以上面的例子来解释,ls test* tttt* 2>&1 > stdout.log

  • 命令开始前,stdout=/dev/tty, stderr=/dev/tty
  • shell从左到右扫描并重新赋值,首先2>&1就相当于stderr=$stdin,此时stderr的值其实还是/dev/tty
  • > stdout.log就相当于stdout=stdout.log,此时stdout值为stdout.log
  • 最后,stdout值为stdout.log,而stderr值仍然为/dev/tty,所以只有stdout输出到文件stdout.log中了

基于这个原则,在讲述完管道之后咱们将展示如何把stdout跟stderr交换一下。

输入重定向

  • <符号

既然输出有重定向,那么输入是否也可以呢?答案是肯定的,可以采用<将输入重定向,<其实是0<的简写。

# cat stdout.log
ls: cannot access tttt*: No such file or directory
-rw-r--r--. 1 root root 12 Nov 16 01:02 test.log
-rw-r--r--. 1 root root  0 Nov 16 00:17 test2
# cat <stdout.log
ls: cannot access tttt*: No such file or directory
-rw-r--r--. 1 root root 12 Nov 16 01:02 test.log
-rw-r--r--. 1 root root  0 Nov 16 00:17 test2
  • <<符号

此外,还可以<<EOF通过手动输入直到输入EOF(或者Ctrl-D)。

  • <<<符号

该符号可以直接将一个字符串重定向给输入

# base64 <<< hello
aGVsbG8K

base64命令参数只接受文件,通过这种方式就可以把字符串直接传给它。

输入输出同时重定向

shell是可以支持同时重定向输入跟输出的,以下方式都会被准确解析:

# cat <test.log > stdout.log 2> stderr.log
# <test.log > stdout.log 2> stderr.log cat

快速清除文件内容

可以通过重定向快速的清空文件内容:

# cat test.log
hello world
# > test.log
# cat test.log
#

可见,咱们并不需要写echo "" > test.log这样的命令来清空一个文件。当noclobber选项被打开时,可以通过>|来强制清空。

管道(Pipe)

在Linux中,我们可以使用管道(Pipe)将前一个命令的stdout作为输入给后面一个命令,管道由|表示。

# ls test* tttt*
ls: cannot access tttt*: No such file or directory
test.log  test2
# ls -l test* tttt* | grep log
ls: cannot access tttt*: No such file or directory
-rw-r--r--. 1 root root 12 Nov 16 01:02 test.log

请务必注意的是,管道只会将stdout传递给下一个命令,stderr并不会传递,为了证明这一点,咱们将后一个命令的stderr重定向到文件:

# ls -l test* tttt* | grep log 2> stderr.log
ls: cannot access tttt*: No such file or directory
-rw-r--r--. 1 root root 12 Nov 16 01:02 test.log
# cat stderr.log
#

这时可以看出,第二个命令的stderr为空,而第一个命令的stderr仍输出到屏幕了。当然,咱们也可以将第一个命令的stderr重定向到stdout上,这样grep命令也可以收到了。

# ls -l test* tttt* 2>&1 | grep "No "
ls: cannot access tttt*: No such file or directory

再回到上一节的问题,咱们如何将stdout跟stderr互相交换一下呢?可以这么做:

# ls -l test* tttt* 3>&1 1>&2 2>&3 | grep "No " 2> stderr.log
ls: cannot access tttt*: No such file or directory
-rw-r--r--. 1 root root 12 Nov 16 01:02 test.log
-rw-r--r--. 1 root root  0 Nov 16 00:17 test2
# cat stderr.log
#

如果你的Linux发行版本对grep输出的颜色设置正确,会发现只有第一行是grep出来的,由此可见3>&1 1>&2 2>&3居然将stdout跟stderr互换了一下,至于怎么解释,可以参照前面的赋值方式自行拆解一下。

本博文还可以在博主个人主页中找到。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • Shell 输入/输出重定向大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回到您的终端。一个命令...
    海角hust阅读 232评论 0 0
  • 先说一下linux重定向: 0、1和2分别表示标准输入、标准输出和标准错误信息输出,可以用来指定需要重定向的标准输...
    梦归游子意阅读 1,122评论 1 2
  • 1. 输入与输出 标准输入 STDIN文件描述符:0,默认:键盘输入 标准输出 STDOUT文件描述符:1,默认:...
    yuanzicheng阅读 992评论 0 50
  • linux资料总章2.1 1.0写的不好抱歉 但是2.0已经改了很多 但是错误还是无法避免 以后资料会慢慢更新 大...
    数据革命阅读 12,016评论 2 34
  • 你愿意食用和使用婕斯的细胞优化管理系统的产品,真的对我是一个惊喜!大惊喜!因为除了因此你会更健康之外,最重要的是你...
    定在阅读 215评论 0 0