一、  重新定向

   在前面的例子中,都是将输出信息打印到控制台或将输出信息保存到文件中,本章的内容是将标准输入和标准输出经过重定向输出到不同的位置和从不同的位置读取,而不是标准输入设备键盘。

13.1          输入和输出

   通过echo命令可以将信息输出到控制台或通过重定向符输出到文件中,通过cat命令将文件的内容定向输出到文件或只显示到控制台。两种方式是输出到控制台或输出到文件,这两种方式要不全部显示到控制台或完全不显示。

13.1.1       标准文件描述符

   Linux中所有的设备都被认为文件,包括输入和输出的过程,使用文件描述符来标识输入输出设备,文件描述符是用非负整数表示,可以唯一标识会话中打开的文件,在每个过程中最多可以使用九个文件描述符,Bash Shell保留了012三个描述符作为标准描述符,如下表。

   标准文件描述符:

描述符

缩写

描述

0

STDIN

标准输入

1

STDOUT

标准输出

2

STDERR

标准错误

  

   上面的三个描述符用来处理脚本的输入和输出,Bash Shell使用它们定义将脚本默认情况下的输入输出设备。

13.1.2       标准输入描述符STDIN

   STDIN标准输入描述符代表标准输入设备,对于控制台来说,键盘是标准输入设备,用户可以通过键盘输入信息显示到控制台,也可以使用<符来修改默认输入设备,如下:

$ cat

Hello  Bash Shell

Hello  Bash Shell

$ cat < file08

1501010001    71.05      2141618  3     07/11/15  21:46:57  1006 User001 109  4     303

1501010002    865.86    1686831  2     05/11/15  03:52:44  1009 User009 109  1     302

1501010003    652.61    2587675  2     07/14/15  19:17:39  1010 User003 110  1     305

1501010004    905.24    1282788  1     04/17/15  17:14:09  1010 User004 102  3     304

1501010005    444.25    1624680  1     04/05/15  11:40:51  1005 User009 108  1     308

 

   默认情况下,cat命令会接收默认标准输入设备键盘的输入并显示到控制台,但是可以通过<符修改标准输入设备到文件,那么cat命令将会从文件作为输入设备将文件中的内容读取并显示到控制台。

13.1.3       标准输出描述符STDOUT

   STDOUT文件描述符代表Bash Shell的标准输出设备,标准输出设备是控制台,用户输出的信息默认情况下都显示到控制台,如果cat命令和echo命令,但是也可以通过>符修改标准输出设备,如下。

$ ls -l

总用量 36

drwxrwxr-x.  3 yarn yarn 4096 3   7 11:35 bash01

drwxr-xr-x.  2 yarn yarn 4096 2   24 13:14 公共的

drwxr-xr-x.  2 yarn yarn 4096 2   24 13:14 模板

drwxr-xr-x.  2 yarn yarn 4096 2   24 13:14 视频

drwxr-xr-x.  2 yarn yarn 4096 2   24 13:14 图片

drwxr-xr-x.  2 yarn yarn 4096 2   24 13:14 文档

drwxr-xr-x.  2 yarn yarn 4096 2   24 13:14 下载

drwxr-xr-x.  2 yarn yarn 4096 2   24 13:14 音乐

drwxr-xr-x.  2 yarn yarn 4096 2   24 13:14 桌面

$ ls -l  > bash01/file10

$ cat bash01/file10

总用量 36

drwxrwxr-x.  3 yarn yarn 4096 3   7 11:43 bash01

drwxr-xr-x.  2 yarn yarn 4096 2   24 13:14 公共的

drwxr-xr-x.  2 yarn yarn 4096 2   24 13:14 模板

drwxr-xr-x.  2 yarn yarn 4096 2   24 13:14 视频

drwxr-xr-x.  2 yarn yarn 4096 2   24 13:14 图片

drwxr-xr-x.  2 yarn yarn 4096 2   24 13:14 文档

drwxr-xr-x.  2 yarn yarn 4096 2   24 13:14 下载

drwxr-xr-x.  2 yarn yarn 4096 2   24 13:14 音乐

drwxr-xr-x.  2 yarn yarn 4096 2   24 13:14 桌面

 

   默认情况下,标准输出设备是控制台,所以ls命令将文件信息输出到控制台。但是可以使用>符将标准输出修改为文件,也可以使用>>符追加信息到文件。修改了文件描述符后ls命令不会将信息输出到控制台而是将信息输出到文件,通过cat命令可以看到文件中的信息。

13.1.4       标准输出错误描述符STDERR

   STDERR文件描述符处理错误信息,Bash Shell会将脚本运行过程中的错误信息输出到STDERR,默认情况下STDERRSTDOUT描述符都是输出到控制台。如下:

$ ls -l  errfile > file11

ls: 无法访问errfile: 没有那个文件或目录

  

   上面的例子将以列表的方式显示errfile文件的信息并重定向文件信息到文件中,当前目录下不存在errfle文件,所以在控制台显示了警告信息,注意到这些警告信息没有输出到文件中而是控制台因为我们只重定向了标准输出到文件没有重定向标准错误输出,所以警告信息输出到了控制台。标准错误输出和标准输出默认情况下都是将信息输出到控制台。另外,重定向标准输出不会重定向表现错误输出。

13.1.5       重定向错误

   错误信息默认输出到控制台,也可以重定向到其他设备,从上面的表中可以看到错误输出描述符是2,只要在重定向符>之前加上一个2(如:2>)Bash Shell会将错误信息重定向到指定的设备,如下:

$ ls -l  errfile 2> errlog

$ ls -l  bash93.sh errfile 2> errlog

-rwxrw-r--.  1 yarn yarn 193 3   7 09:52 bash93.sh

 

   在当前目录下不存在errfile文件,当执行ls命令时,会将警告信息输出到errlog日志文件,不会再输出到控制台。第二条ls命令中bash93.sh文件存在,所以文件信息输出到了控制台,errfile文件不存在,警告信息重定向输出到日志文件中。这个例子中将错误信息重定向到文件而标准输出还是默认的输出设备控制台

   如果同时重定向错误信息和重定向标准输出到文件必须使用两个重定向符号,并且必须在重定向符前加上相应的文件描述符,如下:

$ ls -l  bash93.sh errfile 2> errlog 1> file11

$ ls -l  bash92.sh errfile2 2>> errlog 1>> file11

 

   第一条ls命令列表显示文件的信息,bash93.sh文件存在而errfile文件不存在,可以看到使用了两个重定向符,一个重定向了错误信息到日志文件,另一个重定向符将标准输出定向到文件中,注意:重定向符前面要加上相应的文件描述符。第二条ls命令将信息追加到文件中,下面是两个文件的内容。

   errlog日志文件:

ls: 无法访问errfile: 没有那个文件或目录

ls: 无法访问errfile2: 没有那个文件或目

 

   file11文件:

-rwxrw-r--.  1 yarn yarn 193 3   7 09:52 bash93.sh

-rwxrw-r--.  1 yarn yarn 392 3   5 17:29 bash92.sh

 

   如果想将标准输出和错误信息重定向到一个日志文件,Bash Shell提供了&符,就不需要使用两个重定向符了,如下:

$ ls -l  bash93.sh errfile 2> errlog2 1>> errlog2

 

   上面的例子使用了两个重定向符,将标准输出和错误输出从定向到同一个日志文件。

errlog2文件:

ls: 无法访问errfile: 没有那个文件或目录

-rwxrw-r--.  1 yarn yarn 193 3   7 09:52 bash93.sh

 

   BashShell中警告信息的优先级高于普通信息,所以警告信息在文件的开始部分。也可以使用&>符同时重定向到同一个文件而不需要使用两个重定向符,如下:

$ ls -l  bash94.sh errfile &> errlog3

 

errlog3文件:

ls: 无法访问errfile: 没有那个文件或目录

-rwxrw-r--.  1 yarn yarn 68 3   7 11:34 bash94.sh

 

   使用&>会将错误信息和标准输出定向到同一个设备,警告信息的优先级高于普通信息。

13.2          在脚本中重定向输出

   在脚本中可以将标准输出和错误输出重定向到其他设备,只要使用相应的文件描述符和重定向符。通常情况下在脚本中有两种重定向输出方式:

1.       临时重定向每行输出

2.      永久重定向脚本中的所有输出

13.2.1       临时重定向每行输出

   可以在脚本中定义错误信息,需要将要输出的信息重定向到标准错误输出设备,必须在重定向符和文件描述符之间存在&符,格式如下。

echo "Parameter  input error! " >&2

ls -l  >&2

 

   将信息定义为错误信息,实现信息既显示到控制台同时保存到文件,如下例子。

例:bash94.sh

#!/bin/bash

 

for var  in a b c

do

  # 将输出信息定义为警告信息

  echo "Output data is $var"  >&2

  # 标准输出

  echo "Output data is $var"

done

 

   控制台显示:

$ bash94.sh

Output  data is a

Output  data is a

Output  data is b

Output  data is b

Output  data is c

Output  data is c

$ bash94.sh 2> errlog

Output  data is a

Output  data is b

Output  data is c

$ cat errlog

Output  data is a

Output  data is b

Output  data is c

$ bash94.sh 2>errlog 1> file12

$ cat file12

Output  data is a

Output  data is b

Output  data is c

$ cat errlog

Output  data is a

Output  data is b

Output  data is c

 

   在执行脚本时,如果没有重定向到文件,默认情况下错误信息会定向到标准输出。如果同时将标准输出也重定向到文件,控制台将不会显示信息。

 

13.2.2       永久重定向脚本中的所有输出

   如果脚本中有大量的输出需要重定向,使用上面的临时重定向方式就非常繁琐,可以采用exec命令指定脚本生命周期内的重定向文件描述符,如下例子。

例:bash95.sh

#!/bin/bash

# 重定向标准输出到日志文件

# 在脚本执行期间所有的标准输出都会保存到文件syslog

exec 1> syslog

 

dir=/home/yarn/bash01

 

for  file in $dir/*

do

  if [ -d "$file" ]

  then

    # 标准输出信息

    echo "$file is a directory!"

  fi

  if [ -f "$file" ]

  then

    # 标准输出信息

    echo "$file is a file!"

  fi

done

 

   命令exec会启动一个新的Shell并将标准输出的文件描述符重定向到文件,在脚本执行期间脚本中所有的标准输出都会重定向输出到文件syslog

   也可以在脚本中间重定向标准输出,但需要注意的是,在定义重定向命令前的输出不会改变默认的输出,如下例子。

例:bash96.sh

#!/bin/bash

# 输出到控制台

echo  "System start-up!"

# 信息输出到控制台

read -p  "Please input username: " username

read -s  -p "Please input password: " password

# 换行

echo

# 重定向错误信息输出到文件

exec  2> errlog

# 重定向标准输出到文件

exec  1> syslog

 

if [ -n  "$username" ] && [ -n "$password" ]

then

  if [ $username = "yarn" ]  && [ $password = "123" ]

  then

    # 标准输出,信息重定向到syslog文件

    echo "Login system success! user:  $username"

  else

    # 定义错误信息输出,信息重定向到errlog文件

    echo "Login system failed!"  >&2

  fi

else

  # 定义错误信息输出,信息重定向到errlog文件

  echo "Input username and password  error!" >&2

fi

 

   在重定向标准输出到文件前的输出会默认输出到控制台,在脚本的中间重定向了标准输出和错误输出到文件,在脚本执行期间把不同的信息输出到文件,可以根据文件中的信息跟踪脚本的执行过程。需要注意的是,使用exec命令重定向输出后在脚本的执行周期内无法将输出重定向到默认的或之前的设备,如果想在脚本的重定向中来回切换,将重要的信息输出到文件,而提示信息只输出到控制台。后面将举例说明。

13.3          在脚本中重新定向输入

   还可以在脚本中通过exec命令将标准输入设备从键盘重定向到其他设备,可以将标准输入设备从键盘重定向到文件中,命令格式如下。

exec  0< filename

 

   这个命令告诉系统从文件中获得输入而不是默认的键盘,在脚本的执行周期内有效。下面的例子是脚本从文件中读取用户名和密码并登录系统,登陆成功后输出登录成功信息到控制台,通过exec命令将标准输入键盘重定向到文件。

   file13

username  yarn

password  123

 

例:bash97.sh

#!/bin/bash

# 标准输入从键盘重定向到文件

exec  0< file13

# 循环读取文件

while  read line

do

  # 输出一行信息到控制台

  echo "From file parameter is  $line"

  # 循环读取一行记录的字段

  for parameter in $line

  do

    # 判断一行数据的第一个字段是否是用户名

    if  [ $parameter = "username" ]

then

  # 则循环读取字段值

      for username in $line

      do

        # 如果字段名不是username,则一定是用户名

        if [ $username !=  "username" ]

        then

          # 将用户名保存到变量

          username=$username

        fi

      done

fi 

# 同上,判断密码

    if [ $parameter = "password" ]

    then

      for password in $line

      do

        if [ $password !=  "passoword" ]

        then

          password=$password

        fi

      done

    fi

  done

done

# 简单的输出

echo  "Login username is $username"

echo  "Login password is $password"

# 判断用户名和密码是否正确

if [  $username = "yarn" ] && [ $password = "123" ]

then

  echo "User $username login  success"

else

  echo "User $username login fail"

fi

 

控制台显示:

$  bash97.sh

From  file parameter is username yarn

From  file parameter is password 123

Login  username is yarn

Login  password is 123

User yarn login success

 

   通过exec命令把标准输入设备键盘重定向到文件,这是通常的做法,将配置信息写入到文件,在脚本中循环读取文件中的信息并赋值给变量并在脚本运行期间引用。通过read命令可以从命令行读取用户输入到的参数,当标准输入重定向到文件后,read命令同样可以从文件中读取记录。需要注意的是,当输入设备重定向到文件后,如果要回到默认的标准输入设备键盘要采用另外的方式,如果想在不同的输入设备之间来回切换有不同的方法,下面的内容会详细讲解和演示。

13.4          创建重定向描述符

   在脚本中重定向输入或输出时,除了012外,还有6个文件描述符可以用,分别是38,加上默认的02,一共是九个文件描述符。这另外六个文件描述符可以重定向输入和重定向输出。可以使用其中一个重定向从文件输入或输出到文件,而标准的输入、输出和错误输出文件描述符还采用默认的方式,这样更加灵活并且可以在不同的输入或输出设备之间来回切换,下面通过例子说明。

13.4.1       输出文件描述符

   使用exec命令为输出分配文件描述符,这个文件描述符会一直有效直到重新分配,如下面的例子。

例:bash98.sh

#!/bin/bash

# 为输出分配文件描述符3,输出到文件

exec  3> syslog

 

dir=/home/yarn/bash01

 

for  file in $dir/*

do

  if [ -d "$file" ]

  then

    # 输出重定向到文件描述符3,输出到文件

    echo "$file is a directory"  >&3

  fi

  if [ -f "$file" ]

  then

    # 同上

    echo "$file is a file"  >&3

  fi

done

# 可以修改输出文件描述符3,输出到另一个文件

exec  3> syslog2

# 信息将输出到修改后的文件syslog2

echo  "Select file success!" >&3

# 又切换回syslog文件,注意:采用追加的方式,不覆盖之前输入的信息

exec  3>> syslog

# 输出到默认的标准输出:控制台

echo  "Test over!"

 

   如果日志文件已经存在,可以采用追加的方式而不需要重新创建文件,对文件的内容不会覆盖。另外在脚本中可以将信息输出到不同的文件,只要修改重定向后面的文件就可以了。另外需要注意的是,需要重定向输出的信息后要存在定向符、&符和要定向的文件描述符。

13.4.2       重定向文件描述符

虽然可以采用其他文件描述符的方式重新定向输出到文件或从文件中输入,但是存在的问题是需要在整个脚本中每个输出行的后面添加重定向描述符,使得代码的整洁度降低和编码的繁琐性增加。当然可以采用另一种方法,在标准输出到控制台或输出到文件来回切换,下面通过一个简单的例子说明。

例:bash99.sh

#!/bin/bash

# 将文件描述符3重定向到控制台

exec  3>&1

# 将标准输出描述符重定向到文件

exec  1>syslog

# 输出的内容会保存到日志文件中

echo  "标准输出重定向输出到日志文件"

echo  "显示的内容都存在日志文件中"

# 将标准输出描述符重定向到文件描述符3,也就是重定向到控制台

exec  1>&3

# 输出的内容会输出到控制台

echo  "标准输出重定向到控制台"

echo  "输出的内容会输出到控制台"

 

   在上面的例子中,我们首先将文件描述符3重定向到文件描述符1的默认位置,也就是控制台。这意味着发送给文件描述符3的任何输出都将输出到控制台。然后将文件描述符1重定向输出到文件,但是需要注意的是,文件描述符3还指向标准输出,所以当文件描述符1定向到文件描述符3时,文件描述符1 又回到了默认状态,输出到控制台,通过这种方式,可以在不同的方式之间进行切换,这是一种通用的方式。

13.4.3       输入文件描述符

   创建输入文件描述符的方式类似于上一个案例,首先将输入文件描述符0保存到另一个文件描述符,然后重新定向输入文件描述符到其他设备,如从文件中输入。文件输入完成后,将文件描述符0恢复到之前的状态,下面通过一个简单的例子说明。

例:bash100.sh

#!/bin/bash

# 将文件描述符5重定向到文件描述符0的默认位置控制台

exec  5<&0

# 将文件描述符0重定向到文件,从文件中读取

exec  0<file08

# 从文件中读取信息,read命令会自动读取文件中的数据

while  read line

do

  # 简单的输出到控制台

  echo $line

done

# 文件描述符0恢复到原来的状态

exec  0<&5

# 从控制台接收输入

echo -n  "Input parameter: "

# 读取输入时,read命令会从控制台读取

read  parameter

# 使用case分支语句

case  $parameter in

    open)

    echo "Syatem start-up!"

    ;;

    close)

    echo "System stop!"

    ;;

    *)

    echo "Input error!"

    ;;

esac

 

   这种方式是通用的方式,在不同的输入设备之间进行切换,需要注意的是,首先要保存默认状态到一个文件描述符,用于还原之前的输入设备。

13.4.4       关闭文件描述符

   如果在脚本中定义了输入或输出文件描述符,在脚本执行结束后Shell会自动关闭它们,但是在有些情况下要手动关闭文件描述符,如在脚本中执行另外的脚本之前。关闭文件描述符采用下面的方式。

    exec 3>&-

 

   将文件描述符重新定向到&-会关闭文件描述符,文件描述符关闭后在脚本中就不能在使用了,如果继续使用此文件描述符,系统会提示警告信息,下面通过两个例子说明,第一个是关闭输出描述符后使用输出描述符的情况,另一个是关闭输入描述符。

例:bash101.sh

#!/bin/bash

# 将文件描述符3重定向到文件,输出到文件

exec  3>syslog

# 输出信息到文件描述符3

echo  "Hello Bash Shell!" >&3

# 关闭文件描述符3

exec  3>&-

# 继续输出信息到文件描述符3,系统会报出警告信息

echo  "This is Bash script!" >&3

 

控制台显示:

$  bash101.sh

./bash101.sh:  line 9: 3: 错误的文件描述符

 

例:bash102.sh

#!/bin/bash

# 将文件描述符3输入重定向到文件

exec  3< file08

# 循环读取,从文件描述符3

while  read line <&3

do

  echo $line

done

# 关闭文件描述符3

exec  3>&-

# 又从文件描述符3读取,系统会提示警告信

while  read line <&3

do

  echo $line

done

 

控制台显示:

$  bash102.sh

1501010001  71.05 2141618 3 07/11/15 21:46:57 1006 User001 109 4 303

1501010002  865.86 1686831 2 05/11/15 03:52:44 1009 User009 109 1 302

1501010003  652.61 2587675 2 07/14/15 19:17:39 1010 User003 110 1 305

1501010004  905.24 1282788 1 04/17/15 17:14:09 1010 User004 102 3 304

1501010005  444.25 1624680 1 04/05/15 11:40:51 1005 User009 108 1 308

./bash102.sh: line 12: 3: 错误的文件描述符

 

   注意:一旦关闭了文件描述符,就不能在使用它输入或输出信息了,否则会提示警告信息。关闭文件描述符后又打开到同一个文件时要注意>>>的区别,第一个是创建一个新的文件,而第二个是追加到文件,通过一个例子说明。

例:bash103.sh

#!/bin/bash

# 将文件描述符3输出重定向到文件

exec 3>  errlog

# 输出信息到文件描述符3

echo  "This is first test!" >&3

# 关闭文件描述符3

exec  3>&-

# 重新将文件描述符3输出重定向到同一个文件

exec  3> errlog

# 输出信息到文件,会重新创建errlog文件之前的信息覆盖

echo  "This is second test!" >&3

# 关闭文件描述符3

exec  3>&-

# 重新将文件描述符输出重定向到文件,注意:是追加信息到同一个文件

exec  3>> errlog

# 输出信息到文件描述符3

echo  "This is third test!" >&3

 

控制台显示:

$  bash103.sh

$ cat  errlog

This is second test!

This is third test!

 

   要注意创建和追加的区别。

13.5          阻止命令输出

   在脚本执行过程中,可以控制信息的输出,如警告信息输出到控制台,执行的过程信息输出到日志文件,但是有些情况下不希望有输出信息,如在后台执行的脚本。对于可能输出信息的命令可以采用下面的方式阻止将信息输出,将输出信息重定向到/dev/null

命令 > /dev/null

 

在目录/dev下有一个null的特殊文件,文件中什么都没有,输入到null文件中的内容都会被删除不会保存,所以将可能输出信息的命令后面加上 >/dev/null,信息将不会输出到控制台,如下例子。

$ ls -l  > /dev/null

$ cat  file08 > /dev/null

$ cat  file08

1501010001    71.05 2141618       3 07/11/15 21:46:57 1006 User001       109  4     303

1501010002    865.86 1686831     2 05/11/15 03:52:44 1009 User009       109  1     302

1501010003    652.61 2587675     2 07/14/15 19:17:39 1010 User003       110  1     305

1501010004    905.24 1282788     1 04/17/15 17:14:09 1010 User004       102  3     304

1501010005    444.25 1624680     1 04/05/15 11:40:51 1005 User009       108  1     308

$ ls  test

ls: 无法访问test: 没有那个文件或目录

$ ls  test >/dev/null

ls: 无法访问test: 没有那个文件或目录

$ ls  test 2> /dev/null

 

   由于/dev/null文件不包含任何内容,可以将/dev/null作为输入重定向到想要清除内容的文件,文件的内容将被丢弃。采用这样的方式还可以清空日志文件内容,不需要重新创建一个文件

$ cat file14

1501010001    71.05 2141618       3 07/11/15 21:46:57 1006 User001       109  4     303

1501010002    865.86 1686831     2 05/11/15 03:52:44 1009 User009       109  1     302

1501010003    652.61 2587675     2 07/14/15 19:17:39 1010 User003       110  1     305

1501010004    905.24 1282788     1 04/17/15 17:14:09 1010 User004       102  3     304

1501010005    444.25 1624680     1 04/05/15 11:40:51 1005 User009       108  1     308

$ cat /dev/null > file14

$ cat file14

 

   这是将文件文件清空而不需要重新创建文件的常用方式。上面的例子说明如何通过/dev/null阻止输出和清除文件内容。

13.6          创建临时文件

   Linux系统中的根目录下有一个/tmp目录,主要用来存放临时文件。这个目录下的文件不会长期保存,多数Linux系统会在系统启动时自动清除/tmp目录下的所有文件。系统上的任何用户都有权限在/tmp目录下读或者写,这个目录的特点是为用户提供创建临时文件的方便性但不需要用户来管理。

   创建一个文件用来保存一些信息,可以使用touch命令,但系统提供了另一个命令mktempmktemp命令可以创建一个唯一的文件并将文件的读写权限分配给属主,其他用户没有权限访问,通常在脚本中创建临时文件时会用到。

13.6.1       创建本地临时文件

   默认情况下mktemp命令会在当前目录创建一个文件,并且这个文件在这个目录中是唯一的,创建文件有一定的格式,要创建的文件名后面要加上大写的X,格式如下。

$ mktemp  filenameXXXXXX

filename9TAZG1

 

   不同的Linux版本可能存在差异,X的个数不要少于三个但可以更多,X字符码会生成随机字符,每一次创建的都不会相同,如下所示。

$  mktemp filename.XX

mktemp:  模板"filename.XX" X 太少

$  mktemp filename.XXX

filename.m7q

$  mktemp filename.XXX

filename.qgK

$  mktemp filename.XXXXXXXXXXXXXXXXX

filename.JHTqRHejNl5QuBfvr

 

   文件名和字符码之间可以使用点的方式。因为字符码会随机变化,所以创建的文件一定是唯一的。临时文件通常在脚本中使用,将创建的文件名通常先保存到变量中,就可以在脚本中引用文件名了。下面通过一个例子说明mktemp命令的使用方式。

例:bash104.sh

#!/bin/bash

# 创建文件并将文件名保存到变量filename

filename=`mktemp  logXXX`

# 将文件描述符3输出重定向到文件

exec  3> $filename

 

echo  "Test create temp log file and writer to file: $filename"

# 输出信息到文件描述符3

echo  "This is first test!" >&3

echo  "This is second test!" >&3

echo  "This is third test!" >&3

# 关闭文件描述符

exec  3>&-

 

echo  "Log file contents are: "

# 在控制台显示文件内容

cat  $filename

# 删除临时文件,并屏蔽错误信息输出

rm -f  $filename 2> /dev/null

 

控制台显示:

$  bash104.sh

Test  create temp log file and writer to file: logfUJ

Log  file contents are:

This is  first test!

This is  second test!

This is  third test!

 

   脚本中创建了临时文件,将文件名保存到变量中。将文件描述符3输出重定向到临时文件。将信息输出到文件,在控制台显示信息后并删除临时文件。在删除临时文件时阻止错误信息的输出。

13.6.2       /tmp目录下创建临时文件

   如果要在/tmp目录下创建临时文件,需要在mktemp命令后面跟上参数-t。参数-t会强制mktemp命令在/tmp目录下创建临时文件并返回完整的文件名称(带完整路径)

例:bash105.sh

#!/bin/bash

# /tmp目录下创建临时文件,并将完整的文件名保存到变量中

filename=`mktemp  -t logXXX`

 

echo  "Temp file the full name: $filename"

# 追加信息到临时文件

echo  "This is first test!" >> $filename

echo  "This is second test!" >> $filename

echo  "This is third test!" >> $filename

 

echo  "Contents of the $filename:   "

# 输出文件内容

cat  $filename

# 删除临时文件

rm -f  $filename 2> /dev/null

# 查看文件是否存在

ls -l  $filename

 

控制台显示:

$  bash105.sh

Temp  file the full name: /tmp/logSpp

Contents  of the /tmp/logSpp: 

This is  first test!

This is  second test!

This is  third test!

ls: 无法访问/tmp/logSpp: 没有那个文件或目录

 

   使用带参数-tmktemp命令会返回带/tmp目录的完整的临时文件名,只要将这个文件名保存到变量中,就可以在脚本的任何位置引用。

13.6.3       创建临时目录

   使用mktemp命令的可创建临时目录,只要在命令后面加上参数-d即可。创建临时目录的方式如同创建临时文件,如果不加参数-t会在当前目录下创建临时目录,如果加上参数-t会在/tmp目录下创建临时目录。目录名后要有不少于三个大写的X字符码来产生随机字符,创建的临时目录是唯一的,可以在临时目录下创建临时文件,通过一个例子说明。

例:bash106.sh

#!/bin/bash

# 在当前目录创建一个临时目录

dirname=`mktemp  -d dirXXX`

echo  "Temp directory is $dirname"

cd  $dirname

# 在临时目录下创建两个临时文件

filename1=`mktemp  errlogXXX`

filename2=`mktemp  syslogXXX`

# 将文件描述符输出重定向到文件

exec  3> $filename1

exec  4> $filename2

# 输出重定向到文件描述符3

echo  "This is first test!" >&3

echo  "This is second test!" >&3

echo  "This is third test!" >&3

# 输出重定向到文件描述符4

echo  "This is first test!" >&4

echo  "This is second test!" >&4

echo  "This is third test!" >&4

# 关闭文件描述符

exec  3>&-

exec  4>&-

# 显示创建的临时文件

ls -l  2> /dev/null

# 显示文件内容

cat  $filename1

cat  $filename2

# 回到上一级目录

cd ..

# 删除临时目录同时删除临时文件

rm -rf  $dirname 2> /dev/null

 

控制台显示:

$  bash106.sh

Temp  directory is dirzaM

总用量 8

-rw-------.  1 yarn yarn 61 3   14 11:21 errlogmUH

-rw-------.  1 yarn yarn 61 3   14 11:21 syslog2So

This is  first test!

This is  second test!

This is  third test!

This is  first test!

This is  second test!

This is  third test!

 

   脚本中在当前目录下创建了一个临时目录,切换到临时目录下并创建了两个临时文件,创建文件描述符并输出重定向到临时文件,最后将临时目录和临时文件删除。可以在/tmp目录下创建临时目录,需要在mktemp命令后面加上参数-t

13.7          消息处理

   在脚本的执行过程中,有时候需要将信息同时输出到文件并显示到控制台,采用输出重定向可以实现,但是需要两次输出重定向。可以通过命令tee实现上述的功能,但是需要通过管道命令,如下格式。

$ cat file08 | tee file16

1501010001    71.05 2141618       3 07/11/15 21:46:57 1006 User001       109  4     303

1501010002    865.86 1686831     2 05/11/15 03:52:44 1009 User009       109  1     302

1501010003    652.61 2587675     2 07/14/15 19:17:39 1010 User003       110  1     305

1501010004    905.24 1282788     1 04/17/15 17:14:09 1010 User004       102  3     304

1501010005    444.25 1624680     1 04/05/15 11:40:51 1005 User009       108  1     308

$ cat file16

1501010001    71.05 2141618       3 07/11/15 21:46:57 1006 User001       109  4     303

1501010002    865.86 1686831     2 05/11/15 03:52:44 1009 User009       109  1     302

1501010003    652.61 2587675     2 07/14/15 19:17:39 1010 User003       110  1     305

1501010004    905.24 1282788     1 04/17/15 17:14:09 1010 User004       102  3     304

1501010005    444.25 1624680     1 04/05/15 11:40:51 1005 User009       108  1     308

$ ls -l | tee file16

总用量 616

-rwxrw-r--. 1 yarn yarn   126 2  26 17:46 bash04.sh

-rwxrw-r--. 1 yarn yarn   535 2  27 11:19 bash05.sh

-rwxrw-r--. 1 yarn yarn   125 2  27 13:25 bash06.sh

-rwxrw-r--. 1 yarn yarn   136 2  27 15:23 bash07.sh

$ cat file16

总用量 616

-rwxrw-r--. 1 yarn yarn   126 2  26 17:46 bash04.sh

-rwxrw-r--. 1 yarn yarn   535 2  27 11:19 bash05.sh

-rwxrw-r--. 1 yarn yarn   125 2  27 13:25 bash06.sh

-rwxrw-r--. 1 yarn yarn   136 2  27 15:23 bash07.sh

$ date | tee file16

2016 03 14 星期一 11:41:13 CST

$ cat file16

2016 03 14 星期一 11:41:13 CST

 

   需要注意的是tee命令需要使用管道命令,在输入到文件中的同时输出到控制台。另外,tee命令向文件中输出的内容会覆盖之前的内容,如果需要将输出信息追加到文件中,需要使用参数-a,如下。

$ date  | tee file16

2016 03  14 星期一  11:48:27 CST

$ cat  file16

2016 03  14 星期一  11:48:27 CST

$ date  | tee -a file16

2016 03  14 星期一  11:48:42 CST

$ cat  file16

2016 03  14 星期一  11:48:27 CST

2016 03  14 星期一  11:48:42 CST

  

   使用这种方法,在脚本中可以实现双向输出,既输出到文件又输出到控制台,下面通过一个简单的例子说明。

例:bash107.sh

#!/bin/bash

# 在当前目录下创建一个临时文件

filename=`mktemp  tempXXX`

# 输出信息到文件并输出到控制台

echo "This  is first test!" | tee $filename

echo  "This is second test!" | tee -a $filename

echo  "This is third test!" | tee -a $filename

 

echo  "Contents of to temp file: "

cat  $filename

# 删除临时文件

rm -f  $filename 2> /dev/null

 

   使用命令tee可以将信息保存一份并显示到控制台,在脚本中常用的方式。