Try   HackMD

使用 curl--parallel

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
curl 指令就像是電腦系統上的瑞士刀,可靠、好用且無所不在。除了 Linux 和 macOS 系統內有提供,Win10 也在 2017 年後內建 curl.exe。時至今日,你可以說在任何平台的系統都能見到他。隨著 RESTful API 標準興起,很有可能你呼叫第一個 API,就是透過 curl 指令完成

curl2019 的 7.66 版 迎來新功能 --parallel,遊戲規則產生變化,我們不需再藉由外部工具如 xargsGNU Parallel,即可達成並行化 (concurrency) 工作。curl 開發者持續新增和修正相關功能,建議若要使用此功能直接選用最新版curl

本篇撰文者為系統管理員,測試環境為 Bash 搭配 curl 7.84.0
透過 server 的 BMC 提供的 redfish api (類似 restful api),演示 curl 的 --parallel 功能
本文連結: https://hackmd.io/@kmo/curl_parallel
任何回饋歡迎留言在此篇 hackmd :)

實例演示

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
情境說明

  • 管理的 server 分 3 個群組,每群有 10 台電腦,共 30 台電腦
# 群組 1 的電腦 IP 範圍 10.50.1.[1-10] (也就是 10.50.1.1, 10.50.1.2, 10.50.1.3, ..., 10.50.1.9, 10.50.1.10) # 群組 2 的電腦 IP 範圍 10.50.2.[1-10] (也就是 10.50.2.1, 10.50.2.2, 10.50.2.3, ..., 10.50.2.9, 10.50.2.10) # 群組 3 的電腦 IP 範圍 10.50.3.[1-10] (也就是 10.50.3.1, 10.50.3.2, 10.50.3.3, ..., 10.50.3.9, 10.50.3.10)
  • 現代 server 的 BMC(Baseboard Management Controller) 服務,幾乎都有提供 redfish api (類似 restful api)
  • 使用 curl 指令,透過 api 取得單 1 台電腦 BIOS 設定,並存成檔案
    以 IP 為 10.50.1.1 的 server 為例
# 不同硬體廠牌的 api 都略有差異 # 實際應用務必查詢自己機器的 redfish 說明文件,或是詢問硬體 vendor curl -sku usr:pw 'https://10.50.1.1/redfish/v1/Systems/1/bios' -o 10.50.1.1.bios.conf

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
問題

  • 請使用上述 curl 指令範例,備份 30 台 server 的 BIOS 設定檔

1. Bash 的 nested loop

  • 此題直觀解法,就是透過 bash 腳本的 nested loop 完成
#!/bin/bash for ii in {1..3}; do for jj in {1..30};do curl -sku usr:pw "https://10.50.$ii.$jj/redfish/v1/Systems/1/bios" -o "10.50.$ii.$jj.bios.conf" done done
  • 但此方法效率不夠好,實際測試約花 47 秒完成 😴

2. 匹配多個 URL

  • 透過 curl 的 匹配 URL 語法(URL globbing),可以一次匹配多個 URL 並執行 ,簡化上述 bash 腳本成為一行指令
curl -sku usr:pw 'https://10.50.[1-3].[1-10]/redfish/v1/Systems/1/bios'
  • 題目希望把 bios 設定檔備份下來,但 URL 結尾名稱都是 bios,若使用 -O, --remote-name 直接存檔,檔名相同(都叫 bios)會彼此覆蓋,最後只存到 1 個 bios 檔案
  • 因此 curl 開發者也考慮到此情況,所以 URL 匹配語法支援輸出變數,可改寫為
# 檔名的 `#1` 對應第 1 個匹配語法 `[1-3]` # 檔名的 `#2` 對應第 2 個匹配語法 `[1-10]` curl -sku usr:pw 'https://10.50.[1-3].[1-10]/redfish/v1/Systems/1/bios' -o '10.50.#1.#2.bios.conf'
  • 上述指令尚未使用並行化處理,但執行效率已經大幅改善,實際測試約花 15 秒完成 👌

3. 使用 --parallel

  • 當 request 的 URL 是不同來源,curl 開發者建議可以使用 --parallel 並行化處理
  • 除此之外還有 2 個 option 可搭配使用
    • --parallel-immediate: curl 預設會儘可能重複使用已建立的連線(multiplex),可加速處理需求並減少負載,不過當 URL 是不同來源,那 multiplex 效果就不大。使用此選項會把考慮 multiplex 的因子權重降低,儘可能開啟新連線。本文的實例就很適合使用
    • --parallel-max: 預設是 50 個並行工作,可以調整自己適用的情境
  • 採用 --parallel 一次進行 30 個並行連線,此時指令為
curl --parallel --parallel-immediate --parallel-max 30 \ -sku usr:pw \ 'https://10.50.[1-3].[1-10]/redfish/v1/Systems/1/bios' -o '10.50.#1.#2.bios.conf'
  • 並行化處理後,實際測試僅花 0.5 秒完成 👏

上述測試時間整理

問題解法 實際測試
Bash 的 nested loop 47 秒
匹配多個 URL (curl globbing) 15 秒
使用 curl 的 --parallel 0.5 秒

取得回應資訊

  • 當處理的 URL request 數量多,難免會遇到對方 server 忙碌或當機,此時需要取得回應資訊判斷。可以透過 --write-out 取得 http 的 response_code,並且搭配印出 url 對照。此時指令改為
curl --write-out 'code %{response_code} url %{url}\n' \ --parallel --parallel-immediate --parallel-max 30 \ -sku usr:pw \ 'https://10.50.[1-3].[1-10]/redfish/v1/Systems/1/bios' -o '10.50.#1.#2.bios.conf'
  • 執行時可以看到如下資訊印出在螢幕。由於是並行處理,所以並不會照數字順序執行。仔細看會注意最後一行 10.50.3.3 的回應是 000,代表10.50.3.3有不預期狀況發生
code 200 url https://10.50.1.1/redfish/v1/Systems/1/bios code 200 url https://10.50.1.4/redfish/v1/Systems/1/bios code 200 url https://10.50.1.9/redfish/v1/Systems/1/bios ... 略 ... code 200 url https://10.50.3.10/redfish/v1/Systems/1/bios code 200 url https://10.50.3.9/redfish/v1/Systems/1/bios code 000 url https://10.50.3.3/redfish/v1/Systems/1/bios

讓 curl 更可靠

  • 安全性: 上述例子透過 -u 後面加 usr:pw 指定帳號密碼,這種方式在 linux 系統上是非常不安全的行為,若你使用的電腦為多人登入使用,此時其他用戶下 ps -ef | grep curl 之類指令,即可看到你使用 curl 指定的參數(當然包含密碼)。此時務必參閱 curl --config 方式,至少把密碼包在特定檔案
  • 可靠性: 若要透過 curl 提供穩定的服務,那勢必得考慮錯誤處理,當 timeout 或 fail 等不符合預期的回傳值,要怎麼處理。此時可以參考 manpage 關於 retry or fail 等關鍵字的 option。當然最快方式參考 github or stackoverflow 網友們的腳本,並依據自己情境調整

後記

  • curl 是系統管理老朋友,近年以驚人速度持續更新,開發者在 7.66 release 的 blog 畫這張圖,來表明 curl 更新次數以指數成長。期待不久將來,還有來自這位老朋友的新消息 😀
    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →

參考連結

Everything curl: curl 開發者寫的手冊,讚
curl 的 manpage: 網頁上查詢 option 好用
curl 的 globbing 範例: stackoverflow 網友的範例
curl 的 parallel 範例: stackoverflow 網友的範例


Published on HackMD

https://hackmd.io/@kmo

作者

kmo

授權許可

CC BY-NC-SA 4.0