注:该文章例子来自于网络的收集和整理,附带本人注解。
①I/O重定向的常用用法
符号 意义
cmd1 | cmd2 管道符,将cmd1的标准输出作为cmd2的标准输入。
> filename 将标准输出写到文件filename之中。
< filename 将文件filename的内容读入到标准输入之中。
>>filename 将标准输出写到文件filename之中,若filename文件已存在,则将标准输出追加到filename已有内容之后。
>|filename 即使noclobber选项已开启,仍然强制将标准输出写到文件filename之中,即将filename文件覆盖掉。
n>|filename 即使noclobber选项已开启,仍然使用FD为n以截断模式打开文件filename。
n> filename 使用FD为n以截断模式打开文件filename。
n< filename 使用FD为n以读取模式打开文件filename。
n>>filename 使用FD为n以追加模式打开文件filename。
<< delimiter 此处文档(Here-document)。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
②exec命令的介绍
1,通过文件描述符打开或关闭文件。
2,将文件重定向到标准输入,及将标准输出重定向到文件。
3,exec命令重新设置了I/O重定向,要恢复为原来的I/O指向,还得需要使用exec命令显示指定。
exec用法:
&n :代表描述符代表的文件。
> < :代表以什么形式使用描述符。
exec 8<&2 :描述符8以读取方式打开标准错误对应的文件。
exec &>log:把标准输入错误打开文件log。
exec 8<&- :关闭描述符8。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
1):run.sh脚本使用exec将stdin(标准输入)重定向到文件
root@37C:~# cat run.sh
#!/bin/bash
exec 8<&0 # 标准输入默认是指向了键盘,复制一份到 8 中,8 也指向了键盘。
exec 0< hfile # 1. 使用标准输入打开文件hfile。
read a # 2. read 将从stdin中读取命令。
read b
echo "---------------------------"
echo $a
echo $b
echo "Close FD 8:"
exec 0<&8 8<&- #将FD-8 copy到标准输入(恢复指向键盘),否则,标准输入还是指向hfile。
echo -n "Pls. Enter Data: " #这里,标准输入重新指向了键盘。
read c #需要我们手工键入字符。
echo $c
exit 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
结果输出:
# hfile文件的内容。
root@37C:~# cat hfile
value1
value2
root@37C:~# ./run.sh
---------------------------
value1
value2
Close FD 8:
Pls. Enter Data: value3
value3
root@37C:~#
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
2):run.sh脚本将stdout重定向到文件
root@37C:~# cat run.sh
#!/bin/bash
exec 8>&1 # 打开 FD-8,并使它指向显示器。
exec 1> log # 将标准输出指向log文件
echo '------redirect to log file-------'
# 这部分输出会保存在log文件里面。
echo "Output of date command:"
date
echo "Output of df command:"
df
sleep 5s # 先睡 5 秒,以区分两个结果输出。
exec 1>&8 8>&-
echo "------termincal display:-------"
echo "Output of date command"
date
echo "Output of df command"
df
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
结果输出:
root@37C:~# ./run.sh
------termincal display:-------
Output of date command
2016年 09月 20日 星期二 16:02:08 CST
Output of df command
文件系统 1K-块 已用 可用 已用% 挂载点
udev 355032 0 355032 0% /dev
tmpfs 75824 3020 72804 4% /run
/dev/sda1 17673004 6600160 10152064 40% /
tmpfs 379108 132 378976 1% /dev/shm
tmpfs 5120 4 5116 1% /run/lock
tmpfs 379108 0 379108 0% /sys/fs/cgroup
tmpfs 75824 48 75776 1% /run/user/1000
root@37C:~# cat log
------redirect to log file-------
Output of date command:
2016年 09月 20日 星期二 16:02:03 CST
Output of df command:
文件系统 1K-块 已用 可用 已用% 挂载点
udev 355032 0 355032 0% /dev
tmpfs 75824 3020 72804 4% /run
/dev/sda1 17673004 6600160 10152064 40% /
tmpfs 379108 132 378976 1% /dev/shm
tmpfs 5120 4 5116 1% /run/lock
tmpfs 379108 0 379108 0% /sys/fs/cgroup
tmpfs 75824 48 75776 1% /run/user/1000
root@37C:~#
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
3):&>file将stdout和stderr重定向到文件
#!/bin/bash
exec 8>&1 9>&2 #FD 1复制到FD 8,FD 2复制到FD 9
exec &> log #&>符号将stdout和stderr重定向到文件log
ls z* #错误写入文件log
date #输出写入文件log
exec 1>&8 2>&9 8<&- 9<&- #恢复关闭操作
echo "-----------------"
echo "Close FD 8 and 9:"
ls z*
date
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
4):普通例子
_1):使用文件描述符3以读取模式打开文件run.py
root@37C:~# exec 3<run.py
root@37C:~# cat <&3
#!/usr/bin/python3
# -*- coding:utf-8 -*-
import logging
logging.basicConfig(level=logging.INFO)
s = '0'
n = int(s)
logging.info('n = %d' % n)
print(10 / n)
root@37C:~#
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
_2):使用文件描述符4以截断模式打开文件log
root@37C:~# exec 4>log
root@37C:~# echo " I think befor I am" 1>&4
root@37C:~# cat log
I think befor I am
root@37C:~#
- 1
- 2
- 3
- 4
- 5
_3):使用文件描述符5以追加模式打开文件log
root@37C:~# exec 5>>log
# 这里echo 使用'>'而非'>>'来进行追加。
root@37C:~# echo 'say again: I think before I am!' >&5
root@37C:~# cat log
I think befor I am
say again: I think before I am!
- 1
- 2
- 3
- 4
- 5
- 6
_4):exec 执行后的观察。
# FD 8,9也指向了FD 0,1所指向的文件。
root@37C:~# exec 9>&1
root@37C:~# exec 8<&0
root@37C:~# ls -l /proc/self/fd/
总用量 0
lrwx------ 1 root root 64 9月 21 21:03 0 -> /dev/pts/2
lrwx------ 1 root root 64 9月 21 21:03 1 -> /dev/pts/2
lrwx------ 1 root root 64 9月 21 21:03 2 -> /dev/pts/2
lr-x------ 1 root root 64 9月 21 21:03 3 -> /proc/20455/fd
lrwx------ 1 root root 64 9月 21 21:03 8 -> /dev/pts/2
lrwx------ 1 root root 64 9月 21 21:03 9 -> /dev/pts/2
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
③ 尝试题
# 尝试一下的操作结果会如何?
root@37C:~# exec 0<run.sh
- 1
- 2