shell编程

shell编程,第1张

接上一篇文章shell编程(八) : [shell基础] 处理用户输入

目录 3.4 呈现数据3.4.1 关于输入和输出3.4.2 重定向标准错误1.只重定向标准错误2.同时重定向标准错误和标准输出 3.4.3 在脚本中使用重定向1. 临时重定向2. 永久重定向 3.4.4 创建自己的重定向3.4.5 列出打开的文件描述符3.4.5 阻止命令输出3.4.6 创建临时文件/目录3.4.7 记录消息(日志)

3.4 呈现数据

有时我们需要将脚本的输出重定向到屏幕或文件来展示相关的信息,接下来介绍怎么实现这一功能。

3.4.1 关于输入和输出

在Linux中有一个理念“一切皆文件”,包括进程的输入输出,进程的输入输出 *** 作文件就是文件描述符,如下:

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

这三个特殊文件描述符会处理脚本的输入和输出。shell用它们将shell默认的输入和输出导向到相应的位置。

3.4.2 重定向标准错误

前面介绍过重定向输出和重定向输入,对于标准错误,可以用同样的方法。由于错误也属于输出,所以重定向错误也使用 >符号。以前我们用 >符号其实包含了缺省值,即 1> ,代表重定向标准输出,如果要指定重定向标准错误,就要使用 2>

标准输出和标准错误可以单独重定向也可以同时重定向。

1.只重定向标准错误

重定向标准错误前,输出错误和命令行的打印内容,重定向标准错误后,只有命令行的打印内容,错误被重定向写入了 test 文件。

2.同时重定向标准错误和标准输出

将标准输出重定向到了文件 test1,将标准错误重定向到了文件 test2,可以用这种方法将脚本的正常输出和脚本生成的错误消息分离开来,以便于有针对性的存储。

也可以将标准错误和标准输出重定向到同一个文件,但不是使用 1> test 2> test ,bash shell提供了另一个重定向符号 &>

3.4.3 在脚本中使用重定向

可以在脚本中用 STDOUTSTDERR 文件描述符以在多个位置生成输出,只要简单地重定向相应的文件描述符就行了。重定向输出同理。

有两种方法来在脚本中重定向输出:

临时重定向行输出永久重定向脚本中的所有命令 1. 临时重定向

但我们的脚本想要利用 Linux 的文件描述符输出错误信息时,可以将我们要输出的内容重定向到 STDERR文件描述符,如下:

看起来和普通输出一样,这是因为这就是普通输出,哈哈,因为默认情况下,Linux 会将 STDERR 导向 STDOUT 中,所以,这里的输出其实就是标准输出。

怎样才能看出他们的区别呢?我们将 STDERR 重定向,

可以看到,执行脚本时只输出了 STDOUT 的内容,STDERR 则被重定向到 stderr.log 中。

2. 永久重定向

如果脚本中有大量数据需要重定向,重定向每个 echo 语句就会很烦琐。可以用 exec 命令告诉shell在脚本执行期间重定向某个特定文件描述符。

其中,exec 2>testerrorSTDERR 重定向到 testerror 文件。exec 1>testoutSTDOUT 重定向到 testout 文件。

3.4.4 创建自己的重定向

除了 0、1、2 三个文件描述符,还有另外6个文件描述符 3-8,可以自定义这些文件描述符,如下:

#!/bin/bash

# 自定义文件描述符,并重定向
exec 3>test3out

# 使用文件描述符
echo "This should be stored in the file." >&3

利用自己创建的文件描述符恢复 STDOUTSTDERR 的重定向:

#!/bin/bash

# 利用自建文件描述符备份STDOUT文件描述符
exec 3>&1
exec 1>test14out
echo "This should store in the output file."
exec 1>&3
echo "Now things should be back to normal."

对于文件读写,也可以使用自建文件描述符,不过要注意文件内部指针的位置:

执行脚本后 testfile 的内容丢失了一部分,这是因为读取第一行后,文件内部指针位于第二行行首,紧接着就写入了内容,把原有的内容覆盖了。

关闭文件描述符,结束对文件的 *** 作后,要将文件描述符重定向到特殊符号 &- 即关闭文件描述符。

关闭文件后,再使用文件描述符 *** 作文件就会报错。

3.4.5 列出打开的文件描述符

有时打开的文件描述符过多,需要列出它们,linux提供了 lsof 命令实现这一功能。

lsof 命令会列出整个Linux系统打开的所有文件描述符。因为它会向非系统管理员用户提供Linux系统的信息,所以许多Linux系统隐藏了该命令,没有加到全局环境中。如果想使用它,需要使用绝对路径,一般它位于 /usr/sbin/lsof

由于lsof会显示当前Linux系统上打开的每个文件的有关信息,打印信息较多,需要过滤,所以 lsof 有许多参数选项,常用的有 :

参数选项描述
-p PID指定进程ID(PID)
-d 文件描述符指定要显示的文件描述符编号
-a对其他选项的结果执行布尔AND运算

其中,$$是特殊的环境变量,存储当前进程的ID(PID)。

lsof 的各输出字段意义:

列字段描述
COMMAND正在运行的命令名的前9个字符
PID进程的PID
USER进程属主的登录名
FD文件描述符号以及访问类型(r代表读,w代表写,u代表读写)
TYPE文件的类型(CHR代表字符型,BLK代表块型,DIR代表目录,REG代表常规文件)
DEVICE设备的设备号(主设备号和从设备号)
SIZE/OFF以字节为单位的文件大小或文件偏移量。
以“0t”或“0x”开头的数据代表偏移量。
NODE本地文件的节点号
NAME文件名

在脚本中使用 lsof

3.4.5 阻止命令输出

有时不需要命令行输出内容,比如需要脚本在后台运行时。

这时可以将命令的输出重定向到 null 文件,它是一个特殊文件,里面什么也没有,即使写入了数据也会被系统丢掉。在Linux系统中,null 文件的标准路径是 /dev/null

同样,可以将数据重定向到null,也可以将null的内容重定向到文件,即清空文件。

3.4.6 创建临时文件/目录

有时我们需要创建临时文件存放不需要永久保留的数据,linux为我们提供了mktemp命令和存放临时文件的目录/tmp

系统上的任何用户账户都有权限在读写/tmp目录中的文件。

使用 mktemp 命令创建本地临时文件:

# 首先创建模板,文件名自定义,扩展名为6个大写的X
# 系统会使用数字和大小写字母在6个X的位置随机填充,且会保证文件名的唯一性
mktemp testtemp.XXXXXX

mktemp 命令的输出是创建的文件的名字。在脚本中使用mktemp命令时,可以将文件名保存到变量中,然后在后面做处理。

在系统的 tmp 目录创建临时文件也可以使用 mktemp 命令,只不过要使用-t选项:

mktemp -t testtemp.XXXXXX

这时命令返回的是临时文件的绝对路径。

使用 mktemp-d 选项可以创建临时目录,目录名同样符合上面的规则:

mktemp -d testtemp.XXXXXX

大概你已经想到,同时使用 -t-d 选项可以在 /tmp 目录下创建临时目录。

3.4.7 记录消息(日志)

如果希望消息即在屏幕显示,也要写入文件中,使用上面的重定向方法需要重定向两次,为了不必要的麻烦,linux提供了 tee 命令。

它可以将 STDIN 的数据同时发送到 STDOUT 和 指定文件中,命令格式如下:

tee filename

hello 即在屏幕显示了,也写入了 tee.log 文件。

注意,tee 命令默认情况下每次写入是覆盖模式,如果想使用追加模式,需要加 -a 选项,如下:

文件的初始内容为 hello ,第一次写入hihello 覆盖了,第二次使用 -a 选项,写入 hello ,是追加在 hi 的后面。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/926303.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存