1.标准文件描述符

Linux用文件描述符(file descriptor)来标识每个文件对象。文件描述符是一个非负整数,可以唯一标识会话中打开的文件。每个进程一次 多可以有九个文件描述符。出于特殊目的,bash shell保留了前三个文件描述符(0、1和2):

文件描述符

缩  写

描  述

0

STDIN

标准输入

1

STDOUT

标准输出

2

STDERR

标准错误

1. STDIN代表shell的标准输入。对终端界面来说,标准输入是键盘。

2. STDOUTSTDOUT文件描述符代表shell的标准输出。在终端界面上,标准输出就是终端显示器。

3. STDERRSTDERR文件描述符处理错误消息。STDERR文件描述符代表shell的标准错误输出。

1.1重定向错误

1. 只重定向错误

  1. $ ls -al test badtest test2 2> test5
  2. -rw-rw-r-- 1 rich rich 158 2014-10-16 11:32 test2
  3. $ cat test5
  4. ls: cannot access test: No such file or directory
  5. ls: cannot access badtest: No such file or directory

2. 重定向错误和数据

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

2在脚本中重定向输出

有两种方法来在脚本中重定向输出:

  • 临时重定向行输出
  • 永久重定向脚本中的所有命令

2.1 临时重定向

如果有意在脚本中生成错误消息,可以将单独的一行输出重定向到STDERR。你所需要做的是使用输出重定向符来将输出信息重定向到STDERR文件描述符。在重定向到文件描述符时,你必须在文件描述符数字之前加一个&:

  1. echo "This is an error message" >&2

这行会在脚本的STDERR文件描述符所指向的位置显示文本,而不是通常的STDOUT。

2.2永久重定向

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

  1. $ cat test10
  2. #!/bin/bash
  3. # redirecting all output to a file
  4. exec 1>testout
  5. echo "This is a test of redirecting all output"
  6. echo "from a script to another file."
  7. echo "without having to redirect every individual line"
  8.  
  9. $ ./test10
  10. $ cat testout
  11. This is a test of redirecting all output
  12. from a script to another file.
  13. without having to redirect every individual line

exec命令会启动一个新shell并将STDOUT文件描述符重定向到文件。脚本中发给STDOUT的所有输出会被重定向到文件。

3在脚本中重定向输入

exec命令允许你将STDIN重定向到Linux系统上的文件中:

  1. exec 0< testfile

例子:

  1. $ cat test12
  2. #!/bin/bash
  3. # redirecting file input
  4. exec 0< testfile
  5. count=1
  6. while read line
  7. do
  8. echo "Line #$count: $line"
  9. count=$[ $count + 1 ]
  10. done
  11.  
  12. $ ./test12
  13. Line #1: This is the first line.
  14. Line #2: This is the second line.
  15. Line #3: This is the third line.

4创建自己的重定向

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

创建输出文件描述符

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

  1. $ cat test13
  2. #!/bin/bash
  3. # using an alternative file descriptor
  4. exec 3>test13out
  5. echo "This should display on the monitor"
  6. echo "and this should be stored in the file" >&3
  7. echo "Then this should be back on the monitor"
  8.  
  9. $ ./test13
  10. This should display on the monitor
  11. Then this should be back on the monitor
  12. $ cat test13out
  13. and this should be stored in the file

这个脚本用exec命令将文件描述符3重定向到另一个文件。当脚本执行echo语句时,输出内容会像预想中那样显示在STDOUT上。但你重定向到文件描述符3的那行echo语句的输出却进入了另一个文件。

5列出打开的文件描述符

lsof命令会列出整个Linux系统打开的所有文件描述符。lsof命令位于/usr/sbin目录。

该命令会产生大量的输出。它会显示当前Linux系统上打开的每个文件的有关信息。这包括后台运行的所有进程以及登录到系统的任何用户。

常用的有-p和-d,前者允许指定进程ID(PID),后者允许指定要显示的文件描述符编号。

要想知道进程的当前PID,可以用特殊环境变量$$(shell会将它设为当前PID)。-a选项用来对其他两个选项的结果执行布尔AND运算,这会产生如下输出。

  1. $ /usr/sbin/lsof -a -p $$ -d 0,1,2
  2. COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
  3. bash 3344 rich 0u CHR 136,0 2 /dev/pts/0
  4. bash 3344 rich 1u CHR 136,0 2 /dev/pts/0
  5. bash 3344 rich 2u CHR 136,0 2 /dev/pts/0

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 件描述符都指向终端,所以输出文件的名称就是终端的设备名。

  1. $ cat test18
  2. #!/bin/bash
  3. # testing lsof with file descriptors
  4. exec 3> test18file1
  5. exec 6> test18file2
  6. exec 7< testfile
  7. /usr/sbin/lsof -a -p $$ -d0,1,2,3,6,7
  8.  
  9. $ ./test18
  10. COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
  11. test18 3594 rich 0u CHR 136,0 2 /dev/pts/0
  12. test18 3594 rich 1u CHR 136,0 2 /dev/pts/0
  13. test18 3594 rich 2u CHR 136,0 2 /dev/pts/0
  14. 18 3594 rich 3w REG 253,0 0 360712 /home/rich/test18file1
  15. 18 3594 rich 6w REG 253,0 0 360715 /home/rich/test18file2
  16. 18 3594 rich 7r REG 253,0 73 360717 /home/rich/testfile

6阻止命令输出

null文件跟它的名字很像,文件里什么都没有。可以将STDERR重定向到一个叫作null文件的特殊文件。shell输出到null文件的任何数据都不会保存,全部都被丢掉了。比如:

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

下面是避免出现错误消息,也无需保存它们的一个常用方法:

  1. $ ls -al badfile test16 2> /dev/null
  2. -rwxr--r-- 1 rich rich 135 Oct 29 19:57 test16*

可以在输入重定向中将/dev/null作为输入文件。由于/dev/null文件不含有任何内容,通常用它来快速清除现有文件中的数据,而不用先删除文件再重新创建。

  1. $ cat testfile
  2. This is the first line.
  3. This is the second line.
  4. This is the third line.
  5. $ cat /dev/null > testfile
  6. $ cat testfile

文件testfile仍然存在系统上,但现在它是空文件。

7创建临时文件

mktemp命令可以在/tmp目录中创建一个唯一的临时文件。shell会创建这个文件,但不用默认的umask值。

7.1创建本地临时文件

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

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

mktemp命令会用6个字符码替换这6个X,从而保证文件名在目录中是唯一的。

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

  1. $ cat test19
  2. #!/bin/bash
  3. # creating and using a temp file
  4. tempfile=$(mktemp test19.XXXXXX)
  5. exec 3>$tempfile
  6. echo "This script writes to temp file $tempfile"
  7. echo "This is the first line" >&3
  8. echo "This is the second line." >&3
  9. echo "This is the last line." >&3
  10. exec 3>&-
  11. echo "Done creating temp file. The contents are:"
  12. cat $tempfile
  13. rm -f $tempfile 2> /dev/null
  14.  
  15. $ ./test19
  16. This script writes to temp file test19.vCHoya
  17. Done creating temp file. The contents are:
  18. This is the first line
  19. This is the second line.
  20. This is the last line.
  21. $ ls -al test19*
  22. -rwxr--r-- 1 rich rich 356 Oct 29 22:03 test19*

7.2/tmp 目录创建临时文件

-t选项会强制mktemp命令来在系统的临时目录来创建该文件。mktemp命令会返回用来创建临时文件的全路径,而不是只有文件名。

  1. $ cat test20
  2. #!/bin/bash
  3. # creating a temp file in /tmp
  4. tempfile=$(mktemp -t tmp.XXXXXX)
  5. echo "This is a test file." > $tempfile
  6. echo "This is the second line of the test." >> $tempfile
  7. echo "The temp file is located at: $tempfile"
  8. cat $tempfile
  9. rm -f $tempfile
  10.  
  11. $ ./test20
  12. The temp file is located at: /tmp/tmp.Ma3390
  13. This is a test file.
  14. This is the second line of the test.

7.3创建临时目录

-d选项告诉mktemp命令来创建一个临时目录而不是临时文件。

  1. $ cat test21
  2. #!/bin/bash
  3. # using a temporary directory
  4. tempdir=$(mktemp -d dir.XXXXXX)
  5. cd $tempdir
  6. tempfile1=$(mktemp temp.XXXXXX)
  7. tempfile2=$(mktemp temp.XXXXXX)
  8. exec 7> $tempfile1
  9. exec 8> $tempfile2
  10. echo "Sending data to directory $tempdir"
  11. echo "This is a test line of data for $tempfile1" >&7
  12. echo "This is a test line of data for $tempfile2" >&8
  13.  
  14. $ ./test21
  15. Sending data to directory dir.ouT8S8
  16. $ cd dir.ouT8S8
  17. $ cat temp.N5F3O6
  18. This is a test line of data for temp.N5F3O6
  19. $ cat temp.SQslb7
  20. This is a test line of data for temp.SQslb7

Shell编程—数据展示的更多相关文章

  1. shell编程系列25--shell操作数据库实战之备份MySQL数据,并通过FTP将其传输到远端主机

    shell编程系列25--shell操作数据库实战之备份MySQL数据,并通过FTP将其传输到远端主机 备份mysql中的库或者表 mysqldump 常用参数详解: -u 用户名 -p 密码 -h ...

  2. shell编程系列24--shell操作数据库实战之利用shell脚本将文本数据导入到mysql中

    shell编程系列24--shell操作数据库实战之利用shell脚本将文本数据导入到mysql中 利用shell脚本将文本数据导入到mysql中 需求1:处理文本中的数据,将文本中的数据插入到mys ...

  3. shell编程系列21--文本处理三剑客之awk中数组的用法及模拟生产环境数据统计

    shell编程系列21--文本处理三剑客之awk中数组的用法及模拟生产环境数据统计 shell中的数组的用法: shell数组中的下标是从0开始的 array=("Allen" & ...

  4. shell编程学习之使用jq对json数据进行提取

    shell编程学习之使用jq对json提取 jq命令允许直接在命令行下对JSON进行操作,包括分片.过滤.转换等 ,jq是用C编写,没有运行时依赖,所以几乎可以运行在任何系统上.预编译的二进制文件可以 ...

  5. 大数据学习——shell编程

    03/ shell编程综合练习 自动化软件部署脚本 3.1 需求 1.需求描述 公司内有一个N个节点的集群,需要统一安装一些软件(jdk) 需要开发一个脚本,实现对集群中的N台节点批量自动下载.安装j ...

  6. [转]Windows Shell 编程 第二章 【来源:http://blog.csdn.net/wangqiulin123456/article/details/7987893】

    第二章Shell的结构  “Shell 编程”的大伞之下有大量的API函数和COM接口.这个种类繁多的‘命令’集允许你用不同的方法对Windows Shell进行编程.函数和接口并不是两种提供相同功能 ...

  7. 【转】Shell编程基础篇-上

    [转]Shell编程基础篇-上 1.1 前言 1.1.1 为什么学Shell Shell脚本语言是实现Linux/UNIX系统管理及自动化运维所必备的重要工具, Linux/UNIX系统的底层及基础应 ...

  8. [No000014A]Linux简介与shell编程

    Linux 介绍 内核 库: .so 共享对象,windows:dll 动态链接库 应用程序 Linux的基本原则: 1.由目的单一的小程序组成:组合小程序完成复杂任务: 2.一切皆文件: 3.尽量避 ...

  9. Linux(15):shell 编程

    shell基础 什么是 shell ? Shell是一个命令解释器,它的作用是解释执行用户输入的命令及程序等,用户输入一条命令, Shell 就解释执行一条. 这种从键盘一输入命令,就可以立即得到回应 ...

随机推荐

  1. AI大厂算法测试心得:人脸识别关键指标有哪些?

    仅仅在几年前,程序员要开发一款人脸识别应用,就必须精通算法的编写.但现在,随着成熟算法的对外开放,越来越多开发者只需专注于开发垂直行业的产品即可. 由调查机构发布的<中国AI产业地图研究> ...

  2. Lua学习入门(基本数据类型)

    数据类型 Lua 中有 8 个基本类型分别为:nil.boolean.number.string.userdata.function.thread 和 table. 数据类型 描述 nil 这个最简单 ...

  3. cmd 安装第三方库问题

    pip install 包名 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com 一定要指定 信任豆瓣源,不然就算换了源 ...

  4. dsu on tree详解

    这个算法还是挺人性化的,没有什么难度 就是可能看起来有点晕什么的. 大体 思想是 利用重链刨分来优化子树内部的查询. 考虑一个问题要对每个子树都要询问一次.我们暴力显然是\(n^2\)的. 考虑一下优 ...

  5. centos7与centos6命令差异

    技术群: 816227112 查看ip centos6 : ifconfigcentos7 : ip addr 修改hostname centos6 : 修改/etc/sysconfig/networ ...

  6. electron开发 - mac平台的打包和签名 - 针对electron-builder的自动更新

    配合自动更新 - 安装包签名(mac)(待补充) 前提:实现自动更新需要签名 一.本地开发调试mac签名(无需具有权限的appple账号) 打开xcode,xcode -> preference ...

  7. Maven打包方式

    转自:https://blog.csdn.net/qq_26597927/article/details/80170073 Maven打包三种方法(推荐第三种) 2018年05月02日 18:30:2 ...

  8. HA模式下的java api访问要点

    在非HA架构的HDFS中,客户端要通过java接口调用HDFS时一般是在JobRunner的类中按照下面的方式: 因为nodename只有一个节点所以会在代码中显式的指明要连接哪一个节点:但是在HA模 ...

  9. 连接云MariaDB实例

    新建实例 MariaDB CVM 内网连接 CVM远程登录测试(同一个VPC下): CVM安装客户端: yum install mysql 连接: mysql -h MariaDB内网ip -u 数据 ...

  10. python5.2文件写入

    fh=open(r"C:\55.txt","w")#文件编写新的文字,替代原有的文字!w:writedata = "努力让生活更美好!"fh ...