一般常見的方式是把標準輸出 (stdout) 訊息跟標準錯誤 (stderr) 訊息全部都導進一個檔案裡面,例如以下指令:
$ sudo fdisk -l >fdisk.log 2>&1
如果是寫在一個 Shell Script 的檔案裡面,就可以寫成像是下面這樣:
#!/bin/sh exec >fdisk.log # 0 (stdin) 1 (fdisk.log) 2 (stderr) exec 2>&1 # 0 (stdin) 1 (fdisk.log) 2 (fdisk.log) sudo fdisk -l
但是其實我們也可以使用更複雜的 Redirection,從 bash need STDOUT+STDERR in log, and STDERR to its normal destination 改出來的例子:
$ ((sudo fdisk -l 3>&1 1>&2 2>&3- | tee /dev/fd/2) 3>&1 1>&2 2>&3-) | cat >fdisk.log
這個例子的結果是將標準輸出訊息跟標準錯誤訊息都導進 fdisk.log 裡面,然後將標準錯誤訊息顯示出來。
但是它做了什麼事情?
首先是
sudo fdisk -l 3>&1 1>&2 2>&3-
如果直接用 Shell Script 檔案來寫,會看起來像是這樣:
#!/bin/sh exec 3>&1 # 0 (stdin) 1 (stdout) 2 (stderr) 3 (stdout) exec 1>&2 # 0 (stdin) 1 (stderr) 2 (stderr) 3 (stdout) exec 2>&3- # 0 (stdin) 1 (stderr) 2 (stdout) 3 (closed) sudo fdisk -l
看起來像是
`sudo fdisk -l` --> stdout ` '-> stdout | X `-> stderr ' `-> stderr
它將標準輸出訊息跟標準錯誤訊息互換了,接下來
| tee /dev/fd/2會收到 pipe 符號前面傳來的標準輸出訊息也就是 `sudo fdisk -l` 的 2 (stdout) 會變成 `tee` 的 0 (stdin),然後 `tee` 會將其內容導到 `tee` 的 2 (stderr) 並且顯示在 `tee` 的 1 (stdout) 於是乎 `sudo fdisk -l` 的標準輸出訊息跟標準錯誤訊息都會被導到 stderr 而標準錯誤訊息則被導到 stdout
看起來像是
`tee` `sudo fdisk -l` --> stdout ` '-> stdout --> stdout | X `-> stderr `-> stderr ' `-> stderr
接下來再經歷一次的標準輸出訊息跟標準錯誤訊息互換
((...) 3>&1 1>&2 2>&3-)
看起來像是
`tee` `sudo fdisk -l` --> stdout -> stdout --> stdout ` '-> stdout | ` ' | X | X `-> stderr ' `-> stderr `-> stderr ' `-> stderr --> stdout
從最後一張圖就可以看出最後的兩個 stdout 分別來自於 `sudo fdisk -l` 的 stdout 跟 stderr 而最後的一個 stderr 還是來自於 `sudo fdisk -l` 的 stderr
最後一步就是透過 `| cat >fdisk.log` 將兩個 stdout 都導進 fdisk.log 檔案就大功告成啦!:D
1 則留言:
強 ^_^
張貼留言