將輸出重定向到檔案是否會對該檔案套用鎖定?

將輸出重定向到檔案是否會對該檔案套用鎖定?

如果我有一個命令

$ ./script >> file.log

被呼叫兩次,第二次呼叫發生在第一個呼叫結束之前,會發生什麼事?

第一次呼叫是否獲得輸出檔的獨佔鎖?如果是這樣,第二個腳本在嘗試寫入時是否會失敗,或者 shell 是否接受輸出(允許腳本結束)並拋出錯誤?

或是日誌檔案是否被寫入兩次?

答案1

Unix 系統整體避免強制鎖。在某些情況下,核心會鎖定檔案以防止使用者程式修改,但如果檔案只是由另一個程式寫入,則不會。沒有 UNIX 系統會因為程式正在寫入檔案而鎖定檔案。

如果您希望腳本的並發實例不互相打擾,則需要使用明確鎖定機制,例如flock lockfile

當您開啟檔案進行追加時(確實>>如此),每個程式都保證始終寫入檔案的末端。因此,多個實例的輸出永遠不會互相覆蓋,如果它們輪流寫入,它們的輸出將與寫入的順序相同。

可能發生的壞事是,如果其中一個實例寫入了多個輸出區塊並期望它們一起輸出。在一個實例的連續寫入之間,其他實例可以執行自己的寫入。例如,如果實例 1 寫入foo,然後實例 2 寫入hello,然後只有實例 2 寫入bar,則該檔案將包含foohellobar.

當進程呼叫系統呼叫時,它會有效地寫入檔案write。對 的呼叫write是原子的:每次呼叫都會write寫入不會被其他程式中斷的位元組序列。單次呼叫有效寫入的資料量通常有限制write:對於較大的大小,僅寫入資料的開頭,應用程式必須write再次呼叫。此外,許多程式執行緩衝:它們在記憶體區域中累積數據,然後將這些數據寫入一個區塊中。某些程式在完成行或其他有意義的分隔後會刷新輸出緩衝區。使用此類程序,您可以期望整行不間斷,只要它們不太長(最多幾千位元組;這取決於作業系統)。如果程式不在有意義的位置刷新,而僅根據緩衝區大小進行刷新,您可能會看到一個實例中的4kB,然後是另一個實例中的4kB,然後又是第一個實例中的4kB,依此類推。

答案2

由於您使用的是>>,這意味著附加,因此每個實例的每一行輸出都將按照其發生的順序附加。

如果您的腳本輸出1\n5\n每次列印之間有 1 秒的延遲,且實例 2 在 2.5 秒後啟動,您將得到以下結果:

1
2
1
3
2
4
3
5
4
5

所以回答你的問題:不。

相關內容