こんにちは、山田ハヤオです。
受験も無事に終わったので、最近はGoやNodeJSの勉強をしています。
そんなモダンな言語は放っておいて、今日も懲りずにシェルスクリプトの話題です。
シェルスクリプトでcurlを正しく使えていますか???
シェルスクリプトでcurlを使うとき、おそらく脳死でこう書いてる人が多いんじゃないかと思います。
my_url="https://example.com/something"
curl "${my_url}"
しかしこの書き方には問題点がいくつかあります。
- リダイレクトされない
- エラーハンドリングができない
- 不要な出力が存在する
順番に見ていきます。
環境
今回の記事の内容は以下の環境でテストしています。
リダイレクトされない
例えば短縮URLなどを使用している場合、そのURLは元のURLにリダイレクトされます。
(ここでいうリダイレクトはシェルスクリプトのリダイレクトではないです)
HTTP的にはリダイレクト時には300番台のコードが返されますが、curlはデフォルトではこのリダイレクトを処理してくれません。
試しに、シンプルな実装のURL短縮を用いて実験してみます。
Googleのトップページへのリンクの短縮としてhttps://1lil.li/l/IIII1I11iI1を用意しました。
これをcurlすると
リダイレクトされるという情報のみが返され、リダイレクト先の情報は取得してくれません。
解決方法
この挙動を改善するには-L
を利用します。
今度は適切にGoogleのコードを取得できました。
エラーハンドリングされない
シェルスクリプトでのエラーハンドリングは、コマンドの返り値を用いて行います。
シェルスクリプトはデフォルトではコマンドが異常終了してもそのまま処理を続行します。
しかし、先頭にset -e
と記述して設定を変更することでシェルの設定を変更し、コマンドの異常終了時にスクリプトの実行を停止させます。
試しに、不正なURLを用いてエラーハンドリングが行われるか確認してみましょう。
#!/usr/bin/env bash
set -e
curl -L "https://dyama.net/noexist"
echo "正常に実行されました"
上のスクリプトで叩いているURLは、存在しないパスを参照しているため404を返します。
しかし実際に実行してみると
curlはコード0で正常終了を返し、スクリプトの動作はそのまま続行しています。
解決方法
これを解消するには-f
を利用します。
#!/usr/bin/env bash
set -e
curl -f -L "https://dyama.net/noexist"
echo "正常に実行されました"
これで、curlがhttpのステータスコードに応じて異常終了してくれるため、シェルスクリプト側でエラーハンドリングできるようになります。
不要な出力が存在する
curlで出力先を指定すると、strerrには経過情報が表示されます。
この経過情報を消す方法はいくつかあります。
strerrを破棄する
真っ先に思いつく方法ですが、エラー情報まで見えなくなってしまうのでおすすめしません。
コードも冗長なので、後述する方法を使いましょう。
-sオプションを利用する
ネットを検索して一番出てくるのはこれだと思います。
2> /dev/null
よりも短く記述できるのでこっちを使いましょう。
ですが、これもエラー情報が見えなくなってしまうので完全に独自でエラーハンドリングする場合を除いて使うべきではありません。
–no-progress-meter を使う
エラー出力を残しつつプログレスバーのみ削除してくれるオプションです。
まとめ
これらをまとめると最終的にはこのようになります。
my_url="https://example.com/something"
curl --no-progress-meter -L -f "${my_url}"
最後のまとめの一言が何も思いつかないので、これで終わります。
それでは、また今度。
コメント