【读书笔记】Linux命令行与Shell脚本编程大全--呈现数据

1.理解输入和输出

在Linux系统上,有如下两种方式显示脚本输出的方法:

  1. 在显示器屏幕上显示输出
  2. 将输出重定向到文件

这两种输出方法有个共同的特点:若显示则都显示,若不显示则一点都不显示。
如何做到显示只想显示的一部分到屏幕或者文件呢?
可参考标准文件描述符重定向错误两小节。

1.1 标准文件描述符

Linux用文件描述符(file descriptor)来标识每个文件对象
文件描述符是一个非负整数,可以标识会话中打开的文件。
每个进程一次最多可以有九个文件描述符。

ps: bash shell 保留了前三个描述符(0,1,2)。如下表所示:
在这里插入图片描述

1.2 重定向错误(STDERR)

Q:如何重定向错误?
A:重定向错误只要在使用使用重定向符号时定义STDERR文件描述符就可以了。

实现方法如下:

方法 例程 实现和注意
只重定向错误 ls -la a 2> error.log 将文件描述符放在重定向符号之前,注意,必须紧紧挨着
重定向错误和数据 ls -la a b 2> error.log 1> info.log 同时重定向错误和数据,必须使用两个重定向符号。
也要注意文件描述符和重定向符要紧紧挨着

ps:也可以将STDERR和STDOUT的输出重定向到同一个文件,那就要使用特殊的重定向符号&>
eg:ls -la a b &> all.log
注意:bash shell 在&>这个重定向符上自动赋予了错误消息更高的级别,因此错误消息会在文件前列。

2.在脚本中重定向输出–临时or永久

2.1 临时重定向

脚本中临时重定向和在命令行中略有不同。
后者是文件描述符紧紧跟着重定向符,而前者必须是重定向符号紧紧跟着文件描述符,同时,中间必须紧紧穿插一个&。其格式如下:

echo "error" >&2

ps:若在运行脚本时重定向了STDERR,脚本中所有导向STDERR的文本都会被重定向。

2.2 永久重定向–exec命令

exec命令会启动一个新shell并将指定的文件描述符重定向到文件
脚本中将发送给这个文件描述符的所有输出都会被重定向到文件。
如:

exec 2>error.log

echo "error"

3.在脚本中重定向输入–在脚本中从待处理文件中读取数据的绝妙办法

exec命令也允许将STDIN重定向到Linux文件中。
其格式如下:

exec 0< testfile  #重定向shell应该从testfile中获取数据,而不是STDIN。

4.创建自己的重定向–3到8的文件描述符

4.1 创建输出文件描述符

可以用exec命令来给输出分配文件描述符。
和标准的文件描述符一样,一旦将另一个文件描述符分配给一个文件,这个重定向就会一直有效,直到你重新分配

ps:可以使用exec命令来将输出追加到现有文件中。eg:exec 3>>test13out

4.2 重定向文件描述符

重定向文件描述符的关键是对文件描述符的重定向。
可参考如下加深理解:
eg:

$ cat test14 
#!/bin/bash 
# storing STDOUT, then coming back to it 
exec 3>&1 										# 将自定义的文件描述符3重定向到STDOUT,即文件描述符1
exec 1>test14out 								# 将文件描述符1的输出重定向到test14out文件中
echo "This should store in the output file" 
echo "along with this line."
exec 1>&3 										# 恢复:将STDOUT重定向到自定义的文件描述符3中
echo "Now things should be back to normal" 
$ 
$ ./test14 
Now things should be back to normal 
$ cat test14out 
This should store in the output file 
along with this line. 
$

4.3 创建输入文件描述符

在重定向到文件之前,先将STDIN文件描述符保存到另外一个文件描述符,然后在读取完文件之后再将STDIN恢复到它原来的位置(此做法和重定向输出文件描述符是同样的办法)。
eg:

$ cat test15 
#!/bin/bash 
# redirecting input file descriptors 
exec 6<&0 								#告诉自定义文件描述符6 以STDIN 0 作为输入
exec 0< testfile 						#告诉STDIN 0 以文件testfile作为输入,而不再是键盘,这样最终6也会得到文件里的内容
count=1 
while read line 
do 
 echo "Line #$count: $line" 
 count=$[ $count + 1 ] 
done 
exec 0<&6 								#恢复:告诉STDIN 0 以文件描述符6作为输入,因为之前6是以STDIN 0作为输入的,现在也就恢复了
read -p "Are you done now? " answer 
case $answer in 
Y|y) echo "Goodbye";; 
N|n) echo "Sorry, this is the end.";; 
esac 
$ ./test15
Line #1: This is the first line. 
Line #2: This is the second line. 
Line #3: This is the third line. 
Are you done now? y 
Goodbye 
$

4.4 创建读写文件描述符–<>

创建读写文件描述符即是同时使用重定向输入和输出符号(<>)。
eg:exec 3<> testfile. 该例表明给自定义文件描述符3创建读写。

ps:当打开单个文件描述符来作为输入和输出的时候需要注意。
由于是对同一个文件进行数据读写,shell会维护一个内部指针,指明在文件中的当前位置。任何读或写都会从文件指针上次的位置开始。 因此,对同一个文件进行数据读写,可能会对文件数据造成丢失。

eg:

$ cat test16 
#!/bin/bash 
# testing input/output file descriptor 
exec 3<> testfile 						#对自定义文件描述符3创建读写
read line <&3 							#读取第一行		读
echo "Read: $line" 						#显示第一行
echo "This is a test line" >&3 			#将指定内容输出到自定义文件描述符3	写
$ cat testfile 							#直接查看文件内容
This is the first line. 
This is the second line. 
This is the third line. 
$ ./test16 								#执行脚本
Read: This is the first line. 
$ cat testfile 							#执行脚本后在查看文件内容,丢失了second行
This is the first line. 
This is a test line 
ine. 
This is the third line. 
$

4.5 关闭文件描述符–重定向到特殊符号&-

通常,shell会在脚本退出时自动关闭新的文件描述符

Q:如何提前关闭文件描述符?
A:要关闭文件描述符,将它重定向到特殊符号&-。其脚本格式如:exec 3>&-

ps:

  1. 一旦关闭了文件描述符,就不能在脚本中向它写入任何数据,否则shell会生成错误消息。
  2. 如果随后你在脚本中打开了同一个输出文件,shell会用一个新文件来替换已有文件。这意味着如果你输出数据,它就会覆盖已有文件。

5.列出打开的文件描述符–lsof

lsof命令会列出整个Linux系统打开的所有文件描述符。
lsof常用命令行选项和参数有-p(允许指定进程的ID,即PID)和-d(允许指定要显示的文件描述编号

ps:特殊环境变量$$能知道进程的当前PID。

eg:非书中图
在这里插入图片描述
lsof的默认输出解释如下:

描述
COMMAND 正在运行的命令的前9个字符
PID 进程的PID
USER 进程属主的登录名
FD 文件描述符号以及访问类型(u表示读写,r表示读,w表示写)
TYPE 文件的类型(CHR代表字符型,BLK代表块型,DIR代表目录,REG代表常规文件)
DEVICE 设备的设备号(主设备号和次设备号)
SIZE/OFF 如果有的话,表示文件大小
NODE 本地文件的节点号
NAME 文件名

6.阻止命令输出–重定向输出到/dev/null

在Linux系统上,null文件的标准位置是/dev/null。若重定向到该位置,则不管什么数据都将被丢弃,不会显示。(可以理解成windows的回收站,但并不一样)

Q:如何快速清除一个文件的内容?
A:可借助重定向输入,即将在输入重定向中将/dev/null作为输入文件。由于/dev/null不包含任何内容,则可以快速清除一个文件的内容。

ps:在输入重定向中将/dev/null作为输入文件,是清除日志文件的一个常用方法,因为日志文件不需要删除,只需要清除以前的内容即可。

7.创建临时文件–mktemp

Linux系统中,使用/tmp目录来存放不需要永久保留的文件。这是因为大多数Linux发行版配置了系统在启动时自动删除/tmp目录下的文件。

ps:系统上的任何账户都对/tmp目录有读写权限。
在这里插入图片描述

7.1 创建本地临时文件

默认情况下,mktemp命令会在本地目录中创建一个文件。

Q:如何在本地目录中创建一个临时文件?
A:指定一个文件名模板即可。模板可以包含任意文本文件名,但需要在末尾加上6个X
如下所示:

mktemp test.XXXXXX

mktemp会用6个随机的字符码替换掉这6个X。从而保证文件名在目录中是唯一的。

7.2 在/tmp目录创建临时文件–mktemp -t

-t选项会强制mktemp命令来在系统的临时目录(/tmp)来创建该文件。mktemp命令会返回用来创建临时文件的全路径,而不是只有文件名。

7.3 创建临时目录–mktemp -d

-d选项告诉mktemp命令来创建一个临时目录而不是临时文件。

ps:mktemp -d 创建的临时目录在本地而非在/tmp目录下。

8.记录消息–tee

tee命令相当于管道的一个T型接头。它将从STDIN过来的数据同时发往STDOUT和tee命令行所指定的文件名
其格式如下:

tee testfile

ps:默认情况下,tee命令会在每次使用时覆盖输出文件内容。可使用-a选项将数据追加到文件

申明:文中没特殊注明,图皆来自Linux命令行与shell脚本编程大全<第三版>。

发布了91 篇原创文章 · 获赞 17 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_23327993/article/details/104652388
今日推荐