Skip to content

Zeroplex 生活隨筆

軟體開發、伺服器和生活瑣事

小 縮小字型大小。 中 重設字型大小。 大 放大字型大小。

標籤: Bash

xargs -P 在 stdout 可能會遇到 race condition

Posted on 2016 年 2 月 4 日2021 年 3 月 12 日 By 日落 在〈xargs -P 在 stdout 可能會遇到 race condition〉中尚無留言

爬 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 … (暈)

Tags:Bash, Linux

特定情況下 PHP 可以比 awk 還要快

Posted on 2015 年 11 月 10 日2021 年 3 月 12 日 By 日落 在〈特定情況下 PHP 可以比 awk 還要快〉中尚無留言

因為工作上的需要,會需要將 HTTP log 抓出來做統計,所以會遇到類似下方的 RESTful path:

GET /user/123/bio HTTP/1.1 ...
GET /user/456/bio HTTP/1.1 ...

如果取完整的 path 則無法辨別後端到底是使用哪一個 API,所以使用 awk 的 regex 辨識後 mapping 到 API 名稱上。寫完以後的 awk script 大約有 300 行左右,一份 log 大概要花 2 分鐘左右。

後來經高人指點,PHP 的 native library 好歹也是 C++ 寫的,理論上不會太慢,於是用 PHP 的 preg_match() 將相同的邏輯寫了一次。同一份 log 使用 PHP 來 parse 大約只需要 1 分 32秒。

另外 PHP 預設會載入已安裝的 extensions (mysql, mcrypt …),既然只用到 native library 的話,其實這些也可以去掉不要用。改為「php -n」不載入任何 extension 再執行時,速度又快了一些,只要約 1 分鐘。

PHP 其實還有一些可以繼續調整的東西,像是把資料放在陣列裡面做搜尋時,如果把資料存成 array index 並使用 array_key_exists() 方式去判斷,會比 in_array() 還要更快 [Ref]。

Tags:Bash, PHP

寫 shell script 的一些平行處理工具

Posted on 2015 年 9 月 16 日2021 年 3 月 12 日 By 日落 在〈寫 shell script 的一些平行處理工具〉中有 4 則留言

最近在處理數十 TB 的 HTTP server log 有感,記錄一些可以拿來做分散式運算的工具以及語法 (參數)。

pigz

gzip 一直是你的好工具,特別是儲存空間放在網路上時,可以大幅的減少讀取、寫入資料時所需要的 throughput。不過 gzip 一次只會用到一個 CPU core 壓縮資料,所以有人寫了 pigz ,在壓縮時建立多個 thread 同時運算。

還有不少針對 gz 的工具可以使用,像是:zcat、zgrep 和 zless (這超神奇,其實打 less 好像就會自動偵測是不是 gz 了  XD)

parallel

之前的筆記參考一下即可。

sort

排序大量資料也是會耗掉相當多的時間,幸好 sort 內建平行運算功能,只要加個參數即可。

$ sort --parallel=8 -S 4G unsort.list > sorted.list

「–parallel」可以指定要同時多少資源做排序,而「-S」則是設定要使用多大的記憶體來做排序。

xargs

感謝 Joe Horn 和 Wen-Shih Chao 提供指點,xargs 也有 parallel 的功能。使用「-P」參數就可以讓 xargs 自動做平行處理。

ls *.log | xargs -P 8 grep PATTERN

目前最常用的是這幾個,其他的就待以後用到慢慢補上。若有更好的做法也歡迎分享~

Tags:Bash, Linux, 分享, 資訊學習

多核心主機搭配 GNU parallel

Posted on 2015 年 8 月 3 日2021 年 3 月 12 日 By 日落 在〈多核心主機搭配 GNU parallel〉中尚無留言

假如要將 apache log 中,包含某個 pattern 的記錄找出來,寫起來大概會像這樣子:

cat apache*.log | awk -f log-parser.awk

舊電腦就是放著一個檔案一個檔案慢慢跑,沒什麼問題。若新電腦現在不少都是多核心,看個 parser 慢慢跑,但是剩下的 3 個 CPU core 和 disk 都悠哉沒事做,感覺在浪費時間。

parallel 專門設計來讓 script 可以同時並行運作,使用電腦資源來節省時間的好工具。

假設今天 awk 非常吃 CPU 使用量 (規則較為複雜),處理一個檔案會花上很多 CPU 時間,則可以將 log 中的內容分散給多個 CPU 同時處理:

cat apache*.log | parallel --pipe awk -f log-parser.awk

此時,parallel 偵測到有 4 CPU cores,則會自動將 $FILE 內容分批轉送給 awk 處理 (一行為一個單位),這樣能讓 4 個 CPU 同時跑 awk 解析 log 內容。

不過以一行為一個單位轉送資料給 awk,也會耗掉一些運算資源,可以透過 –block 來要求 parallel 多少資料當作一個單位來轉送資料。以下假設一次送 10MB 的資料給 awk 處理:

cat apache*.log | parallel --pipe --block 10M awk -f log-parser.awk

倘若今天 awk 的要處理的東西並不複雜,可以輕鬆解決掉,上面的寫法反而會讓 CPU 閒閒沒事做,不如就讓一個 awk 負責處理一個檔案,且多個檔案同時進行。此時就可以讓檔案處理的部分轉交給 awk:

parallel --pipe -u --block 10M awk -f log-parser.awk ::: apache*.log

備註:parallel 預設會在所有工作執行結束才輸出結果,若要讓 parallel 即時將結果印出,則可加上參數「-u」。

另外一點要注意的是,parallel 預設會使用所有的 CPU 來處理工作,這在多人共同使用的主機上並不是一件好事,一跑下去大家都不用做事了。所以若在共用環境上請記得加上 -j (jobs) 參數,來限制 parallel 不要用掉所有的系統資源。

Reference:

  • GNU Parallel Tutorial
  • How to write multicore sorting using GNU Parallel
  • Use multiple CPU Cores with your Linux commands — awk, sed, bzip2, grep, wc, etc.
  • Using Multiple CPU Cores With Command Line Tools

Tags:Bash, Linux, 資訊學習

在 grep 搜尋「-」符號

Posted on 2014 年 1 月 15 日2021 年 3 月 12 日 By 日落 在〈在 grep 搜尋「-」符號〉中尚無留言

用 grep 搜尋檔案中出現的文字,通常會這樣寫:

$ grep STR fileToSeatch

不過當要搜尋的字串有特出符號,像是「-」,就會出現錯誤訊息:

$ grep "->getVal()" *
grep: invalid option -- '>'

原因是 grep 將「-」開頭的字串視為命令選項 (command option),去尋找「>get()」這個選項,而這個選項並不存在,所以導致錯誤。

在命令輸入前加上「–」,表示之後的參數都當作一般輸入而非選項 (end of option):

$ grep -- "->getVal()" *

要搜尋的字串,就算沒有空白,也建議用引號括起來。像是「>」、「&」等,沒加上引號會在 bash 解析時就發生錯誤:

$ grep > *  # shoud be: grep ">" *
bash: *: ambiguous redirect
Tags:Bash, Linux

文章分頁

上一頁 1 ... 4 5 6 下一頁

其他

關於我  (About me)

小額贊助

  文章 RSS Feed

  留言 RSS Feed

Apache AWS Bash C/C++ Docker FreeBSD GCP Git Google Java JavaScript Laravel Linux Microsoft MSSQL MySQL Nginx PHP PHPUnit PostgreSQL Python Qt Ubuntu Unix Vim Web Windows WordPress XD 作業系統 分享 好站推薦 專題 攝影 新奇搞笑 新聞 旅遊 生活雜記 程式設計 網路架站 網頁設計 資訊學習 資訊安全 遊戲 音樂


創用 CC 授權條款
本著作係採用創用 CC 姓名標示-相同方式分享 4.0 國際 授權條款授權.