> 文章列表 > shell脚本基础之详解脚本数据的输入与输出

shell脚本基础之详解脚本数据的输入与输出

shell脚本基础之详解脚本数据的输入与输出

数据的展示

    • 理解输入与输出
      • 标准文件描述符
        • STDIN(标准输入)
        • STDOUT(标准输出)
        • STDERR(标准错误)
    • 重定向错误
      • 只重定向错误
      • 重定向错误和数据
    • 在shell脚本中重定向输出
      • 临时重定向
      • 永久重定向
    • 在shell脚本中重定向输入
    • 创建自己的重定向
      • 创建输出文件描述符
      • 重定向文件描述符
      • 创建输入文件描述符
      • 创建读写文件描述符
      • 关闭文件描述符
    • 列出打开的文件描述符
    • 阻止命令输出
    • 创建临时文件
      • 创建本地临时文件
      • 在/tmp 目录创建临时文件
      • 创建临时目录
    • 记录消息
  • 截至到现在,我们所写的shell脚本都是通过将数据打印在屏幕上或将数据重定向到文件中来显示信息的,下面我们会学习如何将脚本的输出重定向到Linux系统的其它位置,并深入了解重定向

理解输入与输出

  • 目前我们已经学习到两种显示脚本输出的方法:
    • 在显示器屏幕上显示输出
    • 将输出重定向到文件,查看文件
  • 上述两种方法,要么是将数据全部显示到屏幕上,要么是什么都不显示。如果可以将一部分数据展示到显示器上,一部分保存到文件中,这个方法看起来是个更优解,对此我们需要了解Linux如何处理输入输出,才能够帮助我们将脚本输出放到正确位置

标准文件描述符

  • Linux系统将每个对象当作文件处理。这包括输入和输出进程。Linux用文件描述符(file descriptor)来标识每个文件对象。文件描述符是一个非负整数,可以唯一标识会话中打开的文件。每个进程一次最多可以有九个文件描述符。出于特殊目的,bash shell保留了前三个文件描述符(0、1、2),如下表:
文件描述符 英文缩写 描述
0 STDIN 标准输入
1 STDOUT 标准输出
2 STDERR 标准错误
  • 这三个特殊文件描述符会处理脚本的输入和输出。shell用它们将shell默认的输入和输出导向到相应的位置,如下介绍:

STDIN(标准输入)

  • STDIN文件描述符代表shell的标准输入。对终端界面来说,标准输入是键盘。shell从STDIN文件描述符对应的键盘获得输入,在用户输入时处理每个字符
  • 在使用输入重定向符号(<)时,Linux会用重定向指定的文件来替换标准输入文件描述符,它会读取文件并提取数据,就好像是从键盘上键入的
  • 许多bash命令能接受STDIN的输入,尤其是没有在命令行上指定文件的话。如下是使用cat命令处理STDIN输入的数据的例子:
    shell脚本基础之详解脚本数据的输入与输出
  • 当在命令行上只输入cat命令时,它会从STDIN接受输入(键盘)。键盘输入一行,cat命令就会显示出一行,但我们也可以通过STDIN重定向符号强制cat命令接受来自另一个STDIN文件的输入,如下:
    shell脚本基础之详解脚本数据的输入与输出
  • 如上cat命令会用cat_txt文件中的行作为输入。我们还可以使用这种技术将数据输入到任何能从STDIN接受数据的shell命令中

STDOUT(标准输出)

  • STDOUT文件描述符代表shell的标准输出。在终端界面上,标准输出就是终端显示器。shell的所有输出(包括shell中运行的程序和脚本)会被定向到标准输出中,也就是显示器

  • 默认情况下,大多数bash命令会将输出导向STDOUT文件描述符,如下,我们可以用输出重定向来改变标准输出:
    shell脚本基础之详解脚本数据的输入与输出

  • 通过输出重定向符号,通常会显示到显示器的所有输出会被shell重定向到指定的重定向文件。我们也可以将数据追加到某个文件。这可以用>>符号来完成,如下:
    shell脚本基础之详解脚本数据的输入与输出

  • who命令生成的输出会被追加到ls_txt文件中已有数据的后面,但是如果你对脚本使用了标准输出重定向,你还可能遇到一个特殊的问题,如下:
    shell脚本基础之详解脚本数据的输入与输出

  • 当命令生成错误消息时,shell并未将错误消息重定向到输出重定向文件。shell创建了输出重定向文件,但错误消息却显示在了显示器屏幕上。注意,在显示new_ls文件的内容时并没有任何错误。new_ls文件创建成功了,只是没有内容而已

  • shell对于错误消息的处理是跟普通输出分开的。如果我们创建了在后台模式下运行的shell脚本,通常必须依赖发送到日志文件的输出消息。用这种方法的话,如果出现了错误信息,这些错误信息也是不会出现在日志文件中的,需要换种方法来处理

STDERR(标准错误)

  • shell通过特殊的STDERR文件描述符来处理错误消息。STDERR文件描述符代表shell的标准错误输出。shell或shell中运行的程序和脚本出错时生成的错误消息都会发送到这个位置
  • 默认情况下,STDERR文件描述符会和STDOUT文件描述符指向同样的地方(尽管分配给它们的文件描述符值不同)。也就是说,默认情况下,错误消息也会输出到显示器输出中
  • 但是从上面的例子可以看出,STDERR并不会随着STDOUT的重定向而发生改变。使用脚本时,我们常常会想改变这种行为,尤其是当希望将错误消息保存到日志文件中的时候,如下介绍

重定向错误

  • 我们已经学习了如何用重定向符号来重定向STDOUT数据。重定向STDERR数据也没太大差别,只要在使用重定向符号时定义STDERR文件描述符即可。有如下几种办法实现

只重定向错误

  • STDERR文件描述符被设成2。选择只重定向错误消息时,只需要将该文件描述符值放在重定向符号前。该值必须紧紧地放在重定向符号前,否则不会工作,如下:
ls -l badTXT 2> err.txt

shell脚本基础之详解脚本数据的输入与输出

  • 如上,错误消息不会出现在屏幕上了。只需要注意:文件描述符值紧贴在重定向符号前,二者之间没有空白符,该命令生成的任何错误消息都会保存在输出文件中。用这种方法,shell会只重定向错误消息,而非普通数据。这里是另一个将STDOUT和STDERR消息混杂在同一输出中的例子,如下:
    shell脚本基础之详解脚本数据的输入与输出
  • ls命令的正常STDOUT输出仍然会发送到默认的STDOUT文件描述符,也就是显示器。由于该命令将文件描述符2的输出(STDERR)重定向到了一个输出文件,shell会将生成的所有错误消息直接发送到指定的重定向文件中

重定向错误和数据

  • 如果想重定向错误和正常输出,必须用两个重定向符号。需要在符号前面放上待重定向数据所对应的文件描述符,然后指向用于保存数据的输出文件,如下:
ls -l err.txt new_ls badTXT 2> err01.txt 1> succ01.txt

shell脚本基础之详解脚本数据的输入与输出

  • shell利用1>符号将ls命令的正常输出重定向到了succ01.txt文件,而这些输出本该是进入STDOUT的。所有本该输出到STDERR的错误消息通过2>符号被重定向到了err01.txt文件
  • 使用这种方法可以将脚本的正常输出和脚本生成的错误消息分离开来。这样就可以轻松方便地查看错误信息
  • 也可以将STDERR和STDOUT的输出重定向到同一个输出文件。为此bash shell提供了特殊的重定向符号&>,如下:
ls -l err.txt new_ls badTXT &> normal.txt

shell脚本基础之详解脚本数据的输入与输出

  • 使用&>符时,命令生成的所有输出都会发送到同一文件,包括数据输出和错误。我们注意到其中错误消息出现的位置和预想中的不一样。badTXT文件(列出的最后一个文件)的这条错误消息出现在输出文件中的第一行。这是为了避免错误信息散落在输出文件中,相较于标准输出,bash shell自动赋予了错误消息更高的优先级。这样就可以集中查看错误信息

在shell脚本中重定向输出

  • 可以在脚本中用STDOUT和STDERR文件描述符以在多个位置生成输出,只要简单地重定向相应的文件描述符就行了。有两种方法来在脚本中重定向输出:
    • 临时重定向行输出
    • 永久重定向脚本中的所有命令

临时重定向

  • 如果有意在脚本中生成错误消息,可以将单独的一行输出重定向到STDERR。所需要做的是使用输出重定向符来将输出信息重定向到STDERR文件描述符。在重定向到文件描述符时,必须在文件描述符数字之前加&,如下:
echo "数据错误!!" >&2
  • 这行代码的输出会在脚本的STDERR文件描述符所指向的位置显示文本,而不是通常的STDOUT,如下:

#!/bin/bashecho "错误输出!!" >&2
echo "正常输出!!"

shell脚本基础之详解脚本数据的输入与输出

  • 如果像平常一样运行这个脚本,是看不出有什么区别的,默认情况下,Linux会将STDERR导向STDOUT。但是,如果在运行脚本时重定向了STDERR,脚本中所有导向STDERR的文本都会被重定向,如下:
    shell脚本基础之详解脚本数据的输入与输出
  • 通过STDOUT显示的文本显示在了屏幕上,而发送给STDERR的echo语句的文本则被
    重定向到了输出文件

永久重定向

  • 当脚本中有大量数据需要重定向,重定向每个echo语句就会很烦琐。我们可以使用exec命令告诉shell在脚本执行期间重定向某个特定文件描述符,如下:
#!/bin/bashexec 1>succ02.txtecho "但行好事莫问前程"
echo "钝鸟先飞大器晚成"

shell脚本基础之详解脚本数据的输入与输出

  • exec命令会启动一个新shell并将STDOUT文件描述符重定向到文件。脚本中发给STDOUT的所有输出会被重定向到文件,可以在脚本执行过程中重定向STDOUT,如下:
#!/bin/bashexec 2>err03.txtecho "但行好事莫问前程"
echo "钝鸟先飞大器晚成"exec 1>succ03.txtecho "正确输出>succ03.txt"
echo "错误输出>err03.txt" >&2

shell脚本基础之详解脚本数据的输入与输出

  • 上述脚本用exec命令来将发给STDERR的输出重定向到文件err03.txt。然后脚本用echo语句向STDOUT显示了几行文本。随后使用exec命令来将STDOUT重定向到succ03.txt文件
  • 注意,尽管STDOUT被重定向了,但仍然可以将echo语句的输出发给STDERR
  • 当我们只想将脚本的部分输出重定向到其他位置时(如错误日志),这个特性用起来非常方便。不过这样做的话,会碰到一个问题一旦重定向了STDOUT或STDERR,就很难再将它们重定向回原来的位置,如果需要在重定向中来回切换的话,下面会介绍一种方法

在shell脚本中重定向输入

  • 我们可以使用与脚本中重定向STDOUT和STDERR相同的方法来将STDIN从键盘重定向到其他位置。exec命令允许将STDIN重定向到Linux系统上的文件中,如下格式:
exec 0< inputfile
  • 这个命令会告诉shell它应该从文件testfile中获得输入,而不是STDIN。这个重定向只要在脚本需要输入时就会作用。如下:
#!/bin/bashexec 0<name.txtcount=1while read line
doecho "Name #$count$line"count=$[ $count + 1 ]
done

shell脚本基础之详解脚本数据的输入与输出

  • 在之前我们学习了如何使用read命令读取用户在键盘上输入的数据。将STDIN重定向到文件后,当read命令试图从STDIN读入数据时,它会到文件去取数据,而不是键盘,这是在脚本中从待处理的文件中读取数据的较好办法

创建自己的重定向

  • 在脚本中重定向输入和输出时,并不局限于这3个默认的文件描述符,在之前提到过,在shell中最多可以有9个打开的文件描述符。其他6个从3~8的文件描述符均可用作输入或输出重定向。你可以将这些文件描述符中的任意一个分配给文件,然后在脚本中使用它们

创建输出文件描述符

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

#!/bin/bashexec 3>test05outecho "但行好事莫问前程"
echo "输出>test05out" >&3
echo "钝鸟先飞大器晚成"

shell脚本基础之详解脚本数据的输入与输出

  • 脚本用exec命令将文件描述符3重定向到另一个文件。当脚本执行echo语句时,输出内
    容会像预想中那样显示在STDOUT上。但你重定向到文件描述符3的那行echo语句的输出却进入了另一个文件。这样就可以在显示器上保持正常的输出,而将特定信息重定向到文件中(比如日志文件)
  • 也可以不用创建新文件,而是使用exec命令来将输出追加到现有文件中:
exec 3>>test05out
  • 现在输出会被追加到test05out文件,而不是创建一个新文件

重定向文件描述符

  • 那么我们该怎么恢复已重定向的文件描述符呢?解决方法:可以分配另外一个文件描符给标准文件描述符,反之亦然。这意味着可以将STDOUT的原来位置重定向到另一个文件描述符,然后再利用该文件描述符重定向回STDOUT。听起来可能有点复杂,但实际上相当直接,如下:
#!/bin/bashexec 3>&1
exec 1>test06outecho "但行好事莫问前程"exec 1>&3
echo "钝鸟先飞大器晚成"

shell脚本基础之详解脚本数据的输入与输出

  • 上述代码:首先,脚本将文件描述符3重定向到文件描述符1的当前位置,也就是STDOUT。这意味着任何发送给文件描述符3的输出都将出现在显示器上,第二个exec命令将STDOUT重定向到文件,shell现在会将发送给STDOUT的输出直接重定向到输出文件中
  • 但是,文件描述符3仍然指向STDOUT原来的位置,也就是显示器。如果此时将输出数据发送给文件描述符3,它仍然会出现在显示器上,尽管STDOUT已经被重定向了。在向STDOUT(现在指向一个文件)发送一些输出之后,脚本将STDOUT重定向到文件描述符3的当前位置(现在仍然是显示器)。这意味着现在STDOUT又指向了它原来的位置(显示器)。这个方法可能有点令人困惑,但这是一种在脚本中临时重定向输出,然后恢复默认输出设置的常用方法

创建输入文件描述符

  • 可以用和重定向输出文件描述符同样的办法重定向输入文件描述符。在重定向到文件之前,先将STDIN文件描述符保存到另外一个文件描述符,然后在读取完文件之后再将STDIN恢复到它原来的位置,如下:
#!/bin/bashexec 6<&0
exec 0<name.txtcount=1while read line
doecho "Name #$count$line"count=$[ $count + 1 ]
doneexec 0<&6
read -p "是否结束?[y|n]" answer
case $answer inY|y) echo "已完成,再见!!";;N|n) echo "已经结束!!";;
esac

shell脚本基础之详解脚本数据的输入与输出

  • 在上述例子中,文件描述符6用来保存STDIN的位置。然后脚本将STDIN重定向到一个文件。read命令的所有输入都来自重定向后的STDIN(也就是输入文件)。在读取了所有行之后,脚本会将STDIN重定向到文件描述符6,从而将STDIN恢复到原先的位置。然后使用了read命令来测试STDIN是否恢复正常了。这次它会等待键盘的输入

创建读写文件描述符

  • 我们还可以打开单个文件描述符来作为输入和输出。可以用同一个文件描述符对同一个文件进行读写。不过用这种方法时,需要特别注意。由于是对同一个文件进行数据读写shell会维护一个内部指针,指明在文件中的当前位置。任何读或写都会从文件指针上次的位置开始。如果不够小心,它会产生一些奇奇怪怪的结果,如下:
#!/bin/bashexec 3<>test08txtread line <&3
echo "输入:$line"
echo "输出:我劝天公重抖擞,不拘一格降人才" >&3

shell脚本基础之详解脚本数据的输入与输出

  • 上述例子用了exec命令将文件描述符3分配给文件test08txt以进行文件读写。接下来,它通过分配好的文件描述符,使用read命令读取文件中的第一行,然后将这一行显示在STDOUT上,然后,用echo语句将一行数据写入由同一个文件描述符打开的文件中
  • 在运行脚本时,一开始还算正常。输出内容表明脚本读取了testfile文件中的第一行。但如果在脚本运行完毕后,查看test08txt文件内容,会发现写入文件中的数据覆盖了已有的数据
  • 当脚本向文件中写入数据时,它会从文件指针所处的位置开始。read命令读取了第一行数据,所以它使得文件指针指向了第二行数据的第一个字符。在echo语句将数据输出到文件时,它会将数据放在文件指针的当前位置,覆盖了当前文件指针位置的已有数据

关闭文件描述符

  • 如果我们创建了新的输入或输出文件描述符,shell会在脚本退出时自动关闭它们。然而在有些情况下,需要在脚本结束前手动关闭文件描述符。要关闭文件描述符,将它重定向到特殊符号&-。格式如下:
exec 3>&-
  • 此语句会关闭文件描述符3,不再在脚本中使用它,如下:
#!/bin/bashexec 3>test09out
echo "输出:但行好事莫问前程" >&3
exec 3>&-
echo "错误输出:钝鸟先飞大器晚成" >&3

shell脚本基础之详解脚本数据的输入与输出

  • 一旦关闭了文件描述符,就不能在脚本中向它写入任何数据,否则shell会生成错误消息。在关闭文件描述符时还要注意另一件事。如果随后在脚本中打开了同一个输出文件,shell会用一个新文件来替换已有文件。这意味着如果你输出数据,它就会覆盖已有文件,如下:
#!/bin/bashexec 3>test10out
echo "输出01:但行好事莫问前程" >&3
exec 3>&-
cat test10outexec 3>test10out
echo "输出02:钝鸟先飞大器晚成" >&3

shell脚本基础之详解脚本数据的输入与输出

  • 在向test10out文件发送一个数据字符串并关闭该文件描述符之后,使用用了cat命令来查看文件的内容。到目前为止,一切都还好。下一步,脚本重新打开了该输出文件并向它发送了另一个数据字符串。当显示该输出文件的内容时,所能看到的只有第二个数据字符串。shell覆盖了原来的输出文件

列出打开的文件描述符

  • 我们所用的文件描述符只有9个,可能会觉得这没什么复杂的。但有时要记住哪个文件描述符被重定向到了哪里很难。为了帮助你理清条理,bash shell提供了lsof命令
  • lsof命令会列出整个Linux系统打开的所有文件描述符。这是个有争议的功能,因为它会向非系统管理员用户提供Linux系统的信息。鉴于此原因,许多Linux系统隐藏了该命令,这样普通用户就不会一不小心就发现了。在很多Linux系统中(如Fedora),lsof命令位于/usr/sbin目录。要想以普通用户账户来运行它,必须通过全路径名来引用:
/usr/sbin/lsof 
  • 此命令会产生大量的输出。它会显示当前Linux系统上打开的每个文件的有关信息。这包括后台运行的所有进程以及登录到系统的任何用户,有大量的命令行选项和参数可以用来帮助过滤lsof的输出。最常用的有-p和-d,前者允许指定进程ID(PID),后者允许指定要显示的文件描述符编号,要想知道进程的当前PID,可以用特殊环境变量$$(shell会将它设为当前PID)。-a选项用来对其他两个选项的结果执行布尔AND运算,如下:
/usr/bin/lsof -a -p $$ -d 0,1,2

shell脚本基础之详解脚本数据的输入与输出

  • 上图显示了当前进程(bash shell)的默认文件描述符(0、1和2)。lsof的默认输出中有7列信息,如下表:
列 名 描 述
COMMAND 正在运行的命令名的前9个字符
PID 进程的PID
USER 进程属主的登录名
FD 文件描述符号以及访问类型(r代表读,w代表写,u代表读写)
TYPE 文件的类型(CHR代表字符型,BLK代表块型,DIR代表目录,REG代表常规文件)
DEVICE 设备的设备号(主设备号和从设备号)
SIZE 如果有的话,表示文件的大小
NODE 本地文件的节点号
NAME 文件名
  • 与STDIN、STDOUT和STDERR关联的文件类型是字符型。因为STDIN、STDOUT和STDERR文件描述符都指向终端,所以输出文件的名称就是终端的设备名。所有3种标准文件都支持读和写(尽管向STDIN写数据以及从STDOUT读数据看起来有点奇怪)
  • 现在看一下在打开了多个替代性文件描述符的脚本中使用lsof命令的结果,如下:
#!/bin/bashexec 3>test11out01
exec 6>test11out02
exec 7<name.txt/usr/bin/lsof -a -p $$ -d 0,1,2,3,6,7

shell脚本基础之详解脚本数据的输入与输出

  • 上述脚本创建了3个替代性文件描述符,两个作为输出(3和6),一个作为输入(7)。在脚本运行lsof命令时,可以在输出中看到新的文件描述符。去掉了输出中的第一部分,这样就能看到文件名的结果了。文件名显示了文件描述符所使用的文件的完整路径名。它将每个文件都显示成REG类型的,这说明它们是文件系统中的常规文件

阻止命令输出

  • 有时候,我们可能不想显示脚本的输出。这在将脚本作为后台进程运行时很常见。如果在运行在后台的脚本出现错误消息,shell会通过其它方式将它们发给进程的属主。这会很麻烦,尤其是当运行会生成很多烦琐的小错误的脚本时
  • 要解决这个问题,可以将STDERR重定向到一个叫作null文件的特殊文件。null文件跟它的名字很像,文件里什么都没有。shell输出到null文件的任何数据都不会保存,全部都被丢掉了
  • 在Linux系统上null文件的标准位置是/dev/null。你重定向到该位置的任何数据都会被丢掉,不会显示,如下:
ls -al > /dev/null

shell脚本基础之详解脚本数据的输入与输出

  • 这是避免出现错误消息,也无需保存它们的一个常用方法:
    shell脚本基础之详解脚本数据的输入与输出
  • 也可以在输入重定向中将/dev/null作为输入文件。由于/dev/null文件不含有任何内容,程序员通常用它来快速清除现有文件中的数据,而不用先删除文件再重新创建,如下:
    shell脚本基础之详解脚本数据的输入与输出
    -文件name.txt仍然存在系统上,但现在它是空文件。这是清除日志文件的一个常用方法,因为日志文件必须时刻准备等待应用程序操作

创建临时文件

  • Linux系统有特殊的目录,专供临时文件使用。Linux使用/tmp目录来存放不需要永久保留的文件。大多数Linux发行版配置了系统在启动时自动删除/tmp目录的所有文件,系统上的任何用户账户都有权限在读写/tmp目录中的文件。这个特性为你提供了一种创建临时文件的简单方法,而且还不用担心清理文件工作
  • 有个特殊命令可以用来创建临时文件。mktemp命令可以在/tmp目录中创建一个唯一的临时文件。shell会创建这个文件,但不用默认的umask值。它会将文件的读和写权限分配给文件的属主,并将你设成文件的属主。一旦创建了文件,我们就在脚本中有了完整的读写权限,但其他人没法访问它(当然,root用户除外)

创建本地临时文件

  • 默认情况下,mktemp会在本地目录中创建一个文件。要用mktemp命令在本地目录中创建一个临时文件,只要指定一个文件名模板就行了。模板可以包含任意文本文件名,在文件名末尾加上6个X即可,如下:
mktemp testing.XXXXXX

shell脚本基础之详解脚本数据的输入与输出

  • mktemp命令会用6个字符码替换这6个X,从而保证文件名在目录中是唯一的。你可以创建多个临时文件,它可以保证每个文件都是唯一的,如下:
    shell脚本基础之详解脚本数据的输入与输出

  • 如上图,mktemp命令的输出正是它所创建的文件的名字。在脚本中使用mktemp命令时,可能要将文件名保存到变量中,这样就能在后面的脚本中引用,如下:

#!/bin/bashtempfile=$(mktemp test12.XXXXXX)exec 3>$tempfileecho "临时文件为:$tempfile"echo "但行好事莫问前程" >&3
echo "钝鸟先飞大器晚成" >&3exec 3>&-
echo "临时文件的值为:"
cat $tempfile
rm -f $tempfile 2> /dev/null

shell脚本基础之详解脚本数据的输入与输出

  • 上述脚本用mktemp命令来创建临时文件并将文件名赋给$tempfile变量。接着将这个临时文件作为文件描述符3的输出重定向文件。在将临时文件名显示在STDOUT之后,向临时文件中写入了几行文本,然后关闭了文件描述符。最后,显示出临时文件的内容,并用rm命令将其删除

在/tmp 目录创建临时文件

  • -t选项会强制mktemp命令来在系统的临时目录来创建该文件。在用这个特性时,mktemp命令会返回用来创建临时文件的全路径,而不是只有文件名,如下:
 mktemp -t test.XXXXXX

shell脚本基础之详解脚本数据的输入与输出

  • 由于mktemp -t命令返回了全路径名,可以在Linux系统上的任何目录下引用该临时文件,不管临时目录在哪里,如下:
#!/bin/bashtempfile=$(mktemp -t test.XXXXXX)exec 3>$tempfileecho "临时文件全路径为:$tempfile"echo "但行好事莫问前程" >&3
echo "钝鸟先飞大器晚成" >&3exec 3>&-
echo "临时文件的值为:"
cat $tempfile
rm -f $tempfile 2> /dev/null

shell脚本基础之详解脚本数据的输入与输出

  • 在mktemp创建临时文件时,它会将全路径名返回给变量。这样就能在任何命令中使用该值来引用临时文件

创建临时目录

  • -d选项告诉mktemp命令来创建一个临时目录而不是临时文件。这样就能用该目录进行任何需要的操作了,比如创建其他的临时文件,如下:
#!/bin/bashtempdir=$(mktemp -d dir.XXXXXX)
cd $tempdir
tempfile1=$(mktemp test.XXXXXX)
tempfile2=$(mktemp test.XXXXXX)exec 3>$tempfile1
exec 4>$tempfile2echo "临时文件目录为:$tempdir"echo "但行好事莫问前程" >&3
echo "钝鸟先飞大器晚成" >&4

shell脚本基础之详解脚本数据的输入与输出

  • 上述脚本在当前目录创建了一个目录,然后它用cd命令进入该目录,并创建了两个临时文件。之后这两个临时文件被分配给文件描述符,用来存储脚本的输出

记录消息

  • 将输出同时发送到显示器和日志文件,这种做法有时候能够派上用场。不用将输出重定向两次,只要用特殊的tee命令就行,tee命令相当于管道的一个T型接头。它将从STDIN过来的数据同时发往两处。一处是STDOUT,另一处是tee命令行所指定的文件名,格式如下:
tee testfile
  • 由于tee会重定向来自STDIN的数据,可以用它配合管道命令来重定向命令输出,如下:
date | tee testfile

shell脚本基础之详解脚本数据的输入与输出

  • 输出出现在了STDOUT中,同时也写入了指定的文件中。注意,默认情况下,tee命令会在每次使用时覆盖输出文件内容,如下:
    shell脚本基础之详解脚本数据的输入与输出
  • 如果想将数据追加到文件中,必须用-a选项,如下:
    shell脚本基础之详解脚本数据的输入与输出
  • 利用上述的方法,既能将数据保存在文件中,也能将数据显示在屏幕上,如下:
#!/bin/bashtempfile=test15outecho "但行好事莫问前程" | tee $tempfile
echo "钝鸟先飞大器晚成" | tee -a $tempfile

shell脚本基础之详解脚本数据的输入与输出