接上一篇文章shell编程(八) : [shell基础] 处理用户输入
有时我们需要将脚本的输出重定向到屏幕或文件来展示相关的信息,接下来介绍怎么实现这一功能。
3.4.1 关于输入和输出在Linux中有一个理念“一切皆文件”,包括进程的输入输出,进程的输入输出 *** 作文件就是文件描述符
,如下:
文件描述符 | 缩写 | 描述 |
---|---|---|
0 | STDIN | 标准输入 |
1 | STDOUT | 标准输出 |
2 | STDERR | 标准错误 |
这三个特殊文件描述符会处理脚本的输入和输出。shell用它们将shell默认的输入和输出导向到相应的位置。
3.4.2 重定向标准错误前面介绍过重定向输出和重定向输入,对于标准错误,可以用同样的方法。由于错误也属于输出,所以重定向错误也使用 >
符号。以前我们用 >
符号其实包含了缺省值,即 1>
,代表重定向标准输出,如果要指定重定向标准错误,就要使用 2>
。
标准输出和标准错误可以单独重定向也可以同时重定向。
1.只重定向标准错误重定向标准错误前,输出错误和命令行的打印内容,重定向标准错误后,只有命令行的打印内容,错误被重定向写入了 test 文件。
2.同时重定向标准错误和标准输出将标准输出重定向到了文件 test1,将标准错误重定向到了文件 test2,可以用这种方法将脚本的正常输出和脚本生成的错误消息分离开来,以便于有针对性的存储。
也可以将标准错误和标准输出重定向到同一个文件,但不是使用 1> test 2> test
,bash shell提供了另一个重定向符号 &>
可以在脚本中用 STDOUT
和 STDERR
文件描述符以在多个位置生成输出,只要简单地重定向相应的文件描述符就行了。重定向输出同理。
有两种方法来在脚本中重定向输出:
临时重定向行输出永久重定向脚本中的所有命令 1. 临时重定向但我们的脚本想要利用 Linux 的文件描述符输出错误信息时,可以将我们要输出的内容重定向到 STDERR
文件描述符,如下:
看起来和普通输出一样,这是因为这就是普通输出,哈哈,因为默认情况下,Linux 会将 STDERR
导向 STDOUT
中,所以,这里的输出其实就是标准输出。
怎样才能看出他们的区别呢?我们将 STDERR
重定向,
可以看到,执行脚本时只输出了 STDOUT
的内容,STDERR
则被重定向到 stderr.log
中。
如果脚本中有大量数据需要重定向,重定向每个 echo 语句就会很烦琐。可以用 exec
命令告诉shell在脚本执行期间重定向某个特定文件描述符。
其中,exec 2>testerror
将 STDERR
重定向到 testerror
文件。exec 1>testout
将 STDOUT
重定向到 testout
文件。
除了 0、1、2
三个文件描述符,还有另外6个文件描述符 3-8
,可以自定义这些文件描述符,如下:
#!/bin/bash
# 自定义文件描述符,并重定向
exec 3>test3out
# 使用文件描述符
echo "This should be stored in the file." >&3
利用自己创建的文件描述符恢复 STDOUT
、STDERR
的重定向:
#!/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
有时不需要命令行输出内容,比如需要脚本在后台运行时。
这时可以将命令的输出重定向到 null
文件,它是一个特殊文件,里面什么也没有,即使写入了数据也会被系统丢掉。在Linux系统中,null
文件的标准路径是 /dev/null
。
同样,可以将数据重定向到null
,也可以将null
的内容重定向到文件,即清空文件。
有时我们需要创建临时文件存放不需要永久保留的数据,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
目录下创建临时目录。
如果希望消息即在屏幕显示,也要写入文件中,使用上面的重定向方法需要重定向两次,为了不必要的麻烦,linux提供了 tee
命令。
它可以将 STDIN
的数据同时发送到 STDOUT
和 指定文件中,命令格式如下:
tee filename
hello
即在屏幕显示了,也写入了 tee.log
文件。
注意,tee
命令默认情况下每次写入是覆盖模式,如果想使用追加模式,需要加 -a
选项,如下:
文件的初始内容为 hello
,第一次写入hi
将 hello
覆盖了,第二次使用 -a
选项,写入 hello
,是追加在 hi
的后面。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)