🤗

stdout仕様の謎みが深いcurlの調査

2021/07/03に公開

こんにちは(๑╹ω╹๑ )

Curlのstdoutの謎仕様?を最近業務中に知りました!笑

えっ?それ標準出力じゃないの???😇

事の発端はcertbotでdns challenge時に"--manual-auth-hook"内で行っていた、
curlの挙動に不信感を覚えたことでした😥

Let's Encryptの証明書を発行するプロセスでDNS Challengeを採用していました。
その際に下記のようなTXTレコードを編集するAPIを叩いておりました

curl -i -X PUT https://hoge.com/api/record/txt \
  -data "{\"value\":\"fooooo\"}" >> response_headers.log

もちろん下記の結果を望んでおりそのようになっておりました

  • レスポンスヘッダーのHTTPステータスコードは200になっている
  • API側の処理も正常に走っており何ら問題は無い

しかし一点気になったのは、manual-auth-hookの実行結果として標準エラー(stderr)が確認されたよというログが残っていたことです。

確認してみるとそこにはcurlのプログレスメータのログがありました😱
(※ -s オプションでstderrの出力を無効化することで解消

調査環境

ライブラリ バージョン
curl 7.65.1
libcurl 7.65.1
nghttp2 1.29.0

※調査に依存するライブラリのみ記載

何の謎が深いの? 🤔

HTTPリクエストの状況を出力するプログレスメーターがstderr扱いになっていたこと。。。
HTTPリクエストの結果(レスポンスヘッダーのステータスコードが200かどうか)に関わらずに標準エラー扱いになるのは謎が深いと感じたためです(※あくまで私の主観です

そもそも

curl側の仕様を疑ったのは、確認した当時のshellスクリプトには他にもstdoutが存在していたこと。
その中でプログレスメータのログのみstderr扱いされていたこと。
からでした。
このような事象であったため、certbot側の挙動というよりもcurl側の仕様に着目したほうが良いのではと思い調査しました。

curlがプログレスメータを出力するとき

  • パイプ or リダイレクトで他の処理系で制御するとき
  • その他(未調査

実際に確認した

まずは標準出力と標準エラーを選別する

$ curl "https://zenn.dev" > stdout.log 2> stderr.log

stderr.logの中身を確認してみる

$ cat stderr.log
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  104k  100  104k    0     0   429k      0 --:--:-- --:--:-- --:--:--  429k

やっぱり標準エラーだった。。。😱

プログレスメータは標準エラー扱いになる仕様を知りました笑

まとめ

当たり前のことなのか分かっていなかったので新鮮みが深く興奮しました笑

あくまで予測ですが、
「プログレスメータはユーザ(開発者)が本来欲しい情報(レスポンスのヘッダやボディ)とは違う区分なために選別しやすい仕様を求めて標準エラーとする」
ような背景があったのかなぁと考えました

その辺りはまだ未調査なので歴史的背景とかもググって調べてみます!!

Discussion