shell Script 打印输出

Linux系统将每个对象当作文件处理。这包括输入和输出进程。Linux用文件描述符来标识每个文件对象。文件描述符是一个非负整数,可以唯一标识会话中打开的文件。

每个进程一次最多可以有九个文件描述符 。bash shell保留了前三个文件描述符(0、1和2),shell用它们将shell默认的输入和输出导向到相应的位置

标准文件描述符
0 STDIN 标准输入 对终端界面来说,标准输入是键盘
1 STDOUT

标准输出

在终端界面上,标准输出就是终端显示器
2 STDERR 标准错误 shell或shell中运行的程序和脚本出错时生成的错误消息都会发送到这个位置

重定向错误

可以选择只重定向错误消息,将该文件描述符值放在重定向符号前

$ ls -al badfile 2> test4
$ cat test4
ls: cannot access badfile: No such file or directory
$

想重定向错误和正常输出,必须用两个重定向符号。需要在符号前面放上待重定向数据所对应的文件描述符,然后指向用于保存数据的输出文件。

$ ls -al test test2 test3 badtest 2> test6 1> test7
$ cat test6
ls: cannot access test: No such file or directory
ls: cannot access badtest: No such file or directory
$ cat test7
-rw-rw-r-- 1 rich rich 158 2014-10-16 11:32 test2
-rw-rw-r-- 1 rich rich 0 2014-10-16 11:33 test3
$

在脚本中重定向输出

  • 临时重定向

在脚本中生成错误消息,可以将单独的一行输出重定向到STDERR。在重定向到文件描述符时,你必须在文件描述符数字之前加一个&,默认情况下,Linux会将STDERR导向STDOUT。但是,如果你在运行脚本时重定向了STDERR,脚本中所有导向STDERR的文本都会被重定向

$ cat test8
#!/bin/bash
echo "This is an error" >&2
echo "This is normal output"
$ ./test8 2> test9
This is normal output
$ cat test9
This is an error
$
  • 永久重定向

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

$ cat test11
#!/bin/bash
exec 2>testerror
echo "This is the start of the script"
echo "now redirecting all output to another location"
exec 1>testout
echo "This output should go to the testout file"
echo "but this should go to the testerror file" >&2
$
$ ./test11
This is the start of the script
now redirecting all output to another location
$ cat testout
This output should go to the testout file
$ cat testerror
but this should go to the testerror file
$

在脚本中重定向输入

exec命令允许你将STDIN重定向到Linux系统上的文件中。这个命令会告诉shell它应该从文件testfile中获得输入,而不是STDIN。

$ cat test12
#!/bin/bash
exec 0< testfile
count=1
while read line
do
    echo "Line #$count: $line"
    count=$[ $count + 1 ]
done
$ ./test12
Line #1: This is the first line.
Line #2: This is the second line.
Line #3: This is the third line.
$

创建自己的重定向

在shell中最多可以有9个打开的文件描述符。其他6个从3~8的文件描述符均可用作输入或输出重定向。你可以将这些文件描述符中的任意一个分配给文件,然后在脚本中使用它们。

exec 3>test13out        #文件描述符3重定向到另一个文件
echo "This should display on the monitor"
echo "and this should be stored in the file" >&3
$ ./test13
This should display on the monitor
$ cat test13out
and this should be stored in the file
$
exec 3>&1  #脚本将文件描述符3重定向到文件描述符1的当前位置,这意味着任何发送给文件描述符3的输出都将出现在显示器上
exec 1>test14out    #将STDOUT重定向到文件
echo "This should store in the output file"
echo "along with this line."
exec 1>&3    #将STDOUT重定向到文件描述符3的当前位置(现在仍然是显示器)。这意味着现在STDOUT又指向了它原来的位置:显示器。
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.
$
exec 6<&0        #文件描述符6用来保存STDIN的位置
exec 0< testfile    #将STDIN重定向到一个文件,read命令的所有输入都来自重定向后的STDIN(也就是输入文件)
count=1
while read line
do
    echo "Line #$count: $line"
    count=$[ $count + 1 ]
done
exec 0<&6    #将STDIN重定向到文件描述符6,从而将STDIN恢复到原先的位置。该脚本用了另外一个read命令来测试STDIN是否恢复正常了。这次它会等待键盘的输入。
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
$
  • 关闭文件描述符

要关闭文件描述符,将它重定向到特殊符号&-

#!/bin/bash
exec 3> test17file
echo "This is a test line of data" >&3
exec 3>&-
echo "This won't work" >&3
$ ./badtest
./badtest: 3: Bad file descriptor
$

阻止命令输出

有时候,你可能不想显示脚本的输出。要解决这个问题,可以将STDERR重定向到一个叫作null文件的特殊文件。null文件跟它的名字很像,文件里什么都没有。shell输出到null文件的任何数据都不会保存,全部都被丢掉了。

在Linux系统上null文件的标准位置是/dev/null。你重定向到该位置的任何数据都会被丢掉,不会显示。

$ ls -al > /dev/null
$ cat /dev/null
$

用它来快速清除现有文件中的数据,而不用先删除文件再重新创建

$ cat /dev/null > testfile
$ cat testfile
$

 

创建临时文件

mktemp命令可以在/tmp目录中创建一个唯一的临时文件

$ mktemp testing.XXXXXX
$ ls -al testing*
-rw------- 1 rich rich 0 Oct 17 21:30 testing.UfIi13
$

在脚本中使用mktemp命令时,可能要将文件名保存到变量中,这样就能在后面的脚本中引用了。

$ cat test19
#!/bin/bash
tempfile=$(mktemp test19.XXXXXX)
exec 3>$tempfile
echo "This script writes to temp file $tempfile"
echo "This is the first line" >&3
echo "This is the second line." >&3
echo "This is the last line." >&3
exec 3>&-
echo "Done creating temp file. The contents are:"
cat $tempfile
rm -f $tempfile 2> /dev/null
$ ./test19
This script writes to temp file test19.vCHoya
Done creating temp file. The contents are:
This is the first line
This is the second line.
This is the last line.
$ ls -al test19*
-rwxr--r-- 1 rich rich 356 Oct 29 22:03 test19*
$

记录消息

将输出同时发送到显示器和日志文件,你不用将输出重定向两次。tee命令相当于管道的一个T型接头。它将从STDIN过来的数据同时发往两处。一处是STDOUT,另一处是tee命令行所指定的文件名:

$ date | tee testfile
Sun Oct 19 18:56:21 EDT 2014
$ cat testfile
Sun Oct 19 18:56:21 EDT 2014
$

默认情况下,tee命令会在每次使用时覆盖输出文件内容。如果你想将数据追加到文件中,必须用-a选项。

猜你喜欢

转载自blog.csdn.net/linshuo1994/article/details/84189549