2012-10-01 82 views
0

我無法將標準錯誤發送到標準輸出。我打算把它放在cron中,但現在我只是手動運行。將標準錯誤發送到標準輸出不起作用

/home/backups/backup_scripts/backup.sh 2>&1 >> /var/log/backups/backup.log 

我希望在日誌文件將包含被印到標準輸出的任何消息,但日誌文件只顯示標準輸出和控制檯輸出顯示錯誤。

我在這裏做錯了什麼?

回答

2

發生這種情況,因爲重定向的順序。 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 

所以現在輸出和錯誤都去文件。

+0

我真的不明白這一點。如果它從左向右讀,那麼你建議的命令是不是不起作用?不是>>將標準重定向到文件?如果是這樣,那麼我需要確保我第一次有標準錯誤重定向第一...在這之前呢? – Brian

+0

@Brian,請參閱編輯。讓我知道如果它仍然不清楚。 –

+0

嗯...當時,STDOUT的當前位置是終端。所以它將STDERR重定向到STDOUT,但它仍然只是終端。但是,那麼>>應該重定向終端的STDOUT,它現在包括我的bash腳本中的STDERR不是嗎? – Brian

2

重定向的順序很重要。你應該將其更改爲:

/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

相關問題