Linux Shell脚本编写——呈现数据(五)

Linux系统将每个对象当做文件来处理。这包括输入和输出的过程。Linux用文件描述符来标识每个文件对象。文件描述符是一个非负整数,可以唯一地标识会话中打开的文件。每个过程一次最多可以有9个文件描述符。出于特殊目的,bash shell保留了最早的3个文件描述符(0、1和2)

Linux的标准文件描述符
文件描述符 缩写 描述
0 STDIN 标准输入
1 STDOUT 标准输出
2 SRDERR 标准错误

STDIN

STDIN文件描述代表shell的标准输入。对于终端界面来说,标准输入就是键盘,shell从SDTIN文件描述符对应的键盘获得输入,在用户输入时处理每个字符,在使用输入重定向符号(<)时,Linux会用重定向指定的文件来替换标准输入文件的描述符。它会读取文件并提取数据,就如同它是从键盘上键入的

只输入cat命令时,它会接受STDIN输入,当用户在每行输入时,cat命令会将每行显示在输出,按Ctrl+C退出

代码5-1

[email protected]:~# cat
this is a test
this is a test
this is a second test
this is a second test
^C

  

通过STDIN重定向符号强制cat命令接受来自另一个非STDIN文件的输入

代码5-2

[email protected]:~# cat text
This is the first line
This is the second line
This is the third line
[email protected]:~# cat < text
This is the first line
This is the second line
This is the third line

  

STDOUT 

STDOUT文件描述代表标准的shell输出。在终端界面上,标准输出就是终端显示器。shell的所有输出会被定向到标准输出中

代码5-3

[email protected]:~# ls -l /home/ > demo1
[email protected]:~# cat demo1
total 36
drwxr-xr-x 58 root root  4096 Nov 28 16:52 backup
drwxr-xr-x  2 root root  4096 Aug 25 10:29 conf
drwx------  2 root root 16384 Aug 24 16:53 lost+found
drwxr-xr-x  4 root root  4096 Aug 25 10:29 mysql
drwxr-xr-x  8 root root  4096 Oct  8 13:09 software
drwxr-xr-x  2 root root  4096 Aug 25 10:41 tmp

  

代码5-4

[email protected]:~# ls -l /home/software/ >> demo1
[email protected]:~# cat demo1
total 36
drwxr-xr-x 58 root root  4096 Nov 28 16:52 backup
drwxr-xr-x  2 root root  4096 Aug 25 10:29 conf
drwx------  2 root root 16384 Aug 24 16:53 lost+found
drwxr-xr-x  4 root root  4096 Aug 25 10:29 mysql
drwxr-xr-x  8 root root  4096 Oct  8 13:09 software
drwxr-xr-x  2 root root  4096 Aug 25 10:41 tmp
total 233600
drwxr-xr-x 9 root root      4096 Nov 25  2014 apache-tomcat-1
drwxr-xr-x 9 root root      4096 Nov 25  2014 apache-tomcat-2
drwxr-xr-x 9 root root      4096 Aug 22 08:32 apache-tomcat-rental
drwxr-xr-x 3 root root      4096 Jan  8  2015 code
drwxr-xr-x 8 uucp  143      4096 Nov 25  2014 java
-rw-r--r-- 1 root root  55062846 Aug 25 10:41 rental.tar.gz
-rw-r--r-- 1 root root  30531249 Oct  8 10:14 scala-2.10.3.tgz
-rw-r--r-- 1 root root 153586658 Aug 25 10:34 software.tar.gz

  

当命令生成错误消息时,shell并未将错误消息重定向到输出重定向文件。shell创建了输出重定向文件,但错误消息却显示在显示器上

代码5-5

[email protected]:~# ls -l /badfile/ > demo2
ls: cannot access /badfile/: No such file or directory
[email protected]:~# cat demo2
[email protected]:~#

  

STDERR

shell通过特殊的STDERR文件描述符来处理错误消息。shell或shell中运行的程序和脚本出错时生成的错误消息都会发送到这个位置将标准错误符号写在重定向符号的前面,可将错误信息打印进error文件,但只能打印错误信息

代码5-6

[email protected]:~# ls -l /badfile/ 2> error
[email protected]:~# cat error
ls: cannot access /badfile/: No such file or directory

  

重定向错误和数据

代码5-7

[email protected]:~# ls -l
total 4
-rw-r--r-- 1 root root 800 Dec  4 20:41 demo1
[email protected]:~# ls -al demo1 demo2 demo3 demo4 demo5 demo6 2>error 1>text
[email protected]:~# ls
demo1  error  text
[email protected]:~# cat error
ls: cannot access demo2: No such file or directory
ls: cannot access demo3: No such file or directory
ls: cannot access demo4: No such file or directory
ls: cannot access demo5: No such file or directory
ls: cannot access demo6: No such file or directory
[email protected]:~# cat text
-rw-r--r-- 1 root root 800 Dec  4 20:41 demo1

  

可以将STDERR和STDOUT的输出重定向到同一个输出文件

代码5-8

[email protected]:~# ls -l
total 4
-rw-r--r-- 1 root root 800 Dec  4 20:41 demo1
[email protected]:~# ls -al demo1 demo2 demo3 demo4 demo5 demo6 &>text
[email protected]:~# cat text
ls: cannot access demo2: No such file or directory
ls: cannot access demo3: No such file or directory
ls: cannot access demo4: No such file or directory
ls: cannot access demo5: No such file or directory
ls: cannot access demo6: No such file or directory
-rw-r--r-- 1 root root 800 Dec  4 20:41 demo1

  

如果故意要在脚本中生成错误消息,可以将单独的一行输出重定向STDERR,默认情况下,Linux会将STDERR定向到STDOUT,但是如果运行脚本时重定向了STDERR,脚本中所有定向到STDERR的文本会被重定向

代码5-9

[email protected]:~# cat demo2
#!/bin/bash
echo "This is an error" >&2
echo "This is normal output"
[email protected]:~# ./demo2
This is an error
This is normal output
[email protected]:~# ./demo2 2>error
This is normal output
[email protected]:~# cat error
This is an error

  

在脚本中重定向输出

代码5-10

[email protected]:~# cat demo3
#!/bin/bash
exec 2>error
echo "Hello world"
exec 1>out
echo "Hello Spring">&2
echo "Hello MyBatis"
[email protected]:~# ./demo3
Hello world
[email protected]:~# cat out
Hello MyBatis
[email protected]:~# cat error
Hello Spring

  

exec 0<text,这个命令告诉shell从text文件中获取输入而不是STDIN

代码5-11

[email protected]:~# cat text
Hello Spring
Hello Hibernate
Hello MyBatis
[email protected]:~# cat demo4
#!/bin/bash
exec 0<text
count=1
while read line
do
        echo "Line:#$count:$line"
        ((count++))
done
[email protected]:~# ./demo4
Line:#1:Hello Spring
Line:#2:Hello Hibernate
Line:#3:Hello MyBatis

  

Linux并不局限3个默认的文件描述符,shell中最多可以有9个打开的文件描述符,其他文件描述符从3排到8,其他描述符与3个默认的文件描述符用法类似,exec 3>>testfile会把输出追加到一个新的文件

下面这个例子:首先,脚本将文件描述符3重定向到文件描述符1的当前位置,也就是STDOUT,意味着发送给文件描述符3都会显示在屏幕上

在向STDOUT发送一些输出后,脚本会将STDOUT重定向到文件描述符3的当前位置,也就是显示器,即它原先的位置

代码5-12

[email protected]:~# cat demo5
#!/bin/bash
exec 3>&1
exec 1>out
echo "Hello World"
echo "Hello Spring">&3
echo "Hello Hibernate"
exec 1>&3
echo "Hello MyBatis">&3
echo "Hello Shiro"
[email protected]:~# ./demo5
Hello Spring
Hello MyBatis
Hello Shiro
[email protected]:~# cat out
Hello World
Hello Hibernate

  

代码5-13中, 文件描述符6用来保存STDIN的位置,然后脚本将STDIN重定向到一个文件。read命令的所有输入都是从重定向后的STDIN中来的,也就是输入文件。在读取完所有行后,脚本会将STDIN重定向到文件描述符6,从而将STDIN恢复到原先的位置

代码5-13

[email protected]:/data# cat text
Spring
MyBatis
Hibernate
Shiro
Hadoop
Spark
[email protected]:/data# cat demo2
#!/bin/bash
exec 6<&0
exec 0<text
count=1
while read line
do
        echo "Line #count:$line"
        ((count++))
done
exec 0<&6
read -p "Are you learned now?" answer
case $answer in
        Y|y) echo "Good job";;
        N|n) echo "GoodBye";;
esac
[email protected]:/data# ./demo2
Line #count:Spring
Line #count:MyBatis
Line #count:Hibernate
Line #count:Shiro
Line #count:Hadoop
Line #count:Spark
Are you learned now?n
GoodBye

  

也可以打开单个文件描述符来作为输入和输出,可以从同一个文件中读取数据,再将数据写入到同一个文件中,下例:exec命令将用作读取输入和写入文件描述符3分配给文件text。下一步,它通过分配好的文件描述符来用read命令读取文件中的第一行,然后将读取的那行输入显示在STDOUT上。之后,它用echo语句来向文件描述符打开的文件写入一行数据

当脚本向文件写入数据时,它会从文件指针所处的位置开始。read命令读取了第一行数据。所以它会让文件指针指向第二行数据的第一个字符。在echo语句将数据输出到文件中,它会将数据放在文件指针的当前位置,覆盖该位置的数据

代码5-14

[email protected]:/data# cat text
Spring
MyBatis
Hibernate
Shiro
Hadoop
Spark
[email protected]:/data# cat demo3
#!/bin/bash
exec 3<>text
read line<&3
echo "Read:$line"
echo "This is a test line">&3
[email protected]:/data# ./demo3
Read:Spring
[email protected]:/data# cat text
Spring
This is a test line
iro
Hadoop
Spark

  

当创建新的输入或输出文件描述符,Linux会在脚本退出时自动关闭它们,要关闭文件描述符,将它重定向到特殊符号&-

exec 3>&-

代码5-15

[email protected]:/data# cat demo4
#!/bin/bash
exec 3>text
echo "Hello Spring">&3
exec 3>&-
echo "Hello Hibernate" >&3
[email protected]:/data# ./demo4
./demo4: line 5: 3: Bad file descriptor
[email protected]:/data# cat text
Hello Spring

  

如代码5-15,一旦关闭了文件描述符,就不能在脚本中向它写入任何数据了,否则shell会生成错误消息

另外需要注意的一点是,关闭文件描述符后,如果后面又打开同一个输出文件,shell会用一个新文件替换已有文件这意味着之前的数据不会存在

代码5-16

[email protected]:/data# cat demo5
#!/bin/bash
exec 3>text
echo "Hello World">&3
exec 3>&-
cat text
exec 3>text
echo "Hello Spring">&3
echo "Hello Hibernate">&3
[email protected]:/data# ./demo5
Hello World
[email protected]:/data# cat text
Hello Spring
Hello Hibernate

  

如果不希望在运行程序时又错误消息出现,可以将STDERR重定向到/dev下一个称为null的特殊文件,shell输出到null文件的任何数据都不会保存

代码5-17

[email protected]:/data# ls -al /home/
total 44
drwxr-xr-x  8 root root  4096 Aug 25 10:29 .
drwxr-xr-x 28 root root  4096 Nov 11 20:08 ..
drwxr-xr-x 58 root root  4096 Nov 28 16:52 backup
drwxr-xr-x  2 root root  4096 Aug 25 10:29 conf
drwx------  2 root root 16384 Aug 24 16:53 lost+found
drwxr-xr-x  4 root root  4096 Aug 25 10:29 mysql
drwxr-xr-x  8 root root  4096 Oct  8 13:09 software
drwxr-xr-x  2 root root  4096 Aug 25 10:41 tmp
[email protected]:/data# ls -al /home/ > /dev/null
[email protected]:/data# cat /dev/null
[email protected]:/data#

  

如果将/dev/null作为输入文件,将会清空现有文件数据,可用它来清除数据而不用删除文件

代码5-18

[email protected]:/data# cat text
Hello Spring
Hello Hibernate
[email protected]:/data# cat /dev/null > text
[email protected]:/data# cat text
[email protected]:/data#

  

创建本地临时文件,点可加可不加,末尾至少加3个X,且只能加X(必须大写)

代码5-19

[email protected]:/data# mktemp test.XXX
test.otX
[email protected]:/data# mktemp test.XXXXX
test.gYDV4
[email protected]:/data# ls -l
total 0
-rw------- 1 root root 0 Dec  5 05:29 test.gYDV4
-rw------- 1 root root 0 Dec  5 05:29 test.otX

  

脚本中使用mktemp

代码5-20

[email protected]:/data# cat demo6
#!/bin/bash
tempfile=`mktemp test.XXX`
exec 3>$tempfile
echo "Hello Java"
echo "Hello Spring">&3
echo "Hello Hibernate">&3
echo "Hello MyBatis">&3
echo "Hello Shiro">&3
echo "Hello Drools">&3
echo "Hello Activity">&3
exec 3>&-
echo "$tempfile content:"
cat $tempfile
rm -rf $tempfile
[email protected]:/data# ./demo6
Hello Java
test.heV content:
Hello Spring
Hello Hibernate
Hello MyBatis
Hello Shiro
Hello Drools
Hello Activity

  

mktemp命令使用-t参数返回全路径

代码5-21

[email protected]:/data# ls -l /tmp/test*
-rw------- 1 root root 0 Dec  5 05:43 /tmp/test.4WExx
-rw------- 1 root root 0 Sep 30 20:43 /tmp/testing.t90
-rw------- 1 root root 0 Sep 30 20:43 /tmp/testingW85
-rw------- 1 root root 0 Dec  5 05:43 /tmp/test.JxQ
[email protected]:/data# rm /tmp/test*
[email protected]:/data# mktemp -t test.XXX
/tmp/test.ZUV
[email protected]:/data# mktemp -t test.XXXXX
/tmp/test.JcyNo
[email protected]:/data# ls -l /tmp/test*
-rw------- 1 root root 0 Dec  5 05:44 /tmp/test.JcyNo
-rw------- 1 root root 0 Dec  5 05:44 /tmp/test.ZUV

  

使用-d创建临时目录,加上-t同时也可以返回创建临时目录的路径

代码5-22

[email protected]:/data# mktemp -d test.XXX
test.U31
[email protected]:/data# mktemp -d test.XXXXX
test.UZBuc
[email protected]:/data# ls -l
total 8
drwx------ 2 root root 4096 Dec  5 05:46 test.U31
drwx------ 2 root root 4096 Dec  5 05:46 test.UZBuc
[email protected]:/data# mktemp -dt test.XXXXX
/tmp/test.Wl6oP
[email protected]:/data# mktemp -dt test.XXXXXXXX
/tmp/test.biKCpQ7C
[email protected]:/data# ls -l /tmp/test*
-rw------- 1 root root    0 Dec  5 05:44 /tmp/test.JcyNo
-rw------- 1 root root    0 Dec  5 05:44 /tmp/test.ZUV

/tmp/test.biKCpQ7C:
total 0

/tmp/test.Wl6oP:
total 0

  

tee可以一边向显示器输出,一边重定向文件,但一般是覆盖原文件内容,可使用-a追加内容

代码5-23

[email protected]:/data# date | tee text
Mon Dec  5 06:18:04 CST 2016
[email protected]:/data# cat text
Mon Dec  5 06:18:04 CST 2016
[email protected]:/data# who | tee text
root     pts/0        2016-12-05 04:26 (122.90.143.21)
root[email protected]:/data# cat text
root     pts/0        2016-12-05 04:26 (122.90.143.21)
[email protected]:/data# date | tee -a text
Mon Dec  5 06:18:29 CST 2016
[email protected]:/data# cat text
root     pts/0        2016-12-05 04:26 (122.90.143.21)
Mon Dec  5 06:18:29 CST 2016

  

时间: 2024-10-14 18:35:35

Linux Shell脚本编写——呈现数据(五)的相关文章

Linux Shell脚本编写——构建基本脚本(一)

创建shell脚本 在创建shell脚本文件,必须在文件的第一行指定要使用的shell,其格式为: #!/bin/bash 创建.执行sh脚本 代码1-1 [email protected]:/data# cat demo1 #/bin/bash date who [email protected]:/data# ls -l total 4 -rw-r--r-- 1 root root 21 Dec 1 13:59 demo1 [email protected]:/data# chmod u+x

Linux Shell脚本编写——使用结构化命令(四)

命令行参数 向shell脚本传数据的最基本方法是使用命令行参数,命令行参数允许在运行脚本时向命令行添加数据值 读取参数 bash shell会将一些称为位置参数的特殊变量分配给命令行输入的所有参数,甚至包括shell执行的程序的名字,$0是程序名,$1是第一个参数,$2是第二个参数 代码4-1 [email protected]:/data# cat demo1 #!/bin/bash factorial=1 for ((i=1;i<=$1;i++)) do factorial=$[ $fact

Linux Shell脚本编写——使用结构化命令(二)

结构化命令中,最基本的类型就是if-then语句 if command then command fi bash shell的if语句会执行if行定义的那个命令,如果命令的退出状态码是0,则代表成功执行,位于then部分的命令就会执行.如果if行定义的命令的退出状态码是其他,则then部分的命令将不会执行,且if-then语句不能测试跟命令的退出状态码无关的条件 代码2-1 [email protected]:/data# cat demo1 #!/bin/bash if date then e

linux shell脚本编写

大家好 这是一篇自己阅读.学习的shell编程,工作中大量应用,尤为awk.sed.grep为主.希望对大家速成有用 可以直接翻看到中部位置 [data] export PATH=/mall/jdk/jdk1.7/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin export LANG=zh_CN.GB18030 start=`date +%s -d "2011-11-28 15:55:37&qu

Linux Shell脚本编写——使用结构化命令(三)

for命令 for var in listdo commandsdone 代码2-1 [email protected]:/data# cat demo1 #!/bin/bash for test in Alabama Alaska Arizona Arkansas "California Colorado" do echo "The next state is $test" done echo "The last state we visited was

linux shell脚本编程笔记(五): 重定向

I/O重定向 简述: 默认情况下始终有3个"文件"处于打开状态, stdin (键盘), stdout (屏幕), and stderr (错误消息输出到屏幕上). 这3个文件和其他打开的文件都可以被重定向. 对于重定向简单的解释就是捕捉一个文件, 命令, 程序, 脚本, 或者甚至是脚本中的代码块的输出, 然后将这些输出作为输入发送到另一个文件, 命令, 程序, 或脚本中. 每个打开的文件都会被分配一个文件描述符.stdin, stdout, 和stderr的文件描述符分别是0, 1,

Linux shell脚本基础学习详细介绍(完整版)二

详细介绍Linux shell脚本基础学习(五) Linux shell脚本基础前面我们在介绍Linux shell脚本的控制流程时,还有一部分内容没讲就是有关here document的内容这里继续. Linux shell脚本基础已经被分成好几个部分了,这里对控制流程的内容也就马上讲完了,这是最后一部分关于here document,这里举例稍微有点复杂,我们慢慢来分析这个复杂Linux shell脚本. 6. Here documents 当要将几行文字传递给一个命令时,here docu

编写可靠Linux shell脚本的八个建议

这八个建议,来源于键者几年来编写 shell 脚本的一些经验和教训.事实上开始写的时候还不止这几条,后来思索再三,去掉几条无关痛痒的,最后剩下八条.毫不夸张地说,每条都是精挑细选的,虽然有几点算是老生常谈了. 1. 指定bash shell 脚本的第一行,#!之后应该是什么? 如果拿这个问题去问别人,不同的人的回答可能各不相同.我见过www.1.qixoo.com/usr/bin/env bash,也见过/bin/bash,还有/usr/bin/bash,还有/bin/sh,还有/usr/bin

LINUX SHELL脚本攻略笔记[速查]

Linux Shell脚本攻略笔记[速查] 资源 shell script run shell script echo printf 环境变量和变量 pgrep shell数学运算 命令状态 文件描述符和重定向 cat 数组和关联数组 alias date 调试脚本 函数和参数 管道 读取命令输出 read 字段分隔符和迭代器 循环 比较和测试 find xargs tr md5sum sha1sum 对目录进行校验 sort uniq tempfile split bash变量匹配切分 exp