什么时候要使用&符号呢!!
我的理解是:当要输出重定向时,>* 这边加&
exec 3>&1 是输出到1,所以要&
exec 1>&3 输出到 3
---
exec 6<&0 这是输入重定向,<* 加&
exec 0<&6
以上说法对吗???
exec 的用法???
考虑重定向
标准输出和标准输入
报告错误
舍弃数据
创建日志文件
========================
标准文件描述符:linux用文件描述符来标识每个文件对象!文件描述符是个非负整数,可以唯一的标识会话中打开的文件。
bash shell中保留了三个特殊的文件描述符。
0 STDIN 标准输入
只输入cat 本身
[oh@localhost shell]$ cat
fu
fu
fellow
fellow
EFO
EFO
EOF
EOF
EXIT
EXIT
QUIE
QUIE
^C
[oh@localhost shell]$
1 STDOUT 标准输出
2 STDERR 标准错误
ls -al badfiel 2> test4
[oh@localhost shell]$ ls -l ddddddddd
ls: cannot access ddddddddd: No such file or directory
[oh@localhost shell]$ ls -l ddddd 2> error.md
[oh@localhost shell]$ cat error.md
ls: cannot access ddddd: No such file or directory
[oh@localhost shell]$
---------
ls -l filea fileb filec 2> error.md 1>ok.md
将错误重定向到error.md 将stdin到ok.md
或者 输出到同一个文件: &> ok.md
==================
脚本中重定向输出:
1.临时重定向每行输出
2.永久重定向脚本中的命令
将echo "error error error" 重定向到文件
echo "eoor" >&2 //将单独的一行输出到STDERR。
然后再重定向: ./c 2> error.md
[oh@localhost shell]$ cat now.md
how are you
[oh@localhost shell]$ cat c
#!/bin/bash
#using redirect in shell script
ls / 1> now.md
(echo "how are you" >&2) 2> now.md
[oh@localhost shell]$
永久重定向:
exec 1>testout
则在执行期间会重定向某个特定的文件描述符。。。
所有的都会重定向!!!!
exec命令:
[oh@localhost shell]$ ./c
hi,oh the start of shell script
now redirecting all output to another location
[oh@localhost shell]$ cat c
#!/bin/bash
#using redirect in shell script
exec 2> testerror
echo "hi,oh the start of shell script"
echo "now redirecting all output to another location"
exec 1>testout
echo "this out put should go to testout"
echo "go now" >&2
[oh@localhost shell]$ cat testerror
go now
[oh@localhost shell]$ cat testout
this out put should go to testout
[oh@localhost shell]$
=============
在脚本中重定向输入!!
exec 0<file1
while read line
do
echo “ $line”
done
首先,stdin 被重定向到file1了
然后read是到stdin里读命令,也就是file1了。
===========
创建自己的重定向!!!
输出重定向
exec 3>test
echo "dfddf" >&3
------
输入重定向:
exec 6<&0
========
这一般用来当你改变了输入或是输出的重定向时,先用自定义文件描述符来保存原先位置,当一切搞好了后,再复原。
exec 3>&1 //先将文件描述符3定向到stdout
exec 1>test1 //再stdin定向到test1里,但是3仍然指向stdout
....
exec 1>&3 //再把1也就是test1,返回到3,也就是stdout
先将文件描述符3定向到stdin
再stdin定向到test1里
但是3仍然指向stdin
===============
exec 6<&0 //6重定向到0文件描述符,也就是stdin
exec 0<testfile //stdin被重定向到testfile
exec 0<&6 // 0再被重定向到6,也就是stdin
==============
创建读写文件描述符:
[oh@localhost shell]$ cat ca
#!/bin/bash
#testing input/output file descriptor
exec 3<> testfile
read line<&3
echo "Read: $line"
echo "This is a test line">&3
[oh@localhost shell]$ cat testfile
This is a test line
[oh@localhost shell]$ vim testfile
[oh@localhost shell]$ cat testfile
this is the first line
this is the second line
this is the third line
this is the end line
[oh@localhost shell]$ ./ca
Read: this is the first line
[oh@localhost shell]$ cat testfile
this is the first line
This is a test line
ine
this is the third line
this is the end line
[oh@localhost shell]$
由于你在向同一个文件进行读取数据,写入数据操作,shell会维护一个内部指针,指明现在在文件的什么位置。
任何读或写都会在文件指针上次保存的位置开始。
现在,read命令从testfile里读取了一行,文件指针指向了第二行数据的第一个字符,echo命令向其中写入数据,覆盖
了该指针位置的所有数据。。。
那么ine 是怎么回事???????
原来是写入是按字符个数覆盖文件指针的位置。
[oh@localhost shell]$ cat testfile
this is the first line
This is the second line
this is the third line
this is the end line
[oh@localhost shell]$ cat ca
#!/bin/bash
#testing input/output file descriptor
exec 3<> testfile
read line<&3
echo "Read: $line"
echo "This is a test">&3
[oh@localhost shell]$ ./ca
Read: this is the first line
[oh@localhost shell]$ cat testfile
this is the first line
This is a test
ond line
this is the third line
this is the end line
[oh@localhost shell]$
this is the second line\0共23个字符
this is a test\0 14个字符
14个字符对应------》就变成了 cond line\0
由于字符串结束标志是\0 所以多覆盖了一个c------------》ond line\0
我猜是这样的!!!!!!!!!
--------------
现在你想在脚本当中关闭文件描述符,使用 &-
exec 3>&-
-------
既然关闭了,就不能再使用了。
然后要使用的话,就得再次重新打开来!!!打开之后,得小心是再写入时会覆盖原有数据的!!!
==========
列出打开的文件描述符!!!
首先,只有九个文件描述符可用。而知道哪个文件描述符被重定向到哪里很难。
使用 /usr/sbin/lsof 命令来查看
lsof 会有大量输出,显示了当前linux系统上打开的每个文件的有关信息。包括后台运行的所有进程以及登录到系统的任何用户。
所以:
lsof -a -p $$ -d 0,1,2
-a:对其它两个选项的结果执行布尔and运算。
-p:允许指定进程ID,要知道该进程的当前PID,可以使用$$变量
-d:指定要显示的文件描述符个数
[oh@localhost shell]$ lsof -a -p $$ -d 0,1,2
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 3865 oh 0r CHR 136,1 0t0 4 /dev/pts/1 终端设备名
bash 3865 oh 1u CHR 136,1 0t0 4 /dev/pts/1
bash 3865 oh 2u CHR 136,1 0t0 4 /dev/pts/1
[oh@localhost shell]$
可以看到有7列:
command:正在运行命令的名字的前九个字符
FD:文件描述符数目及访问类型 (u代表读写)
TYPE:文件的类型(chr:字符型,blk:快型,dir:目录,reg:常规文件)
DEVICE:主设备号,从设备号
NODE:本地文件的节点数
SIZE:如果有的话,文件的大小
name:文件名
==========
使用 /dev/null
eg:
ls -al s dfdf dfd f 2> /dev/null
eg:
cat /dev/null >testfile 将testfile清空!!!!但是不删除文件。
=========
创建临时文件:
在/tmp目录下的东西在开机时会自动删除。
使用 mktemp命令可以在/tmp目录下创建文件。
在本地创建一个临时文件,你需要指定一个文件名模板。
mktemp testing.xxxxxx/必须是大写
6个X,X之后会被字符替换,它可以保证每个文件名都是唯一的。
[oh@localhost shell]$ mktemp testing.xxxxxx
mktemp: too few X's in template `testing.xxxxxx'
[oh@localhost shell]$ mktemp testing.XXXXXX
testing.ChmF1Y
[oh@localhost shell]$ ls -l testing.*
-rw-------. 1 oh oh 0 Apr 17 18:14 testing.ChmF1Y
[oh@localhost shell]$
在脚本中使用:
tempfile=`mktemp test.XXXXXX`
exec 3>$tempfile
=====
在/tmp 目录下创建临时文件
-t 选项
[oh@localhost shell]$ mktemp -t aaa.XXXXXX
/tmp/aaa.RfCZ1h
[oh@localhost shell]$
临时目录: -d
temdir=`mktemp -d dir.XXXXXX`
cd $temdir
------------
记录消息:tee命令
tee想一个T型接头
这样就既可以将数据显示到显示器,又可以保存到文件里
stdin 的数据发往两个目地的
tee filename
date | tee file
tee 默认会覆盖file内容
tee -a 追加到文件后面。