註:該文章例子來自於網路的收集和整理,附帶本人註解。 ①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)。
②exec命令的介紹
1,通過檔案描述符開啟或關閉檔案。2,將檔案重新導向到標準輸入,及將標準輸出重新導向到檔案。3,exec命令重新設定了I/O重新導向,要恢複為原來的I/O指向,還得需要使用exec命令顯示指定。exec用法:&n :代表描述符代表的檔案。> < :代表以什麼形式使用描述符。exec 8<&2 :描述符8以讀取方式開啟標準錯誤對應的檔案。exec &>log:把標準輸入錯誤開啟檔案log。exec 8<&- :關閉描述符8。
1):run.sh指令碼使用exec將stdin(標準輸入)重新導向到檔案
root@37C:~# cat run.sh#!/bin/bashexec 8<&0 # 標準輸入預設是指向了鍵盤,複製一份到 8 中,8 也指向了鍵盤。exec 0< hfile # 1. 使用標準輸入開啟檔案hfile。read a # 2. read 將從stdin中讀取命令。read b echo "---------------------------"echo $aecho $becho "Close FD 8:" exec 0<&8 8<&- #將FD-8 copy到標準輸入(恢複指向鍵盤),否則,標準輸入還是指向hfile。echo -n "Pls. Enter Data: " #這裡,標準輸入重新指向了鍵盤。read c #需要我們手工鍵入字元。echo $cexit 0
結果輸出:
# hfile檔案的內容。root@37C:~# cat hfile value1value2root@37C:~# ./run.sh ---------------------------value1value2Close FD 8:Pls. Enter Data: value3value3root@37C:~#
2):run.sh指令碼將stdout重新導向到檔案
root@37C:~# cat run.sh#!/bin/bashexec 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:"dfsleep 5s # 先睡 5 秒,以區分兩個結果輸出。exec 1>&8 8>&-echo "------termincal display:-------"echo "Output of date command"dateecho "Output of df command"df
結果輸出:
root@37C:~# ./run.sh ------termincal display:-------Output of date command2016年 09月 20日 星期二 16:02:08 CSTOutput of df command檔案系統 1K-塊 已用 可用 已用% 掛載點udev 355032 0 355032 0% /devtmpfs 75824 3020 72804 4% /run/dev/sda1 17673004 6600160 10152064 40% /tmpfs 379108 132 378976 1% /dev/shmtmpfs 5120 4 5116 1% /run/locktmpfs 379108 0 379108 0% /sys/fs/cgrouptmpfs 75824 48 75776 1% /run/user/1000root@37C:~# cat log------redirect to log file-------Output of date command:2016年 09月 20日 星期二 16:02:03 CSTOutput of df command:檔案系統 1K-塊 已用 可用 已用% 掛載點udev 355032 0 355032 0% /devtmpfs 75824 3020 72804 4% /run/dev/sda1 17673004 6600160 10152064 40% /tmpfs 379108 132 378976 1% /dev/shmtmpfs 5120 4 5116 1% /run/locktmpfs 379108 0 379108 0% /sys/fs/cgrouptmpfs 75824 48 75776 1% /run/user/1000root@37C:~#
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
4):普通例子
_1):使用檔案描述符3以讀模數式開啟檔案run.py
root@37C:~# exec 3<run.py root@37C:~# cat <&3#!/usr/bin/python3# -*- coding:utf-8 -*-import logginglogging.basicConfig(level=logging.INFO)s = '0'n = int(s)logging.info('n = %d' % n)print(10 / n)root@37C:~#
_2):使用檔案描述符4以截斷模式開啟檔案log
root@37C:~# exec 4>logroot@37C:~# echo " I think befor I am" 1>&4root@37C:~# cat log I think befor I amroot@37C:~#
_3):使用檔案描述符5以追加模式開啟檔案log
root@37C:~# exec 5>>log# 這裡echo 使用'>'而非'>>'來進行追加。root@37C:~# echo 'say again: I think before I am!' >&5root@37C:~# cat log I think befor I amsay again: I think before I am!
_4):exec 執行後的觀察。
# FD 8,9也指向了FD 0,1所指向的檔案。root@37C:~# exec 9>&1root@37C:~# exec 8<&0root@37C:~# ls -l /proc/self/fd/ 總用量 0lrwx------ 1 root root 64 9月 21 21:03 0 -> /dev/pts/2lrwx------ 1 root root 64 9月 21 21:03 1 -> /dev/pts/2lrwx------ 1 root root 64 9月 21 21:03 2 -> /dev/pts/2lr-x------ 1 root root 64 9月 21 21:03 3 -> /proc/20455/fdlrwx------ 1 root root 64 9月 21 21:03 8 -> /dev/pts/2lrwx------ 1 root root 64 9月 21 21:03 9 -> /dev/pts/2
③ 嘗試題
# 嘗試一下的操作結果會如何。root@37C:~# exec 0<run.sh