linux学习(七) shell脚本(4)

来源:互联网 发布:php扩展 版本适配 编辑:程序博客网 时间:2024/06/15 11:45
显示数据1.linux标准文件描述符linux系统将每个对象当做文件处理,包括输入和输出过程,linux使用文件描述符标志每个文件对象。文件描述符是是个非负整数,可以唯一标识会话中打开的文件。每个进程最多可以有9个打开的文件描述符。Bash shell为特殊需要保留前3个文件描述符(0, 1, 2)。0, STDIN, 标准输入(键盘);1, STDOUT, 标准输出(显示器)2, STDERR, 标准错误(将错误输出到显示器)这3个特殊文件描述符处理脚本的输入和输出。shell使用他们将shell中默认输入和输出重定向到相应位置(通常是显示器)。STDIN  STDIN 文件描述符引用shell的标准输入,对于终端接口,标准输入是键盘。Shell通过STDIN 文件描述符从键盘接受数据,并在键入时处理每个字符。{直接使用cat命令,则是将下面标准输入的内容紧跟着显示出来}使用重定向符号(<)时,linux将使用重定向引用的文件替换标准的输入文件描述符。它读取文件并获取数据。STDOUTSTDOUT文件描述符引用shell的标准输出。在终端接口,标准输出是终端监视器。shell的所有输出(包括shell中运行的程序和脚本)都重定向到标准输出,也就是显示器。可以使用重定向符号( > )将输出重定向到其他文件描述符所引用的文件。还可以使用 >> 符号向文件添加数据。 Ls -l  > tests;  who  >> test2; 如果使用脚本的标准输出重定向,可能遇到问题。当要重定向的命令发生错误时,不会将错误信息重定向到重定向文件, 但是错误信息会显示在屏幕上。STDERRshell使用特殊的STDERR文件描述符处理错误信息。STDERR文件描述符引用shell的标准错误输出。这是shell发送错误信息(shell或shell中运行的程序或脚本所生成)的目的地。默认情况下,STDERR描述符和STDOUT描述符都指向相同的位置(即使他们分配了不同的文件描述符),即在默认情况下,所有的错误信息都输出到屏幕。处理脚本时,常常要重定向输出错误信息的文件。2.重定向错误   (1)仅仅重定向错误STDERR的文件描述符的值为2, 通过替换位于重定向符号正前方的这个文件描述符,可以仅重定向错误消息。该值必须位于重定向符号的正前方,否则无效。$ls -al badfile 2> test3$cat test3ls :cannot access badfile: No such file or directory下示例联合在同一输出中混合使用了STDOUT和STDERRjason@Ubuntu:~$ ls -al test.sh test2 2> test3-rwxrw-r-- 1 jason jason 162 12月  2 23:15 test.shjason@Ubuntu:~$ cat test3ls: 无法访问test2: 没有那个文件或目录(2)重定向错误和数据如果需要同时重定向错误和普通数据,则必须使用两个重定向符号。必须在希望重定向的数据前面放置相应的文件描述符,然后将他们指向相应的输出文件以保存数据。$ls -al test test2 test3 badtest 2> test6 1> test7在上例中,将错误信息都输出到test6,普通数据输出到test7这样,将标准输出和标准错误重定向到两个文件,如果需要也可以将STDIN和STDOUT重定向到一个文件,包括数据和错误。3. 在脚本中重定向输出(1)临时重定向每一行在脚本中要重定向到某个文件描述符时,必须在文件描述符编号前面加&. >&文件描述符(或文件名)Echo “this is an error message” >&2    /////则将该信息,本来是要定向到标准输出STDOUT的,重定向到了标准错误STDERR,可当做错误信息显示到屏幕上。Echo “this is an error message” >& test3 ////将该信息,本来是定向到标准输出STDOUT的,重定向到了test3文件中。在脚本中也可以使用文件名进行重定向,如Echo “this is an error message” > test3 ///可以不使用&,直接 > 加文件名。   如果在运行脚本时重定向 STDERR, 则任何使用脚本定向到STDERR的文本都被重定向。如 ./test.sh 2> errfile(2)永久重定向如果在脚本中重定向许多数据,那么使用echo语句重定向每行就不方便了。可以使用exec命令通知脚本执行期间重定向特殊的文件描述符。exec 1> testfileecho helloecho what are you doingecho bye这种方法的一个缺陷是重定向STDOUT或STDERR之后,就无法轻松的将他们重定向到原来的位置。可以通过创建自己的重定向来解决。4.在脚本中重定向输入exec命令可以将STDIN重定向到linux系统的文件。 Exec 0< testfile该命令告知shell应该从testfile中读取数据,而不是获得STDIN输入(在使用read命令进行读取的时候就会忽略读取STDIN,而从重定向的文件中进行读取)。在脚本请求输出的任何时候都可以使用这种重定向方式。    这种方式可以读取文件的数据并进行脚本处理,linux系统管理员常见的一个任务是,从日志文件读取数据并进行处理。这种方式很使用。5.创建自己的重定向shell中最多可以有9个打开的文件描述符,其他6个文件描述符编号从3~8,可以将这些文件描述符应用到任何文件,然后在脚本中打开他们。(1)创建输出文件描述符使用exec命令为输出分配文件描述符。与标准的文件描述符一样,向文件位置分配了备选文件符之后,该重定向是永久的,除非重新分配。exec 3>test3echo "hello jason" >&3这种方法可以使得在脚本中将普通输出重定向到监视器,将特殊信息重定向到文件。(2)重定向文件描述符可以向标准文件描述符分配一个备选文件描述符,反之亦然。这样,就可以将STDOUT的原位置重定向到备选文件描述符A(进行暂存),然后如果在脚本中重定向STDOUT到某个文件(这样在输出到STDOUT的时候就会输出到文件),如果需要再恢复STDOUT的输出位置,则可以从暂存的备选文件描述符A中恢复STDOUT。exec 3>&1exec 1>test3echo "this should be stored in the output file"echo "along with this line"exec 1>&3echo "Now things should be back to normal"首先,将文件描述符3的输出重定向到1的当前位置,即标准输出STDOUT,则任何输出到文件描述符3的数据都会输出到标准输出STDOUT; 然后将文件描述符1重定向到test3文件,则任何标准输出的数据都会输出到test3文件中;最后将文件描述符1 重定向到文件描述符3(此时文件描述符3的输出定到 STDOUT到屏幕),则文件描述符1的输出也定向到了STDOUT(即标准输出到显示器)。(3)创建输入文件描述符在重定向输入描述符之前,将STDIN文件描述符位置暂时保存到另一个备选文件描述符,然后在完成了文件的读取操作之后,可以将STDIN 恢复为原来的位置。exec 6<&0exec 0< test3count=1while read linedoecho "Line #$count: $line"count=$[$count+1]doneexec 0<&6read -p "Are you done now?" answercase $answer inY|y) echo "Goodbye";;N|n) echo "Sorry";;esac(4)创建读取/写入文件描述符   为读取和写入打开同一个文件描述符。可以使用同一个文件描述符从一个文件读取数据,同时向这个文件写入数据。但这种方式不常用{因为为同一个文件进行操作,不太容易进行读写指针的控制}(5)关闭文件描述符如果在脚本中创建新的输入或输出文件描述符,shell将在脚本退出时自动关闭他们。但有时需要在脚本结束前手动关闭文件描述符。要关闭文件描述符,将他重定向到特殊符号 &-。 exec 3>&-, 则就关闭了文件描述符36.列出开放的文件描述符lsof命令列出整个linux系统上所有的开放文件描述符。经常使用选项 -p 指定进程pid, -d 指定要显示的文件描述符编号lsof -a -p $$ -d 0,1,2jason@Ubuntu:~$ lsof -a -p $$ -d 0,1,2COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAMEbash    1939 jason    0u   CHR  136,0      0t0    3 /dev/pts/0bash    1939 jason    1u   CHR  136,0      0t0    3 /dev/pts/0bash    1939 jason    2u   CHR  136,0      0t0    3 /dev/pts/0jason@Ubuntu:~$ lsof -a -p $$ -d 0,1,2COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAMEbash    2798 jason    0u   CHR  136,1      0t0    4 /dev/pts/1bash    2798 jason    1u   CHR  136,1      0t0    4 /dev/pts/1bash    2798 jason    2u   CHR  136,1      0t0    4 /dev/pts/1每个shell进程都可以最多有9个文件描述符。7.禁止命令输出有时候不希望显示任何脚本输出。可以通过将STDERR重定向到成为空文件(null file)的特殊文件。该问价不包含任何内容。Shell输出到空文件的任何数据都不会保存。Exec 1> /dev/null8.使用临时文件 linux系统保留了一个特殊的目录位置,以供临时文件使用。Linux系统使用/tmp目录处理不需要永久保存的文件,大部分linux发行版的系统配置都是在启动时自动删除/tmp目录中的任何文件。系统上的任何账户都有权读写/tmp目录中的文件,该特性可以使得用户轻松创建临时文件,而无需担心清理问题。Mktemp命令可以在/tmp目录中创建一个唯一的临时文件,shell在创建该文件时不适用默认的umask,它仅仅向文件所有者分配读取和写入的权限。创建临时文件之后,可以通过脚本进行完整权限的读取和写入,但其他人都不能访问它。(1)创建本地临时文件使用mktemp命令在本地目录中创建临时文件,只需要指定一个文件名模板即可。模板包括文本文件名以及附加到文件名后的6个X$mktemp testing.XXXXXX$ls -al testing.*mktemp命令使用一个6字符代码替换6个X,以确保文件名在目录中的唯一性。这样可以创建多个临时文件,每个文件确保是唯一的。jason@Ubuntu:~$ mktemp jason.XXXXXXjason.TBuZw9jason@Ubuntu:~$ mktemp jason.XXXXXXjason.MSkOOFmktemp 使用 -t 选项可以获得返回一个包含完整路径名的临时文件,而不仅仅是文件名。jason@Ubuntu:~$ mktemp -t jason.XXXXXX/tmp/jason.cgZyTt在脚本中使用mktemp命令时,需要使用一个变量名保存该文件名,以便稍后在脚本中引用。tempfile=`mktemp jason.XXXXXX`exec 3>$tempfileecho this is a teempecho fdsfjd >&3exec 3>&-cat $tempfilerm -f $tempfile 2> /dev/null(2)创建临时目录-d选项使得mktemp命令创建一个临时目录而不是一个文件。然后可以将该目录用于任何目的。9.记录消息有时候需要将输出同时发送到监视器和日志文件,这种情况不需要使用两次重定向,只需要使用特殊的tee命令即可。将数据同时发送到两个目的地,一个是STDOUT,一个是指定的文件。$date | tee test3//上条命令将 date命令的输出管道给了tee命令,tee命令一方面输出到显示器,一方面输出到文件test3中。如果希望向文件中添加数据,而不是将文件删除后再写入,则可以使用-a命令。如:$date | tee -a test3  //则向test3追加数据。    
原创粉丝点击