bash - 將正常輸出和錯誤信息保存到日志文件,同時在終端輸出


背景知識

文件描述符(file descriptor)

『它是一個索引值,指向內核為每一個進程所維護的該進程打開文件的記錄表。當程序打開一個現有文件或者創建一個新文件時,內核向進程返回一個文件描述符』https://zh.wikipedia.org/wiki/文件描述符

每個Unix進程(除了可能的守護進程)應均有三個標准的POSIX文件描述符,對應於三個標准流:

        0 - stdin
        1 - stdout
        2 - stderr

(以下均用fd指代文件描述符)

bash - 3.6 Redirections

一個重定向可由一系列的 >, <, >&, <& , >>構成,從左到右決定了輸出最終指向的文件。重定向的符號兩端是文件描述符,或者可被expand解析的文件名稱。

重定向的解析遵循三個規則:

  1. 解析順序從左到右
  2. 依次解析,右邊的不能影響左邊的結果
  3. 在具體command執行之前就解析完整

在redirection - 重定向中,順序是非常重要的。比如[manual](https://www.gnu.org/software/bash/manual/html_node/Redirections.html)中的一個例子是:
    ls > dirlist 2>&1  

    ls 2>&1 > dirlist

的結果不同。

manual中的解釋為,后者"the standard error was made a copy of the standard output before the standard output was redirected to dirlist."

http://stackoverflow.com/a/34326455/6081699 這位答主給出了詳盡的解釋。回顧重定向的三個原則(也是來自這位答主的整理):

  1. 解析順序從左到右
  2. 依次解析,右邊的不能影響左邊的結果
  3. 在具體command執行之前就解析完整

在第二條中,2>&1stderr的輸出導向了stdout的輸出,然而stdout的輸出還沒有被重定向,依然指向默認輸出地點 - 終端tty。之后stdout才被重定向到dirlist,而由於重定向不受之后的規則影響的性質,stderr則繼續指向終端tty。

這位答主繼續解釋了manual中的copy一詞的含義:

    技術上講,`stdout`的fd被復制給了`stderr`用來讓它指向,因此這就解釋了后面定義的重定向規則不會影響之前定義的重定向規則。

因此,要寫一條完整有效的重定向鏈,可以采用一個形象化的技巧:將重定向鏈看做

    -> -> -> -> -> ... ->->->

的鏈條的話,與redirection從左到右的解析順序正相反,我們應該從最右端開始寫起,這樣->左端的文件流就依然能夠被下一個->右端的文件流所指向。


現在

我們可以實現題目中的要求 - 『將正常輸出和錯誤信息保存到日志文件,同時在終端輸出』

如果要把重定向規則寫入到.sh文件中,則要在開頭使用exec語句:


### bash - [Read and exec](http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_08_02.html#sect_08_02_03)
    exec fd_number> file

表示將fd_number文件描述符指向的文件指向file作為輸出文件。


如果直接在命令行中使用,則采用

    $ <some_cmd> <redirection>

的語法。

『將正常輸出和錯誤信息保存到日志文件,同時在終端輸出』描述了一個這樣的重定向鏈:

由於指向終端的fd只能通過復制stdout的fd得到,在重定向stdout之前,應該將它的文件描述符保存下來,然后再將stdout指向log_file並將stderr接入鏈條的末端。寫為:

    exec 3>&1 1>&{logfile} 2>&1

這樣我們就用fd 3保存了對終端tty的輸出,在之后的使用中想要將一些命令輸入到終端顯示,就可以手動:

    <some_cmd> >&3

以上的方案更詳細的展示可見這個答案:

『如何將輸出同時寫到日志文件和console』

這篇文章實際產生於這個答案。從這個答案出發,補充了各類的背景知識,最后充分理解也自行寫出了答主的方案。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM