一、了解输入和输出
(1)标准文件描述符
文件描述符标识每个文件对象。文件描述符是一个非负整数。
1》STDIN
STDIN文件描述符引用shell的标准输入,对于终端接口,标准输入是键盘。shell通过STDIN文件描述符从键盘接受输入,并在键入时处理每个字符。
[root@ceph01 display-the-data]# cat
hah
hah
shdv sc
shdv sc
2》STDOUT
STDOUT文件描述符引用shell的标准输出,在终端接口,标准输出是终端监视器。shell的所有输出(包括shellzhon中运行的程序和脚本)都定向到标准输出,也就是监视器。
[root@ceph01 display-the-data]# ls -l ../ > test
[root@ceph01 display-the-data]# cat test
total 8
drwxr-xr-x 2 root root 18 Jan 5 20:50 display-the-data
drwxr-xr-x 2 root root 4096 Jan 5 14:53 test
drwxr-xr-x 2 root root 4096 Jan 5 20:30 test1
3》STDERR
STDERR文件描述符处理错误消息,STDERR文件描述符引用shell的标准错误输出。
(2)重定向错误
1》仅重定向错误
[root@ceph01 display-the-data]# ls -al badfile 2> test1
[root@ceph01 display-the-data]# cat test1
ls: cannot access badfile: No such file or directory
2》重定向错误和数据
[root@ceph01 display-the-data]# ls -al test test1 badtest 2> test3 1> test4
[root@ceph01 display-the-data]# cat test3
ls: cannot access badtest: No such file or directory
[root@ceph01 display-the-data]# cat test4
-rw-r--r-- 1 root root 159 Jan 5 20:50 test
-rw-r--r-- 1 root root 53 Jan 5 20:55 test1
二、在脚本中重定向输出
在脚本中使用STDOUT和STDEER文件描述符在多个位置生成输出,只要重定向相应的文件描述符即可。使用脚本重定向输出的方法有两种:
临时重定向每一行
在脚本中永久重定向所有命令
(1)临时重定向
[root@ceph01 display-the-data]# cat stdeer.sh
#!/bin/bash
# testing STDERR messages
echo "This is an error" >&2
echo "This is normal output"
运行脚本:
[root@ceph01 display-the-data]# ./stdeer.sh
This is an error
This is normal output
[root@ceph01 display-the-data]# ./stdeer.sh 2>test3
This is normal output
(2)永久重定向
[root@ceph01 display-the-data]# cat forever.sh
#!/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"
[root@ceph01 display-the-data]#
运行脚本:
[root@ceph01 display-the-data]# cat testout
This is a test of redirecting all output
from a script to another file!
without having to redirect every individual line
三、在脚本中重定向输入
[root@ceph01 display-the-data]# cat file.sh
#!/bin/bash
# redirecting file input
exec 0< test1
count=1
while read line
do
echo "Line #$count: $line"
count=$[ $count + 1 ]
done
运行脚本:
[root@ceph01 display-the-data]# ./file.sh
Line #1: ls: cannot access badfile: No such file or directory
四、创建自己的重定向
(1)创建输出文件描述符
[root@ceph01 display-the-data]# cat my-output.sh
#!/bin/bash
# using an alternative file descriptor
exec 3>testout
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"
运行脚本:
[root@ceph01 display-the-data]# ./my-output.sh
This should display on the monitor
Then this should be back on the monitor
[root@ceph01 display-the-data]# cat testout
and this should be stored in the file
(2)重定向文件描述符
[root@ceph01 display-the-data]# cat my-output1.sh
#!/bin/bash
# storing STDOUT,then coming back to it
exec 3>&1
exec 1>testout1
echo "This should store in the output file"
echo "along with this line"
exec 1>&3
echo "Now things should be back to normal"
运行脚本
[root@ceph01 display-the-data]# ./my-output1.sh
Now things should be back to normal
[root@ceph01 display-the-data]# cat testout1
This should store in the output file
along with this line
(3)创建输入文件描述符
[root@ceph01 display-the-data]# cat my-output2.sh
#!/bin/bash
# redirecting input file descripors
exec 6<&0
exec 0<test1
count=1
while read line
do
echo "Line #$count: $line"
count=$[ $count + 1 ]
done
exec 0<&6
read -p "Are you done now?" answer
case $answer in
Y|y) echo "Goodbye";;
N|n) echo "Sorry,this is the end!";;
esac
运行脚本:
[root@ceph01 display-the-data]# ./my-output2.sh
Line #1: ls: cannot access badfile: No such file or directory
Are you done now?y
Goodbye
[root@ceph01 display-the-data]# ./my-output2.sh
Line #1: ls: cannot access badfile: No such file or directory
Are you done now?n
Sorry,this is the end!
(4)创建读取/写入文件描述符
[root@ceph01 display-the-data]# cat my-output3.sh
#!/bin/bash
# testing input/output file descriptor
exec 3<> test3
read line <&3
echo "Read: $line"
echo "This is a test line" >&3
运行脚本:
[root@ceph01 display-the-data]# cat test3
This is an error
[root@ceph01 display-the-data]# ./my-output3.sh
Read: This is an error
(5)关闭文件描述符
[root@ceph01 display-the-data]# cat my-output4.sh
#!/bin/bash
# testing calosing file descriptors
exec 3>test3
echo "This is a test line of data" >&3
exec 3>&-
cat test3
exec 3>test3
echo "This'll be bad" >&3
运行脚本:
[root@ceph01 display-the-data]# ./my-output4.sh
This is a test line of data
五、列出开放文件描述符
[root@ceph01 display-the-data]# /usr/sbin/lsof -a -p $$ -d 0,1,2
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 2386 root 0u CHR 136,0 0t0 3 /dev/pts/0
bash 2386 root 1u CHR 136,0 0t0 3 /dev/pts/0
bash 2386 root 2u CHR 136,0 0t0 3 /dev/pts/0
[root@ceph01 display-the-data]# cat lsof.sh
#!/bin/bash
# testing lsof with file descriptors
exec 3> test1
exec 6> test3
exec 7< test4
/usr/sbin/lsof -a -p $$ -d 0,1,2,3,6,7
运行脚本:
[root@ceph01 display-the-data]# ./lsof.sh
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
lsof.sh 10085 root 0u CHR 136,0 0t0 3 /dev/pts/0
lsof.sh 10085 root 1u CHR 136,0 0t0 3 /dev/pts/0
lsof.sh 10085 root 2u CHR 136,0 0t0 3 /dev/pts/0
lsof.sh 10085 root 3w REG 253,2 0 16777282 /home/display-the-data/test1
lsof.sh 10085 root 6w REG 253,2 0 16777283 /home/display-the-data/test3
lsof.sh 10085 root 7r REG 253,2 91 16777284 /home/display-the-data/test4
六、禁止命令输出
[root@ceph01 display-the-data]# ls -al > /dev/null
[root@ceph01 display-the-data]# cat /dev/null
七、使用临时文件
(1)创建本地临时文件
[root@ceph01 display-the-data]# mktemp testing.XXXXXX
testing.hJJ69f
[root@ceph01 display-the-data]# mktemp testing.XXXXXX
testing.NOovdd
[root@ceph01 display-the-data]# mktemp testing.XXXXXX
testing.K69zcY
[root@ceph01 display-the-data]# ls -la
total 52
drwxr-xr-x 2 root root 323 Jan 5 23:44 .
drwxr-xr-x. 5 root root 55 Jan 5 20:40 ..
-rw------- 1 root root 0 Jan 5 23:44 testing.hJJ69f
-rw------- 1 root root 0 Jan 5 23:44 testing.K69zcY
-rw------- 1 root root 0 Jan 5 23:44 testing.NOovdd
[root@ceph01 display-the-data]# cat mktemp.sh
#!/bin/bash
# creating and using a temp file
tempfile=`mktemp testing.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
运行脚本:
[root@ceph01 display-the-data]# ./mktemp.sh
This script writes to temp file testing.8i44Je
Done creating temp file.The contents are:
This is the first line
This is the second line
This is the last line
(2)在/temp中创建临时文件
[root@ceph01 display-the-data]# mktemp -t test.XXXXXX
/tmp/test.4cYGdm
[root@ceph01 display-the-data]# cat mktemp-tmp.sh
#!/bin/bash
# creating a temp file in /tmp
tempfile=`mktemp -t tmp.XXXXXXX`
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
运行脚本:
[root@ceph01 display-the-data]# ./mktemp-tmp.sh
The temp file is located at: /tmp/tmp.gXg0VwT
This is a test file!
This is the second line of the test!
(3)创建临时目录
-d选项可以让mktemp命令创建一个临时目录而不是一个文件。
[root@ceph01 display-the-data]# cat mktemp-dir.sh
#!/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
运行脚本:
[root@ceph01 display-the-data]# ./mktemp-dir.sh
Sending data to directory dir.piJXVi
八、记录消息
tee命令就像管道的T形接头,他将STDIN的数据同时发送到两个目的地,一个是STDOUT,一个是tee命令行指定的文件名:
tee filename
[root@ceph01 display-the-data]# date | tee date
Sun Jan 6 00:07:23 CST 2019
[root@ceph01 display-the-data]# cat date
Sun Jan 6 00:07:23 CST 2019
[root@ceph01 display-the-data]# cat tee.sh
#!/bin/bash
# using the tee command for logging
tempfile=teeout
echo "This is the start of the test" | tee $tempfile
echo "This is the cecond of the test" | tee -a $tempfile
echo "This is the end of the test" | tee -a $tempfile
运行脚本:
[root@ceph01 display-the-data]# ./tee.sh
This is the start of the test
This is the cecond of the test
This is the end of the test