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. 只重定向错误

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

2. 重定向错误和数据

$ 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

2在脚本中重定向输出

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

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

2.1 临时重定向

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

echo "This is an error message" >&2

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

2.2永久重定向

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

$ cat test10
#!/bin/bash
# redirecting all output to a file
exec 1>testout
echo "This is a test of redirecting all output"
echo "from a script to another file."
echo "without having to redirect every individual line" $ ./test10
$ cat testout
This is a test of redirecting all output
from a script to another file.
without having to redirect every individual line

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

3在脚本中重定向输入

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

exec 0< testfile

例子:

$ cat test12
#!/bin/bash
# redirecting file input
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.

4创建自己的重定向

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

创建输出文件描述符

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

$ cat test13
#!/bin/bash
# using an alternative file descriptor
exec 3>test13out
echo "This should display on the monitor"
echo "and this should be stored in the file" >&3
echo "Then this should be back on the monitor" $ ./test13
This should display on the monitor
Then this should be back on the monitor
$ cat test13out
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运算,这会产生如下输出。

$ /usr/sbin/lsof -a -p $$ -d 0,1,2
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
bash 3344 rich 0u CHR 136,0 2 /dev/pts/0
bash 3344 rich 1u CHR 136,0 2 /dev/pts/0
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 件描述符都指向终端,所以输出文件的名称就是终端的设备名。

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

6阻止命令输出

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

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

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

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

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

$ cat testfile
This is the first line.
This is the second line.
This is the third line.
$ cat /dev/null > testfile
$ cat testfile

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

7创建临时文件

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

7.1创建本地临时文件

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

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

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

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

$ cat test19
#!/bin/bash
# creating and using a temp file
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*

7.2/tmp 目录创建临时文件

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

$ cat test20
#!/bin/bash
# creating a temp file in /tmp
tempfile=$(mktemp -t tmp.XXXXXX)
echo "This is a test file." > $tempfile
echo "This is the second line of the test." >> $tempfile
echo "The temp file is located at: $tempfile"
cat $tempfile
rm -f $tempfile $ ./test20
The temp file is located at: /tmp/tmp.Ma3390
This is a test file.
This is the second line of the test.

7.3创建临时目录

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

$ cat test21
#!/bin/bash
# using a temporary directory
tempdir=$(mktemp -d dir.XXXXXX)
cd $tempdir
tempfile1=$(mktemp temp.XXXXXX)
tempfile2=$(mktemp temp.XXXXXX)
exec 7> $tempfile1
exec 8> $tempfile2
echo "Sending data to directory $tempdir"
echo "This is a test line of data for $tempfile1" >&7
echo "This is a test line of data for $tempfile2" >&8 $ ./test21
Sending data to directory dir.ouT8S8
$ cd dir.ouT8S8
$ cat temp.N5F3O6
This is a test line of data for temp.N5F3O6
$ cat temp.SQslb7
This is a test line of data for temp.SQslb7

最新文章

  1. windows7下php5.4成功安装imageMagick,及解决php imagick常见错误问题。(phpinfo中显示不出来是因为:1.imagick软件本身、php本身、php扩展三方版本要一致,2.需要把CORE_RL_*.dll多个文件放到/php/目录下面)
  2. 用 javascript 脚本,网站判读来访者是手机还是电脑
  3. HDU 4942 Game on S♂play(线段树、模拟、扩栈)
  4. Linux Bash Shell 快速入门
  5. PC-1500的代码存入WAV文件
  6. MongoDB 聚合 (转) 仅限于C++开发
  7. Sqlserver中存储过程,触发器,自定义函数(一)
  8. ubuntu安装 scala
  9. 1、Singleton 单件(创建模式)
  10. N年之后,只记得三井寿!而我们程序猿们也要加油珍惜时间!
  11. 前端project师,确定你的目标吧!无能的人才管他叫命运
  12. Windows服务的创建、安装、卸载
  13. HTML学习笔记Day11
  14. HDU.5394.Trie in Tina Town(回文树)
  15. zookeeper集群环境搭建(纯zookeeper)
  16. SQL Server 2008 表分区的含义
  17. iOSApp上下有黑边
  18. XmlSerializer 对象序列化成XML 自定义编码格式(gb2312)
  19. 使用VS Code开发.Net Core 2.0 MVC Web应用程序教程之一
  20. ASP.NET Core读取appsettings.json配置文件信息

热门文章

  1. 用xshell连接linux服务器失败 Could not connect to &#39;112.74.73.194&#39; (port 22): Connection failed.
  2. PHP curl_strerror函数
  3. CF R 635 div2 1337D Xenia and Colorful Gems 贪心 二分 双指针
  4. Android JNI之动态注册
  5. 并发|WEB服务器并发
  6. requests上传文件,又要上传data的处理
  7. OO第一单元(前四周)作业总结
  8. Go语言入门系列(四)之map的使用
  9. mongodb学习这篇你就成功入门了,springboot2.0整合mongodb
  10. ROS 八叉树地图构建 - 使用 octomap_server 建图过程总结!