我無法將標準錯誤發送到標準輸出。我打算把它放在cron中,但現在我只是手動運行。將標準錯誤發送到標準輸出不起作用
/home/backups/backup_scripts/backup.sh 2>&1 >> /var/log/backups/backup.log
我希望在日誌文件將包含被印到標準輸出的任何消息,但日誌文件只顯示標準輸出和控制檯輸出顯示錯誤。
我在這裏做錯了什麼?
我無法將標準錯誤發送到標準輸出。我打算把它放在cron中,但現在我只是手動運行。將標準錯誤發送到標準輸出不起作用
/home/backups/backup_scripts/backup.sh 2>&1 >> /var/log/backups/backup.log
我希望在日誌文件將包含被印到標準輸出的任何消息,但日誌文件只顯示標準輸出和控制檯輸出顯示錯誤。
我在這裏做錯了什麼?
發生這種情況,因爲重定向的順序。 2>&1
的意思是「將標準錯誤重定向到當前的標準輸出的位置」。它們從左到右進行處理,以便將第一個標準錯誤重定向到當前標準輸出(仍是終端),然後將標準輸出重定向到文件。如果您將訂單切換爲讀取
/home/backups/backup_scripts/backup.sh >> /var/log/backups/backup.log 2>&1
它應該做你想做的。如果你的shell是bash,它有一個快捷方式來同時重定向標準輸出和標準錯誤:command &> file
將它們重定向到一個文件並且command &>> file
將兩個文件都附加到一個文件中。此命令依賴關係也在bash手冊中提到
請注意,重定向的順序很重要。例如,命令
ls > dirlist 2>&1
指示標準輸出和標準誤差到文件dirlist,而命令
ls 2>&1 > dirlist
指示只有標準輸出到文件dirlist,因爲標準誤差爲 複製從標準輸出之前的標準輸出重定向到dlist的 。
我認爲文件描述符和重定向的工作方式存在一些誤解。內核有一個包含文件偏移量,狀態標誌和文件本身名稱的系統上所有打開文件的大表。然後每個進程都有一個表,將文件描述符編號映射到此全局表中的條目。
之前的任何重定向發生全局表可能是這個樣子
A: TERMINAL
和進程表看起來像
0: A
1: A
2: A
因爲描述數字0,1,和2標準輸入,標準輸出,和stderr分別。
然後處理2>&1
重定向。這將更改進程表,以便2包含與1相同的全局條目。但是,它們已經相同,因此沒有任何反應。
當>> /var/log/backups/backup.log
重定向被處理。首先,文件被打開並分配到文件描述符3在進程表使表看起來像
A: TERMINAL
B: /var/log/backups/backup.log
和
0: A
1: A
2: A
3: B
那麼標準out變成指向新打開的文件(好像1>&3
被完成),從而進程表現在
0: A
1: B
2: A
3: B
注意,2(錯誤)仍然指向該終端。
當重定向以其他順序完成時,>> /var/log/backups/backup.log
之後的表看起來相同。
0: A
1: B
2: A
3: B
然後2>&1
重定向改變什麼2點給
0: A
1: B
2: B
3: B
所以現在輸出和錯誤都去文件。
重定向的順序很重要。你應該將其更改爲:
/home/backups/backup_scripts/backup.sh >> /var/log/backups/backup.log 2>&1
這個標準輸出重定向到/var/log/backups/backup.log
,然後重定向標準錯誤到標準輸出(這是進入該文件)。
您還可以使用較短的形式:
/home/backups/backup_scripts/backup.sh &>> /var/log/backups/backup.log
&>>file
是語義上等同於>>file 2>&1
我真的不明白這一點。如果它從左向右讀,那麼你建議的命令是不是不起作用?不是>>將標準重定向到文件?如果是這樣,那麼我需要確保我第一次有標準錯誤重定向第一...在這之前呢? – Brian
@Brian,請參閱編輯。讓我知道如果它仍然不清楚。 –
嗯...當時,STDOUT的當前位置是終端。所以它將STDERR重定向到STDOUT,但它仍然只是終端。但是,那麼>>應該重定向終端的STDOUT,它現在包括我的bash腳本中的STDERR不是嗎? – Brian