Shell I/O重定向与exec的使用介绍

注:该文章例子来自于网络的收集和整理,附带本人注解。

①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,将文件重定向到标准输入,及将标准输出重定向到文件。
3exec命令重新设置了I/O重定向,要恢复为原来的I/O指向,还得需要使用exec命令显示指定。
exec用法:
&n  :代表描述符代表的文件。
> < :代表以什么形式使用描述符。
exec 8<&2 :描述符8以读取方式打开标准错误对应的文件。
exec &>log:把标准输入错误打开文件logexec 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
20160920日 星期二 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:
20160920日 星期二 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值