爬 log 發現 log 格式不正確,而且還是經常發生,而手動追蹤時又找不到錯誤在哪裡:
find . -name '*2016-01*.log.gz' | xargs -I'{}' -P 4 zgrep keyword {} | awk ...
做了測試以後才發現 xargs -P 時,各個 process 只要有 stdout 就會和其他 process 打架,造成資料還沒寫完就被其他 process 插單,導致最後出來的資料不正確。
先建立二個檔案,儲存不同的二個資料。
0.test.log (每行 50 字):
.................................................
.................................................
.................................................
....
1.test.log (每行 50 字):
1111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111
...
接下來使用 xargs 來 echo 這二個檔案內容:
find . -name '*test.log' | xargs -I'{}' -P 2 cat {} > output.xargs.log
接下來寫個 script 來檢查 output.xargs.log 的內容是否都正確:
for LINE in `cat output.xargs.log `; do
if [ 50 -lt ${#LINE} ]; then
echo $LINE
fi
done
結果會發現 output 有一行超過 50 個自得情況發生:
111111111111111111111111111111111111.................................................
而相同的情況下,parallel 就不會有相同的情況發生:
find . -name '*test.log' | parallel -j 2 cat {} > output.xargs.log
原因是 parallel 會將 jobs (process) 的 output 先 buffer 起來,等到整個 job 都結束以後在一起送到 stdout。若使用上述的範例改用 parallel 的操作來測試的話,可以發現不同 job 的 output 有被完全區隔開來,沒有混在一起:
...
.................................................
.................................................
.................................................
1111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111
...
總之,以後用到 xargs -P 時,要小心 race condition … (暈)