主要概念:

1.基于终端的程序往往从一个源读取信息,向一个目的地写入信息;

2.程序读取的源被称为标准输入(简称为stdin),通常与终端键盘连接;

3.程序写入的目的地被称为标准输出(简称为stdout),通常与终端显示器相连;

4.使用bash Shell时,可以用>或>>重定向标准输出,用<重定向标准输入;


许多Linux命令从键盘读取输入,向终端显示输出。一个命令的输出可以用作另一个命令的输入,从而可以同时使用多个简单的命令来执行更复杂的任务。


三种类型的程序:

1.图形程序

图形程序是为在X图形环境中运行设计的。它们希望用户使用鼠标,并且使用常用的图形组件,如弹出菜单和按钮作为用户输入。Firefox网络浏览器就是一种图形程序。


2.屏幕程序

基于屏幕的程序使用文本控制台。它们利用整个屏幕熟练地处理文本定位和屏幕刷新。它们不需要鼠标,因此适用于终端盒虚拟控制台。vi和nano文本编辑器以及links网络浏览器都属于屏幕程序。


3.终端程序

终端程序以流的形式聚集输入和显示输出,很少刷新屏幕,终端程序以其简明的特点经常被简单地称作命令。ls、grep和useradd属于终端程序。


例如:

1.用户elvis使用的机器变得非常缓慢,为了诊断问题,elvis想检查当前运行的进程,但是由于机器反应很慢,他现在先搜集信息,之后再做分析,他把ps aux命令的输出重定向到文件pusaux.txt文件中,当机器反应快时再回头检查这个文件。

[root@host2 tmp]# ps aux > /tmp/sluggish.txt


2.elvis现在不仅想要收集进程信息,还要记录电脑出现反应迟钝情况时的时间戳

[root@host2 tmp]# date > psaux.txt | ps aux >> sluggish.txt
[root@host2 tmp]# head sluggish.txt 
Wed Nov  5 19:07:00 CST 2014
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.1  0.1  19352  1536 ?        Ss   18:50   0:01 /sbin/init
root         2  0.0  0.0      0     0 ?        S    18:50   0:00 [kthreadd]
root         3  0.0  0.0      0     0 ?        S    18:50   0:00 [migration/0]
root         4  0.0  0.0      0     0 ?        S    18:50   0:00 [ksoftirqd/0]
root         5  0.0  0.0      0     0 ?        S    18:50   0:00 [migration/0]
root         6  0.0  0.0      0     0 ?        S    18:50   0:00 [watchdog/0]
root         7  0.1  0.0      0     0 ?        S    18:50   0:01 [events/0]
root         8  0.0  0.0      0     0 ?        S    18:50   0:00 [cgroup]


3.用户elvis用基于终端的mail命令从键盘上给管理员写了一封电子邮件。mail命令把收件人当做一个参数,主题行可以用-s命令行选项指定,然后从键盘上键入邮件正文,另起一行上单独写一个英语的句号,标志着邮件正文结束。

[root@host2 /]# mail -s "Computer is sluggish" sysadmin@example.com
Hey sysadmin:
I'm sending a list of processes that were running when the computer was running in a separate email.
Thanks!  --elvis
.
EOT


作为后续回复信息,用户elvis可以将记录在文件sluggish.txt中的ps命令输出发送出去,他只需重定向mail命令的标准输入流,使之从文件中读取就可以了。

[root@host2 tmp]# mail -s "ps output" sysadmin@example.com < sluggish.txt



【透过表象看本质:打开文件盒文件描述符】

为了全面理解进程如何管理标准输入、标准输出和文件,我们必须引入文件描述符(file descriptor)这一概念。要从文件读取信息或向文件写入信息,进程必须打开这个文件。Linux/Unix进程通过给每个当前被他们打开的文件赋整数值来追踪这些文件,这个整数被称作文件描述符。

Linux内核提供了一个简单的方法,用/proc文件系统来检查当前运行进程打开的文件和文件描述符。每个进程在/proc下有一个相关的子目录,以其进程ID命名。进程的子目录里有一个叫做fd(file descriptor)的子目录。在/proc/pid/fd子目录中,进程打开的每个文件都有一个符号连接。符号连接的名称是打开文件的整数文件描述符,符号连接解析到被打开文件本身。


例子:

ftp和gnuplot程序都是复杂的程序,因此这几个例子仅仅介绍了与本节主题相关的程序功能:如果程序是从命令行界面上驱动的,通常可以用简单的文本输入和重定向自动驱动这个程序。

1.走出sort命令的困惑

用户使用sort命令对文本文件zoo中的动物进行排序;

[root@host2 tmp]# ls
zoo
[root@host2 tmp]# cat zoo 
elephant
seal
ape
giraffe
fish
[root@host2 tmp]# sort zoo 
ape
elephant
fish
giraffe
seal
[root@host2 tmp]# sort < zoo
ape
elephant
fish
giraffe
seal


sort命令(以最简单的形式)读取文件,并写入按字母顺序逐行分类的内容。像cat命令一样,当没有提供任何参数时,sort命令将标准输入作为它的输出。

[root@host2 tmp]# sort
ls
quit
man sort
exit
get me out of this
exit
get me out of this
ls
man sort
quit


2.用户想用简单的方法生成机器CPU活动图。他对vmstst命令很熟悉,这个命令可以对设计系统性能许多参数进行抽样并制成表格,这个命令采用两个数字参数:

第一个指定了抽样时间(以秒为单位);

第二个指定了要采集的样本数;

他对后三列很感兴趣,这三列是CPU在用户(us)、系统(sy)和空闲(id)状态上所花的时间百分比。他从机器上采集了60秒的数据,抽样检查每秒钟的数据。

[root@host2 tmp]# vmstat 1 60 > stats.txt
[root@host2 tmp]# head stats.txt 
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 256156  74520 257560    0    0    38     9   43   73  0  0 99  1  0
 0  0      0 256140  74520 257592    0    0     0     0   27   50  0  0 100  0  0
 0  0      0 256140  74520 257592    0    0     0     0   29   48  1  0 99  0  0
 0  0      0 256140  74520 257592    0    0     0     0   22   40  0  0 100  0  0
 2  0      0 256140  74520 257592    0    0     0     0   25   53  0  0 100  0  0
 0  0      0 256140  74520 257592    0    0     0     0   25   49  0  1 99  0  0
 1  0      0 256140  74528 257592    0    0     0    56   30   55  1  0 99  0  0
 1  0      0 256132  74528 257592    0    0     0    88   48   57  0  2 98  0  0


由于前两行文本影响了数据图,用户在文本编辑器中打卡文件stats.txt,轻而易举地把它们删除了。


为了绘制数据图,她使用了gnuplot命令,这是一个复杂的绘图软件包,使用从终端界面读取的命令来生成数学函数和数值数据图。浏览了gnuplot在线帮助后,她用下列命令绘制数据图,生成了一个叫做cpu.png的PNG制图文件。

#gnuplot
gnuplot>set term png
gnuplot>set output 'cpu.png'
gnuplot>plot 'stats.txt' using 0:13 title "user" with lines,'stats.txt' using 0:14 title "system" with lines,'stats.txt' using 0:15 title "idle" with lines
gnuplot>quit

退出gnuplot命令后,他返回到bash shell,用ego图像浏览器查看数据图,如图所示:


由于他想经常生成类似的图,而且不想每次都痛苦地敲gnuplot的绘图命令,于是他生成了一个可以用来自动运行gnuplot的脚本,编辑了一个文件cpu_plot.gnuplot,其中包含了所有敲入gnuplot命令:

#cat cpu_plot.gnuplot
set term png
set output 'cpu.png'
plot 'stats.txt' using 0:13 title "user" with lines,'stats.txt' using 0:14 title "system" with lines,'stats.txt' using 0:15 title "idle" with lines


现在,他将脚本重定向为gnuplot标准输入来方便地绘制新采集的数据:

#gnuplot < cpu_plot.gnuplot


标准输入、标准输出和错误输出的文件描述流:

数据流    描述符    缩写

标准输入    0        stdin

标准输出    1        stdout

标准错误    2        stderr


【重定向】


>输出重定向,覆盖掉原有内容;称为覆盖输出

<输入重定向

>>追加输出,在原文后追加输入内容

<<在此处生成文档(here document)


set -C禁止对已经存在的文件使用覆盖重定向

强制覆盖输出,则使用 >|

set +C关闭上述功能


2>重定向错误输出

2>>追加方式重定向错误输出

&>重定向标准输出或错误输出至同一个文件(输出所有)


-----bash中重定向标准输入、标准输出和标准错误一览表-----

cmd < file从file重定向标准输入

cmd > file把标准输出重定向到file中,如果file存在的话,覆盖(损坏)它

cmd >> file把标准输出重定向到file中,如果file存在,附加给它

cmd 2> file把标准错误重定向到file,如果file存在,覆盖(损坏)它

cmd 2>> file把标准错误重定向到file,如果file存在,附加给它

cmd > file 2> &1合并标准输出和标准错误,并且重定向到file中(可移植的语法)

cmd >& file合并标准输出和标注错误,并且重定向到file中(方便的语法)


【用/dev/null过滤标准错误】

find /var -user elvis 2> /tmp/tmp 
find /var -user elvis 2> /dev/null


因为elvis的权限有限,var下面的目录中与用户elvis有关的子目录就显示出来,但更多是保所有权限拒绝的错误信息,因此要筛选错误;

第一种方法虽然过滤了错误信息,但却多了个用户并不想要的tmp文件,因此采用了第二种方法过滤;

在这种情况下,当用户想抛弃信息流时,有经验的Unix用户通常会把输出重定向到一个叫做/dev/null的伪设备中。

/dev/null是一个字符设备节点,就像用在约定的设备驱动中的节点一样。

当用户写入/dev/null时,信息只会被内核抛弃,当用户从/dev/null读取时,他们会很快读完文件。注意,RHEL默认配置下,/dev/null是少数几个普通用户有写入权限的文件之一。


ls /varr > /tmp/var1.out 2> /tmp/var2.out

如果正确就输出到var1.out,如果错误就输出到var2.out


END有时候也用EOF(End of File)

[root@host2 tmp]# cat << END
> the first line.
> the second line.
> END
the first line.
the second line.
[root@host2 tmp]# cat >> /tmp/file.txt << EOF
> the first line.
> the second line.
> EOF
[root@host2 tmp]# ls
file.txt
[root@host2 tmp]# cat file.txt 
the first line.
the second line.