原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://twentyfour.blog.51cto.com/945260/521455

知识体系:

#回顾重定向

#标准输入和输出

#报告错误

#丢弃数据

#创建日志文件

这里主要讲述如何将脚本重定向到linux系统的各个位置。

1、了解输入和输出

我们知道显示脚本输出的方法有两种:

*在监视器屏幕上显示

*将输出重定向到文件

下面主要讲述如何使用标准的linux输入和输出体系满足将脚本输出定向到特定位置的需求。

1.1、标准文件描述符

linux使用文件描述符来标识每个文件对象,每个进程最多有9个可以打开文件的描述符(且非零),bash
shell为特殊需要保留了前三个文件描述符(0、1、2),如下所示:

**************************************

文件描述符   
缩写      
描述

0          
STDIN      
标准输入

1          
STDOUT     
标准输出

2          
STDERR     
标准错误
**************************************

shell使用他们将shell中的默认输入输出重定向到相应的位置,默认就是监视器屏幕了。

下面简单讲述下这三个保留的文件描述符:

1》STDIN

STDIN文件描述符引用shell的标准输入,对于终端接口的标准输入就是键盘了。当然,我们可以使用输入重定向符号(<)也可以使其读取文件中的数据,跟键盘输入时一样的道理。先来看个例子:

[root@wzp ~]# cat

i am twentyfour , who are you ?

i am twentyfour , who are you ?
我直接输入cat后回车,结果我输入什么内容,系统就显示一样的内容。

这就是cat命令通过STDIN输入数据的示例。
[root@wzp
~]# vim testfile

[root@wzp ~]# cat < testfile

aaaaaaaaaaaa

bbbbbbbbbbbb

cccccccccccc
现在cat命令使用包含在testfile文件的中行作为输入,也是标准输入。

2》STDOUT

STDOUT文件描述符引用shell的标准输出,在终端接口的标准输出就是终端监视器。我们可以使用输出重定向(>)或者追加(>>)向文件添加数据。对于这个都是很好理解的,看个例子:
[root@wzp
~]# ls > 51cto.test

[root@wzp ~]# cat 51cto.test

51cto.test

anaconda-ks.cfg

Desktop

install.log

install.log.syslog

linux-linkto-mysql

login-mysql

mbox

sendto-mysql
如上把定向到监视器的内容重定向到文件中。

3》STDERR

STDERR文件描述符处理错误消息,默认情况下将所有错误消息显示在监视器上,具体应用下来讲述。

1.2、重定向错误

重定向STDERR数据的时候只要定义好STDERR文件描述符即可,这里头分两种情况的数据重定向。

(1)先来第一种:仅重定向错误消息

我们已经知道ETDERR文件描述符值为2,在重定向符号前附加2即可把错误消息重定向到具体的位置去,看个例子:
[root@wzp
~]# ll 51cto 2> errfile

[root@wzp ~]# cat errfile 
ls: 51cto: 没有那个文件或目录

就是说明知道不存在51cto,然后去ll后把错误消息重定向到errfile中,而不是默认的显示在显示器上。下面的例子也如此:
[root@wzp
~]# ll 51cto.test 51cto 2>> errfile

-rw-r--r-- 1 root root 115 02-14 17:02 51cto.test

[root@wzp ~]# cat errfile

ls: 51cto: 没有那个文件或目录

ls: 51cto: 没有那个文件或目录
从结果都可以看出存在的文件显示在屏幕上,而不存在的文件的报错消息被追加到errfile文件中。

(2)还有一种是:重定向错误和数据

既然要分开处理错误消息和正确的数据显示,我们就可以通过1>符号进行标准输出重定向,和2>进行错误消息重定向,看个例子就明白了:
[root@wzp
~]# ls -al 51cto.test install.log linux rhca 1> exist 2> error
[root@wzp ~]# cat exist

-rw-r--r-- 1 root root   115
02-14 17:02 51cto.test

-rw-r--r-- 1 root root 27682 12-12 18:06 install.log

[root@wzp ~]# cat error

ls: linux: 没有那个文件或目录

ls: rhca: 没有那个文件或目录
存在的文件重定向到exist文件中,不存在的文件把报错信息重定向到error中,这就是灵活使用1>和2>符号的效果。

当然,假如你想把正确输出的错误输出都重定向到一个文件的时候可以使用特殊的重定向符号:&>
先来看个例子:
[root@wzp
~]# ls -al 51cto.test install.log linux rhca &>
totalfile

[root@wzp ~]# cat totalfile

ls: linux: 没有那个文件或目录

ls: rhca: 没有那个文件或目录

-rw-r--r-- 1 root root   115
02-14 17:02 51cto.test

-rw-r--r-- 1 root root 27682 12-12 18:06 install.log
我们看到totalfile包含的所有信息,并且是按照顺序排列两类信息。

2、在脚本中重定向输出

使用脚本重定向输出的方法有两种:

*临时重定向每一行

*在脚本中永久性重定向所有命令

2.1、临时重定向

我们可以通过在文件描述符前加&符号来把一些输入重定向到文件描述符中,然后在重定向输入的时候调用这些文件描述符,也行听起来觉得怪怪的不好理解,OK,先来看个例子:

[root@wzp ~]# chmod u+x 5.2test

[root@wzp ~]# cat 5.2test

#!/bin/bash

echo "this is a error" >&2

echo "this is normal output"

[root@wzp ~]# ./5.2test

this is a error

this is normal output
这个脚本执行后没什么不同之处,但"this is a error" >&2已经是把这个"this is a
error"消息重定向给STDERR文件描述符了。
[root@wzp
~]# ./5.2test 2> errorfile

this is normal output

[root@wzp ~]# cat errorfile

this is a error
如上就表示把STDERR文件描述符的消息"this is a
error"重定向给errorfile文件。所以我们知道,这里头的动作有两个重定向!

2.2、永久重定向

如果在脚本中要重定向许多数据,可以通过exec命令通知shell在脚本执行中重定向特定的文件描述符,先看如下例子:
[root@wzp
~]# cat 5.2test

#!/bin/bash

exec 1>testfile

echo "welcome to CHINA"

date

[root@wzp ~]# ./5.2test

[root@wzp ~]# cat testfile

welcome to CHINA

2011年 02月 14日 星期一 19:15:25 CST
exec命令启动一个新的shell,并且STDOUT文件描述符重定向到testfile。

当然还可以在脚本中重定向到STDOUT,看如下例子:
[root@wzp
~]# cat 5.2test

#!/bin/bash

exec 2>testfile1

echo "aaaaaaaaa"

exec 1>testfile2

echo "bbbbbbbbb"

echo "ccccccccc" >&2

[root@wzp ~]# ./5.2test

aaaaaaaaa

[root@wzp ~]# cat testfile1

ccccccccc

[root@wzp ~]# cat testfile2

bbbbbbbbb
脚本内容是从上往下执行每个命令的,所以在STDERR后的echo
aa的内容势必显示在显示屏上。当定义了STDOUT后,bb的内容就被重定向到testfile2中。但是,虽然cc处于STDOUT之后,但是此行特意制定重定向到STDERR中,所以也就发生两次重定向最后处于testfile1中。

3、在脚本中重定向输入

重定向STDOUT和STDERR的技术也可以用来重定向键盘的STDIN,如

exec 0< testfile

该命令告诉shell应该从文件testfile而不是STDIN获取输入,如下例:

[root@wzp ~]# chmod u+x 5.3test

[root@wzp ~]# cat 5.3test

#!/bin/bash

exec 0< testfile

count=1

while read line

do

echo "Line #$count: $line"

count=$[ $count + 1 ]

done

[root@wzp ~]# cat testfile

5555555

1111111

CCCCCCC

TTTTTTT

OOOOOOO

[root@wzp ~]# ./5.3test

Line #1: 5555555

Line #2: 1111111

Line #3: CCCCCCC

Line #4: TTTTTTT

Line #5: OOOOOOO
如上表示把testfile中的每一行重定向到STDIN中,然后通过变量line把STDIN的内容逐行echo出来。

4、创建自己的重定向

一开始我就提及到shell中最多可以有9个打开的文件描述符,其他六个的编号是3~8,对于这6个文件描述符同样可运用在较本中。

4.1、创建输出文件描述符

直接来看一个例子,非常好理解:

[root@wzp ~]# chmod u+x 5.4test

[root@wzp ~]# cat 5.4test

#!/bin/bash

exec 3> testfile

echo "aaaaaaa"

echo "bbbbbbb" >&3

[root@wzp ~]# ./5.4test

aaaaaaa

[root@wzp ~]# cat testfile

bbbbbbb
对于aa的正常显示没啥好说,而bb的内容被重定向给文件描述符3,然后文件描述符3再次重定向给文件testfile,所以可以预知testfile的内容。

4.2、重定向文件描述符

对于重定向文件描述符说起来挺复杂的,先看个例子解释下:
[root@wzp
~]# cat 5.4test

#!/bin/bash

exec 3>&1

exec 1>testfile

echo "today is so cold"

exec 1>&3

echo "kobe bryant is great" >&3

[root@wzp ~]# ./5.4test

kobe bryant is great

[root@wzp ~]# cat testfile

today is so cold
第一次看如上的脚本,也许会头晕的。呵呵,把文件描述符3重定向给STDOUT,而STDOUT重定向给文件testfile,接下来的echo标准输出,所以对应上面的理念存到testfile中,先理解好这点!接下来就是STDOUT重定向给文件描述符3,而下面的echo重定向内容给文件描述符3,回头看脚本exec
3>&1,很明显把echo的内容重定向给etdout了,所以就显示在屏幕上

4.3、创建输入文件描述符

之所以要讲述这个就是说当出现有文件重定向输入文件描述符的时候,并且出现键盘输入这样的STDIN普通设置,我们可以通过先把默认的输入文件描述符重定向给2~9这样的文件描述符,等文件的内容被重定向结束后回过头来把先前设置的2~9文件描述符重定向到默认的STDIN,恢复原状。也许你对这段话看起来觉得费解,可以先理解下面的例子:
[root@wzp
~]# cat testfile

aaaaaaaaaaaa

bbbbbbbbbbbb

cccccccccccc

[root@wzp ~]# cat 5.4test

#!/bin/bash

exec 6<&0

exec 0< testfile

count=1

while read wzp

do

echo  "Line #$count :
$wzp"

count=$[ $count + 1 ]

done

exec 0<&6

read -p "are you sure now ?"

case $REPLY in

Y | y) echo "OK , Goodbye";;

N | n) echo "Why ?";;

esac

[root@wzp ~]# ./5.4test

Line #1 : aaaaaaaaaaaa

Line #2 : bbbbbbbbbbbb

Line #3 : cccccccccccc

are you sure now ?y

OK , Goodbye

[root@wzp ~]# ./5.4test

Line #1 : aaaaaaaaaaaa

Line #2 : bbbbbbbbbbbb

Line #3 : cccccccccccc

are you sure now ?N

Why ?
如上要把testfile的内容重定向输入,随着while循环通过read命令读取testfile每一行。等这个读取的过程完成以后,把文件描述符6重定向为默认的STDIN,也就是文件描述符0,就可以通过键盘输入了。并且借用read命令的-p选项做交互性问答。

4.4、关闭文件描述符
有时候想在脚本运行过程中关闭一些输入输出文件描述符,使得其失去存在意义,这个时候可以借用特殊符号 &-
exec 3>$-  
这就表示文件描述符3在脚本中不能使用,先来看个例子:
[root@wzp
~]# cat 5.4test

#!/bin/bash

exec 8> testfile

echo "i will come back to school soon" >&8

exec 8>&-

echo "lalalalala" >&8

[root@wzp ~]# ./5.4test

./5.4test: line 5: 8: 错误的文件描述符

[root@wzp ~]# cat testfile

i will come back to school soon
把回校的消息重定向到&8,而&8重定向到testfile中,这点没什么质疑的。然后把&8关闭后,再次使用echo重定向给&8就报错了,当然,testfile的内容肯定是有的,脚本即便报错也是有运行结束。

5、列出开放文件描述符

因为可用的文件描述符有9个,所以有时候会出现很难跟踪哪个文件描述符重定向到哪个位置的情况发生,这个时候就可以借用losf命令理清线索。

lsof输出有很多参数和选项,常用的有-p,该参数可以指定进程ID;还有-d可以指定要显示饿文件描述符编号。

为了轻松确定进程当前的PID,可以借助特殊环境变量$$,而-a选择则是用于连接其他两个选项的结果,如下:

[root@wzp ~]# lsof -a -p $$ -d
0,1,2

COMMAND   PID
USER  
FD   TYPE DEVICE SIZE NODE
NAME

bash    19302
root   
0u   CHR 
136,0        
2 /dev/pts/0

bash    19302
root   
1u   CHR 
136,0        
2 /dev/pts/0

bash    19302
root   
2u   CHR 
136,0        
2 /dev/pts/0
把0、1、2文件描述符的相关进程显示出来。

6、禁止命令输出

有时候一个脚本在后台运行出现了一些错误,shell就会通过mail通知进程的所有者,而这些错误却是无关紧要的。这个时候就可以利用回收站来处理这些错误信息。这就是我经常使用的linux系统特有的/dev/null空设置文件,可谓无底洞,给他多少吃多少。。。

先来看看例子:

[root@wzp ~]# echo aaaaa > /dev/null

[root@wzp ~]# cat /dev/null 
查看的时候一直为空,再来看个例子:
[root@wzp
~]# cat testfile

i will come back to school soon

[root@wzp ~]# cat /dev/null > testfile

[root@wzp ~]# cat testfile
利用上面原本存在数据的testfile文件,把空文件重定向到该文件中,结果testfile的内容都被吃光了,O(∩_∩)O哈哈~

7、使用临时文件

linux系统有一个创建临时文件的特殊命令mktemp,可以在临时目录/tmp创建一个唯一的临时文件。不过,创建的临时文件不使用默认的umask值,而是600权限的文件。

7.1、创建本地临时文件

mktemp可以在任一目录创建临时文件,并且只需指定一个文件模板名即可。模板包括文本文件名和文件名后6的大写的X。如下:

[root@wzp ~]# mktemp 51cto.XXXXXX

51cto.Z26308

[root@wzp ~]# ll 51cto.Z26308

-rw------- 1 root root 0 02-14 23:05 51cto.Z26308

后面的Z26308是系统随意创建的,并且具有唯一性

[root@wzp ~]# mktemp 51cto.XXXXXX

51cto.n26366

[root@wzp ~]# mktemp 51cto.XXXXXX

51cto.o26367

[root@wzp ~]# mktemp 51cto.XXXXXX

51cto.G26369

[root@wzp ~]# ll 51cto.*

-rw------- 1 root root 0 02-14 23:07 51cto.G26369

-rw------- 1 root root 0 02-14 23:07 51cto.n26366

-rw------- 1 root root 0 02-14 23:07 51cto.o26367
所以放心,决不出现一样文件名的临时文件

7.2、在/tmp中创建临时文件

-t选项强迫mktemp在系统的/tmp目录下创建文件,这是一个挺不错的特性,直接看看例子:
[root@wzp
~]# mktemp -t wzp.XXXXXX

/tmp/wzp.I26701

[root@wzp ~]# ll /tmp/wzp.I26701

-rw------- 1 root root 0 02-14 23:16 /tmp/wzp.I26701
由于mktemp命令返回完整路径名,因此可以从linux系统引用临时文件,如下例子:
[root@wzp
~]# chmod u+x 7.2test

[root@wzp ~]# cat 7.2test

#!/bin/bash

tempfile=`mktemp -t tmp.XXXXXX`

echo "this is a temp file" >$tempfile

[root@wzp ~]# ll /tmp/tmp.u26849

-rw------- 1 root root 20 02-14 23:21 /tmp/tmp.u26849

[root@wzp ~]# cat /tmp/tmp.u26849

this is a temp file
通过这种方式非常的方便,灵活调用系统目录文件。

7.3、mktemp不仅可以创建临时文件,还可临时创建目录
以借用-d选项创建临时目录,下例:
[root@wzp
~]# chmod u+x 7.3test

[root@wzp ~]# ./7.3test

[root@wzp ~]# cat 7.3test

#!/bin/bash

tempdir=`mktemp -d dir.XXXXXX`

cd $tempdir

tempfile1=`mktemp temp.XXXXXX`

tempfile2=`mktemp temp.XXXXXX`

exec 7> $tempfile1

exec 8> $tempfile2

echo "this is 7" >&7

echo "this is 8" >&8

[root@wzp ~]# ll dir.A27050/

总计 16

-rw------- 1 root root 10 02-14 23:27 temp.f27052

-rw------- 1 root root 10 02-14 23:27 temp.p27051

[root@wzp ~]# cat dir.A27050/temp.f27052

this is 8

[root@wzp ~]# cat dir.A27050/temp.p27051

this is 7
通过创建临时目录后切换目录创建临时文件。

8、记录消息

有时候需要将输出同时发送到监视器和日志文件中,这个时候不需要使用两次重定向,只要使用特殊的tee命令即可。

比如看下简单的操作:

[root@wzp ~]# date | tee testfile

2011年 02月 14日 星期一 23:31:05 CST

[root@wzp ~]# cat testfile

2011年 02月 14日 星期一 23:31:05 CST
由于tee重定向来自于STDIN的数据,因此配合管道命令就可以把输出显示在监视屏和指定的文件中。

如果希望对如上的testfile文件不断增加这样的数据,必须使用-a选项,先看看一个效果:
[root@wzp
~]# cal | tee testfile

二月
2011

日 一 二 三 四 五 六

1  2  3 
4  5

6  7 
8  9 10 11 12

13 14 15 16 17 18 19

20 21 22 23 24 25 26

27 28

[root@wzp ~]# cat testfile

二月
2011

日 一 二 三 四 五 六

1  2  3 
4  5

6  7 
8  9 10 11 12

13 14 15 16 17 18 19

20 21 22 23 24 25 26

27 28
你会发现date的内容没了,也就好比是重定向完全覆盖的概念,所以想追加内容到文件中就必须使用-a选项,例子:
[root@wzp
~]# date | tee -a testfile

2011年 02月 14日 星期一 23:35:10 CST

[root@wzp ~]# cat testfile

二月
2011

日 一 二 三 四 五 六

1  2  3 
4  5

6  7 
8  9 10 11 12

13 14 15 16 17 18 19

20 21 22 23 24 25 26

27 28

2011年 02月 14日 星期一 23:35:10 CST
对于这样的效果就比较好,可以把各个信息都归档到一个日志文件中。

本文出自 “twenty_four
博客,请务必保留此出处http://twentyfour.blog.51cto.com/945260/521455


bash&nbsp;shell笔记5&nbsp;显示数据的更多相关文章

  1. bash&nbsp;shell笔记1&nbsp;脚本基础知识

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://twentyfour.blog.51cto.com/945260/505644 * ...

  2. bash&nbsp;shell笔记4&nbsp;处理用…

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://twentyfour.blog.51cto.com/945260/521448 知 ...

  3. bash&nbsp;shell笔记7&nbsp;创建函数

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://twentyfour.blog.51cto.com/945260/525126 知 ...

  4. bash&nbsp;shell笔记3&nbsp;结构化命令二

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://twentyfour.blog.51cto.com/945260/513601 三 ...

  5. bash&nbsp;shell笔记2&nbsp;结构化命令

    二.使用结构化命令 知识内容: # 改变命令流 # 使用if-then逻辑 # 嵌套if-then # 测试条件 # 高级if-then功能 许多程序在脚本命令之间需要某些逻辑控制流,有些命令允许脚本 ...

  6. bash&nbsp;shell笔记6&nbsp;脚本控制

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://twentyfour.blog.51cto.com/945260/522415 知 ...

  7. 08 bash特性--shell脚本编程入门

    shell脚本编程入门 编程语言介绍 编程语言分为:机械语言.汇编语言和高级语言: 计算机能识别的语言为机械语言,而人类能学习的并且能够方便掌握的为高级语言,所以,我们所编写的程序就要通过编译来转换成 ...

  8. shell 编程 && bash 简介(shell 变量、shell操作环境、数据流重导向、管线命令、shell script)

    如何学习一门编程语言 数据类型 运算符 关键字 1 认识BASH 这个shell linux是操作系统核心,用户通过shell与核心进行沟通,达到我们想要的目的.硬件.核心.用户之间的关系: 原理:所 ...

  9. shell脚本获取mysql插入数据自增长id的值

    shell脚本获取mysql插入数据自增长id的值 在shell脚本中我们可以通过last_insert_id()获取id值,但是,需要注意的是,该函数必须在执行插入操作的sql语句之后,立即调用,否 ...

随机推荐

  1. Python基础学习(第7天)

    第6课 1.循环对象:包括一个next方法,这个方法的目的是进行到下一个结果,结束后抛出StopInteration异常: 当循环结构如for循环调用一个循环对象时,每次循环的时候都会调用next方法 ...

  2. 《修炼Java开发技术 在架构中体验设计模式和算法之美》 - 书摘精要

    (P7) 建议直接加入到软件公司中去,这样会学到很多实际的东西: 程序员最主要的发展方向是资深技术专家,无论是 Java..Net 还是数据库领域,都要首先成为专家,然后才可能继续发展为架构师: 增强 ...

  3. css权威指南读书笔记

    今天翻手机,翻到了许久之前看css权威指南时的笔记,遂移到博客中来. 1.属性选择器p.one class名为one的p元素p[class][name] 含有class和name属性的p元素p[cla ...

  4. js中的函参(arguments)

    函参,顾名思义,就是函数的参数,一般我们的js函数这么写: function sum(a,b){ console.log(a+b); } 不难看出,这实现了两个数的相加,比如sum(1,2),打印结果 ...

  5. YARN学习笔记——Overview and Architecture

    YARN的简介 什么是YARN MRv1的架构和缺陷 经典MapReduce的局限性 解决可伸缩性问题 YARN的架构 一个可运行任何分布式应用程序的集群 YARN中的应用程序提交 YARN的其他特性 ...

  6. Mouse without Borders 跨屏鼠标

    Mouse without Borders 跨屏鼠标 软件方式 当你有几台电脑同时工作时,不停的换鼠标和键盘是非常不方便的. 如果用的 Mouse without Borders 就不一样了,可以在多 ...

  7. python 函数名,闭包

    1.函数名字的应用 函数名是什么? 函数名是函数的名字,本质:变量,特殊变量 函数名+() ———>执行此函数: 2.函数名的赋值: def func2(): print(44) f = fun ...

  8. INSTALL_FAILED_SHARED_USER_INCOMPATIBLE的问题

    eclipse编译出来的apk,安装时报出INSTALL_FAILED_SHARED_USER_INCOMPATIBLE的错误. 原因:apk的AndroidManifest.xml中声明了andro ...

  9. Host ASP.NET WebApi in Owin

    什么是OWIN Owin其实是微软为了解耦.Net Web app对IIS的依赖而制定的一套规范,规范定义了Web Server与Web App之间的接口,这样Web App就可以Host在所有兼容O ...

  10. yii console

    Here is a step by step to show how to run command in the server with yii framework. 1. Create the we ...