搜索
查看: 4433|回复: 13
收起左侧

[讨论] Hello , Linux(四):I/O Redirection

  [复制链接]
root1605
发表于 2018-2-2 00:33:36 | 显示全部楼层 |阅读模式
本帖最后由 root1605 于 2018-2-17 10:45 编辑
Hello , Linux(四):
I/O Redirection
023123.jpg


                                              目录

                                              Ⅰ 前言
                                              Ⅱ 再探I/O重定向
                                              Ⅲ 管道
                                              Ⅳ 键盘操作技巧
                                               V 别名  

By root1605 & 翼风Fly
来自bbs.kafan.cn



第三篇:Hello , Linux(三):You AreThe Commander !
http://bbs.kafan.cn/thread-2112580-1-1.html



评分

参与人数 5原创 +1 人气 +4 收起 理由
JAYSIR + 1 感谢解答: )
ziqianweiyang + 1 版区有你更精彩: )
langren1353 + 1 很给力! 版区有你更精彩: )
翼风Fly + 1 版区有你更精彩: )
a330391 + 1 版区有你更精彩: )

查看全部评分

root1605
 楼主| 发表于 2018-2-2 00:33:37 | 显示全部楼层
本帖最后由 root1605 于 2018-2-14 15:55 编辑


Ⅰ 前言

折腾≠学习
         Linux的发行版有很多,各种各样或精美或简洁的桌面环境吸引着你去安装,各种酷酷的软件看上去不错。于是有些人就认为,折腾=学习。
       “吾常终日而思矣,不如须臾之所学也”,即使你作为非专业人员,你也有必要了解下基本的概念,不需要你去了解VFS机制的实现细节,不需要你清楚Linux的进程调度算法,但你至少要知道进程是什么,怎样不通过某些发行版的软件中心安装软件,怎样运行shell脚本等。就像你到了北京去,总得知道有“北京烤鸭”这种东西吧。
        楼主并不反对“实践”,但是实践要和理论相结合,虽然有些理论来自于实践,但不代表你就能总得到正确正确的结论,也不能保证你不会走偏。见过这样一批“忠实”的Linux用户:他们不知道deb包和rpm有什么区别,却因自己心仪的几个Linux发行版使用两种包管理方式而不知如何选择,或者就说xx包管理方式比xx包管理方式更先进”;不会不通过GUI界面的软件中心(或类似看起来很友好的软件安装软件),却对怎样配置Wine QQ了如指掌……甚至对Linux仅仅停留在“这是一个开源免费的软件”认识的时候,听别人说“使用Arch Linux才是高手,使用Arch Linux能快速精通Linux”,就照猫画虎的按照教程配置Arch Linux,最后顺便捎带一个Wine QQ之类的软件。
        这是“折腾”,并且“折腾无错”,但折腾之后不一定学到了什么,就像你在Windows上折腾了各种花花绿绿的杀毒软件一样,你不一定懂得诸如“注入”之类的词语是什么意思。
        所以,要学习,要有正确的方法,当然,为了好玩折腾下没什么问题,但不要陷入这个正反馈的怪圈就行了。


它们不是无意义的符号

        有些命令一看就能猜出大概意思,比如“clear”,它是一个英文单词,但是像"cd","pwd"这些呢?
        为了拼写简便(或者是其他的什么原因),它们经常是一个词组的缩写,比如"cd"指"change directory","du"代表"disk usage"。了解这些,可以更快速记住命令。
举例:
ls命令是List的缩写,
cd命令是Change Directory的缩写,
chown命令是 Change Owner 的缩写,
su命令是Swith user的缩写;
cat是 Concatenate的缩写;
df是Disk Free的缩写;
du是Disk Usage的缩写;
ps是Process Status的缩写;
chmod是Change Mod的缩写;
ldd是List Dynamic Dependencies的缩写。

Ⅱ 再探I/O重定向

        Unix文化中“一切都是文件”前面已经有所“领略”了,甚至你从键盘上输入命令,从终端输出内容,都与它紧密相关。
        每个Linux用户进程创建后,系统自动给它三个特殊文件,为“stdin”,“stdout”,“stderr”(标准输入,标准输出,标准错误输出)。比如命令“pwd”(也把它看做程序),文件“stdin”就表示它的输入,文件“stdout”表示正常的输出,“stdout”表示它输出的错误信息。在之前介绍我们已经知道Linux甚至把鼠标也当做设备文件来使用,这里类似的,这三个文件就是表示这三种信息,这三种信息就是这三个文件。默认情况,标准输入指向键盘,标准输出和标准错误输出指向屏幕。标准输入,标准输出,标准错误输出,指的是这三种信息,而不是有些人认为的“标准输入就是键盘,标准输出就是屏幕,标准错误输出也是屏幕”。上一篇文章我们将标准输出重定向,使其不再连接到屏幕,所以下文的重定向,就可以理解为改换了这三个文件的连接而已。
        更近一步想一下,因为“文件是一系列有序列的字节”,这是毫无疑问的。一个程序要运行,可能需要有输入、输出,如果有错,还要能表现出自身的错误。不管是标准输入,标准输出,还是标准错误输出,都是由一个文件代表,也是一串有序列的字节,所以,这样我们也可以把标准输入称为“标准输入流”,以此类推,“标准输出流”,“标准错误输出流”,这是一种形象的说法(把数据比做流水),是另一个层面来看待数据的名称,和“标准输入”,“标准输出”,“标准错误输出”是一个意思。所以“把标准输入流重定向到标准输入”(明显是把标准输出当做“屏幕”这个设备了)这种话是错误的。
*/dev/stdin    ->      /proc/self/fd/0             #表示标准输入,即键盘输入
/dev/stdout   ->      /proc/self/fd/1     #表示标准输出,即显示屏,屏幕
/dev/stderr   ->     /proc/self/fd/2           #表示标准错误输出
       如下两张图,第一张毫无疑问命令的用法是正确的,产生的标准输出被重定向到一个文件中,而第二张图就中,因为“pwd”命令没有“-s”这个选项,所以它不会给你正确的信息,它产生了标准错误输出,根据第三篇所写,“>>”和“>”符号仅仅是对标准输出进行重定向,而标准错误输出依然出现在了屏幕上。

图1:将pwd的标准输出重定向到一个存储在磁盘上的文件中

图2:未重定向标准错误输出
     没有专用的重定向标准错误的操作符,如果需要重定向标准错误输出,需要知道其文件描述符。在shell内部,标准输入为0,标准输出为1,标准错误输为 2,观察下面的命令:
pwd >s.txt
pwd 1>s.txt
pwd -s 2>s.txt #重定向标准错误到s.txt
        在“>”或者“>>”前面加上数字,就表示了你要重定向什么,没有数字就默认为1,要重定向错误输出,就要指出描述符。
        重定向有什么用呢?就目前所讲内容来说,有以下几个好处:
#当屏幕输出的信息很重要,而且我们需要将他存下来的时候;
#背景执行中的程序,不希望他干扰屏幕正常的输出结果时;
#刻意丢弃掉一些输出
#错误讯息与正确讯息需要分别输出时。
        要达成以上第三个目的,可以将流重定向到已经提过的“/dev/null”,下面这行命令,就“隐瞒”了可能的错误信息:
ls -l /bin/usr 2> /dev/null
        如果我们希望将一个命令的所有输出到一个文件。我们必须同时重定向标准输出和标准错误输出。参考下面的命令:
ls -l /bin >output.txt 2>&1
        它表示首先重定向标准输出到文件,然后重定向标准错误输出到标准输出,这样就把两种输出重定向到了一个文件,重定向顺序不能反。就好比三条河流,A,B,C要把A和B的水都输送到C河中,所以就先把A河的水连接到B河,再把B河的水通向C河,这样也就等效于把A,B两条河的水都送到C河。
        也有另一种简单的写法(不用太纠结语法,记住即可):
ls -l /bin &>output.txt


Ⅲ 管道
        管道是Linux中的一种基本的IPC(进程通信)方式,用于进程间信息传递。数据从管道的写端流入管道,从读端流出,内核使用环形队列机制,借助内核缓冲区实现通信。
       不过这里可不会多介绍这些知识,它们牵扯到的其他知识太多了。而这里命令之间传递数据也用了这个机制。
基本语法是如此:
command 1| command 2 |command 3 | ...|command n
        它的含义是,将command 1的标准输出传递给command 2作为command 2的标准输入,以此类推直到command n,注意标准错误是不能直接这样传递的。
        可能你要问了,不是“标准输入”“标准输入”是文件吗?这说明你还没清楚上一小节的内容,标准输出的内容就是抽象为一个特殊文件,这个文件就是标准输出(即一些输入输出的信息)。

图3:“ls/bin/sbin |sort”的执行
        命令 “ls /bin /sbin | sort”的意思是,将这两个目录的内容合起来输出(作为标准输出),而“sort”接受这个标准输出,作为标准输入,然后对其进行排序(sort命令默认以字符排序,其他用法可自行学习,并不难)。
        再举一个例子。先介绍一个“厕所命令”,“wc”。wc的用途是统计标准输入中有多少英文单字,行,字符,比如
wc  -l    /a.cpp
        就会输出这个“a.cpp”中有多少个字符,实际上,它是先读取这个文件中的内容,作为标准输入,而不是把这个文件的路径当做标准输入。观察下面的命令:
cat /init.rc | wc -l

        首先,cat命令接受一个文件路径为参数,并将其打开,产生标准输出,再将标准输出传递给管道线“|”右边的命令,作为“wc”的标准输入。执行结果如下图:

图4:“cat /init.rc | wc -l”的执行
       再举一个特殊的例子,有一个双向重定向的命令,“tee”,它的基本用法是:
tee file
或者
tee -a file
        基本作用是,得到标准输入,然后将它输出到文件中和屏幕上。其中,使用选项“-a”为追加模式,不会清空文件内容再写入。举个例子:
ls /bin | sort | tee a.txt
        屏幕上输出为(输出内容较多,截取了一部分):

图5:“ls /bin | sort | tee a.txt”的执行
        我们再分析一下这个命令的执行过程(已经看懂了的不必再看),首先ls接受/bin这个参数,产生标准输出,也就是/bin目录下的内容,但是这个标准输出通过管道成为了sort的标准输入,随即,sort将它排序,通过管道传输给tee命令,成为tee的标准输入,最后,tee命令将标准输入的内容同时输出在屏幕和文件中。
        总结一下,管道线左边的命令必须要能产生标准输出,管道线右边的命令必须要能接受标准输入,这个管道才是有意义的。像命令“less”,“grep”,“cut”等即能接受标准输入,也能产生标准输出,而有些命令,比如“ls”,“pwd”,“type”等就不是了,要么不能接受标准输入,要么不能产生标准输出,甚至都没有。能不能用在管道组合中,判断依据就是上文提到的管道线左右的命令的要求。至于哪些命令能够产生标准输出或者接受标准输入,要靠积累或者查阅资料。
*上述的各种动词,“传递”,“接受”等都是一种形象的容易理解的说法,为了贴合“管道”这个名词。可能你会觉得“读取”,“输出”等动词更加合适。


Ⅳ 键盘操作技巧
       有些发行版喜欢标榜自己“很像Windows”,符合“Windows的操作习惯”。可能在窗口程序的应用上做的很像,比如各种快捷键,但在shell中就没法总是符合Windows的一些操作习惯了。
也许你就曾经在终端中使用“Ctrl +V”和“Ctrl+C”操作文本,但发现屏幕上会产生莫名其妙的情况。在使用shell的时候,合理使用键盘操作技巧,有助于提高效率。下面介绍一些常用的快捷键,不难但是比较多,只要多用就会了。现在的很多发行版中的终端使用鼠标操作也不麻烦,如果你真想用鼠标。
(你猜猜我为什么要用“#”这个符号?)
#Ctrl-A        移动光标到行首(光标,就是那个发亮的小长方条,不是鼠标指针)
#Ctrl-E 移动光标到行末(可以思考下A和E是什么意思,方便记忆)
#Ctrl-L 清空屏幕,和输入命令“clear”一样的效果

#Ctrl-D 删除光标所指的字符
#Ctrl-T光标位置的字符和光标前面的字符互换位置。
#Ctrl-K剪切从光标位置到行尾的文本
#Ctrl-U剪切从光标位置到行首的文本
        建议亲自体验一下上面的快捷键,搞清楚它们什么意思,具体细节,可以自己体会。常用快捷键不止这些,可以自行搜索。
        下面提一个东西叫“自动补全”,看下面这张图就明白了。

图6:搜索引擎的“自动补全”功能
        无非是给你一个“偷懒”的机会,让你少输点东西,免得出错,也可能在你不知道怎么做的时候给一点提示。
        比如输入字符“pw”,再按一下Tab键,就会自动补全“pwd”这个命令。输入字符“s”,按两次Tab键,会出现所有以“s”开头的命令。

图7:列出以“s”开头的命令
        自动补全能对变量、用户名、命令和主机名等起作用(主机名自动补全只对包含在文件/etc/hosts 中的主机名有效)。具体例子在以后涉及(变量,用户名等概念未讲述)。
        这只是最基本的补全功能,你也可以安装一些增强工具包,甚至你的发行版自带的终端功能就很“高级”,但基本作用就是提示和补全。

V别名

       在Windows Powershell中,清空屏幕可以用“Clear-Host”,在bash上可以用“clear”,如果我喜欢Windows Powershell的写法呢?
       “alias”命令用来设置指令的别名。我们可以使用该命令可以将一些较长的命令进行简化,当然也可以拿来完成上一段所讲的目的。
       它的基本用法是:
   alias 别名='原命令 -选项/参数'
比如:
alias Clear-Host='clear'
alias cls='clear'
alias Get-LineCount='wc -l'

图8:设置别名
        要删除一个别名,可以使用 unalias 命令,用法请自行搜索(尝试一下输入“man unalias”并观察屏幕上的输出)。
        alias命令的作用只局限于该次登录的。若要每次登入都能够使用这些命令别名,则可将相应的alias命令存放到bash的初始化文件/etc/bashrc(对所有用户启动的shell都有效) 。
        用任意编辑器打开这个文件,如下图框出的地方就可以设置“永久别名”,语法参考图中示例。暂时不要在不清楚本文件其他用途的时候随意修改。

图9:打开配置文件



        本篇文章的重点在于理解I/O重定向的用法。对于管道的使用,并没有过多的例子,这会在以后提到。也许目前为止感觉不到这些东西有什么大用,其实在具体应用场景中,才能体会到它们的好处。

评分

参与人数 3人气 +4 收起 理由
翼风Fly + 1
ForeverX + 1 赞一个!
4毛5的诺顿 + 2 版区有你更精彩: )

查看全部评分

我撤退,你掩护
发表于 2018-2-7 19:12:42 | 显示全部楼层
谢谢分享
tanglf
发表于 2018-2-7 20:46:19 | 显示全部楼层
学习
收藏
piouu
发表于 2018-2-7 21:07:22 | 显示全部楼层
ubuntu16.04,可以更新了
liu浪的人
发表于 2018-2-7 21:58:47 | 显示全部楼层
比如说
2018-02-07 21-58-30屏幕截图.png




邂逅相识是缘
发表于 2018-2-11 07:50:59 | 显示全部楼层
学习学习。
ask007
发表于 2018-2-11 13:48:26 | 显示全部楼层
给个建议, alias这个设置最好放在用户配置文件中(~/.bashrc),修改/etc/bashrc会影响所有用户,而各个用户的习惯可能不一样。
im-t
发表于 2018-2-13 22:05:56 | 显示全部楼层
举例那里,chown重复了,chmod后少个是,ldd字体小了一号。
FUZE
发表于 2018-2-14 22:17:02 | 显示全部楼层
靴习一个,虽然一直没入坑....
您需要登录后才可以回帖 登录 | 快速注册

本版积分规则

手机版|杀毒软件|软件论坛|优惠券| 卡饭论坛

Copyright © KaFan  KaFan.cn All Rights Reserved.

Powered by Discuz! X3.4( 苏ICP备07004770号 ) GMT+8, 2018-7-18 10:31 , Processed in 0.129340 second(s), 25 queries .

快速回复 返回顶部 返回列表