curl コマンド 使い方メモ

  • 642
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

はじめに

「最近、curlが楽しい」
というわけで、最近、curlでPOSTしたりDELETEしたりcookieからSessionを読み込んだりと触れ合う機会が多かったので、その時知ったものを備忘録も兼ねてまとめました。
なるべく実行コマンドとその結果の出力をセットで書くようにしています。

curlコマンドは便利

http://curl.haxx.se/

curlは便利です。
APIと触れ合っていると、 手軽に HTTPリクエストしたくなる色んなシーンに出会います。

「あれ? サーバー死んでる?」
「思ってたレスポンスと違うな、何が返されているんだ?」
「認証必須にしたんだけど、うっかり抜け道ないよね?」
「さくっとPOSTしてテスト用にデータ準備したいんだけど...」
...etc

こういった、とりあえず生で、くらいのテンションでHTTPリクエストしたいなら、curlは有力な選択肢の一つと思います。

もちろん、本格的な確認やデータが欲しいなら、
ブラウザのデベロッパツールや、Burp suiteといったリッチなツールを使う方がいいかもしれません。

curlの実験準備

今回はJenkinsさんのAPIを叩くことにします。

curlのインストール

最近のLinuxには初めからcurlがインストールされていると思いますが、ない場合はaptyum など、使用しているディストリビューションに沿った方法でインストールして下さい。

今回使用したcurlバージョン

7.38.0

$ curl --version
curl 7.38.0 (x86_64-pc-linux-gnu) libcurl/7.38.0 OpenSSL/1.0.1k zlib/1.2.8 libidn/1.29 libssh2/1.4.3 librtmp/2.3

Jenkinsのインストール

こちらも、aptyum などで適当にインストールします。
実験用に幾つか設定をしたり、ジョブを作りますが、その都度、簡単に説明することとします。

jqのインストール

jq (https://stedolan.github.io/jq/) は、jsonをうまいことパースしてくれるコマンドです。
今回は、Jenkinsのレスポンスをちょっと見やすくするためだけにjqを使用しているので、ここでは特に説明はしません。

GET

ただGETリクエストを投げたいだけならば、何もオプションは要りません。

$ curl localhost:8080/api/json | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   371  100   371    0     0  53489      0 --:--:-- --:--:-- --:--:-- 61833
{
  "assignedLabels": [
    {}
  ],
  "mode": "NORMAL",
  "nodeDescription": "ノード",
  "nodeName": "",
  "numExecutors": 2,
  "description": null,
  "jobs": [],
  "overallLoad": {},
  "primaryView": {
    "name": "すべて",
    "url": "http://localhost:8080/"
  },
  "quietingDown": false,
  "slaveAgentPort": 0,
  "unlabeledLoad": {},
  "useCrumbs": false,
  "useSecurity": false,
  "views": [
    {
      "name": "すべて",
      "url": "http://localhost:8080/"
    }
  ]
}

Jenkinsの一番トップのAPIを叩いています。
jq . で、Jsonを見やすい形に整列しています。
もっともJenkinsでは、jsonjson?pretty=true に変えればほぼ同じ出力になります。

ファイルに出力 -o -O

-o オプションでファイルに出力できます。

$ curl localhost:8080/api/json -o response
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   371  100   371    0     0  68538      0 --:--:-- --:--:-- --:--:-- 74200
$ cat response | jq .
{
  "assignedLabels": [
    {}
  ],
  "mode": "NORMAL",
  "nodeDescription": "ノード",
  "nodeName": "",
  "numExecutors": 2,
  "description": null,
  "jobs": [],
  "overallLoad": {},
  "primaryView": {
    "name": "すべて",
    "url": "http://localhost:8080/"
  },
  "quietingDown": false,
  "slaveAgentPort": 0,
  "unlabeledLoad": {},
  "useCrumbs": false,
  "useSecurity": false,
  "views": [
    {
      "name": "すべて",
      "url": "http://localhost:8080/"
    }
  ]
}

-O だと、リクエスト先の名前でファイルを保存します。

$ curl localhost:8080/api/json -O
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   371  100   371    0     0  64985      0 --:--:-- --:--:-- --:--:-- 74200

# 先ほど保存した response と同じ内容か比較
$ diff json response; echo $?
0

Progress Meter

curlはデフォルトで、↓のような転送情報をコンソールに出力します。

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   371  100   371    0     0  53489      0 --:--:-- --:--:-- --:--:-- 61833

-# オプションを使うと、プログレスバーのような表記に変更できます。

$ curl localhost:8080/api/json -o response -#
######################################################################## 100.0%

どちらにせよ、このプログレス情報を邪魔に思う日もあるでしょう。
stderrに出力されているので、/dev/nullにでも突っ込んでしまうのも手ですが、素直に-sオプションで制御します。

$ curl -s localhost:8080/api/json -O

ただしこの時、エラーメッセージまで消えてしまいます。
URLやPortを間違えた時に気づけないので、-Sを一緒に指定しておいた方が無難です。

# Portを間違えてしまったが、エラーメッセージがない
$ curl -s localhost:8081/api/json

# -Sの効果で、エラーメッセージが出力される。
$ curl -Ss localhost:8081/api/json
curl: (7) Failed to connect to localhost port 8081: 接続を拒否されました

HTTP Headerを確認する -I -i -v

-I で、Headerのみ取得し、出力することができます。

$ curl -I -s 'localhost:8080/api/json?'
HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-Jenkins: 1.619
X-Jenkins-Session: b34411df
Content-Type: application/json;charset=UTF-8
Content-Length: 371
Server: Jetty(winstone-2.8)

-i ならば、Respnse Header, Body 両方を出力できます。

$ curl -i -s 'localhost:8080/api/json?'
HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-Jenkins: 1.619
X-Jenkins-Session: b34411df
Content-Type: application/json;charset=UTF-8
Content-Length: 371
Server: Jetty(winstone-2.8)

{"assignedLabels":[{}],"mode":"NORMAL","nodeDescription":"ノード","nodeName":"","numExecutors":2,"description":null,"jobs":[],"overallLoad":{},"primaryView":{"name":"すべて","url":"http://localhost:8080/"},"quietingDown":false,"slaveAgentPort":0,"unlabeledLoad":{},"useCrumbs":false,"useSecurity":false,"views":[{"name":"すべて","url":"http://localhost:8080/"}]}

ただし、これはレスポンスのHttp Headerだけです。
curlでリクエストした時のHeaderも見たければ、-v が使用できます。

$ curl -v -s 'localhost:8080/api/json' | jq .
* Hostname was NOT found in DNS cache
*   Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /api/json HTTP/1.1
> User-Agent: curl/7.38.0
> Host: localhost:8080
> Accept: */*
> 
< HTTP/1.1 200 OK
< X-Content-Type-Options: nosniff
< X-Jenkins: 1.619
< X-Jenkins-Session: b34411df
< Content-Type: application/json;charset=UTF-8
< Content-Length: 371
* Server Jetty(winstone-2.8) is not blacklisted
< Server: Jetty(winstone-2.8)
< 
{ [data not shown]
* Connection #0 to host localhost left intact
{
  "assignedLabels": [
    {}
  ],
  "mode": "NORMAL",
  "nodeDescription": "ノード",
  "nodeName": "",
  "numExecutors": 2,
  "description": null,
  "jobs": [],
  "overallLoad": {},
  "primaryView": {
    "name": "すべて",
    "url": "http://localhost:8080/"
  },
  "quietingDown": false,
  "slaveAgentPort": 0,
  "unlabeledLoad": {},
  "useCrumbs": false,
  "useSecurity": false,
  "views": [
    {
      "name": "すべて",
      "url": "http://localhost:8080/"
    }
  ]
}

もっと HTTP パケットのデータを確認する --trace --trace-ascii

--trace--trace-ascii を使用すると、HTTPリクエスト・レスポンスのデータを全て dump することができます。

--trace
$ curl -sS  localhost:8080 -X POST -F "hoge=fuga" --trace trace.log -o /dev/null
$ cat trace.log  | head
== Info: Rebuilt URL to: localhost:8080/
== Info: Hostname was NOT found in DNS cache
== Info:   Trying 127.0.0.1...
== Info: Connected to localhost (127.0.0.1) port 8080 (#0)
=> Send header, 208 bytes (0xd0)
0000: 50 4f 53 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d POST / HTTP/1.1.
0010: 0a 55 73 65 72 2d 41 67 65 6e 74 3a 20 63 75 72 .User-Agent: cur
0020: 6c 2f 37 2e 33 35 2e 30 0d 0a 48 6f 73 74 3a 20 l/7.35.0..Host: 
0030: 6c 6f 63 61 6c 68 6f 73 74 3a 38 30 38 30 0d 0a localhost:8080..
0040: 41 63 63 65 70 74 3a 20 2a 2f 2a 0d 0a 43 6f 6e Accept: */*..Con

--trace の場合です。バイナリエディタとかでよく見る感じですね。

--trace-ascii
$ curl -sS  localhost:8080 -X POST -v -F "hoge=fuga" --trace-ascii trace-ascii.log -o /dev/null
$ cat trace-ascii.log  | head
== Info: Rebuilt URL to: localhost:8080/
== Info: Hostname was NOT found in DNS cache
== Info:   Trying 127.0.0.1...
== Info: Connected to localhost (127.0.0.1) port 8080 (#0)
=> Send header, 208 bytes (0xd0)
0000: POST / HTTP/1.1
0011: User-Agent: curl/7.35.0
002a: Host: localhost:8080
0040: Accept: */*
004d: Content-Length: 143

--trace-ascii の場合です。人間に優しい感じですね。

ちなみに、 --trace-time というオプションを付与すると、出力に日時が付与されるようになります。

$ curl -sS  localhost:8080 -X POST -v -F "hoge=fuga" --trace-ascii trace-ascii.log -o /dev/null --trace-time
$ cat trace-ascii.log  | head
08:01:57.605505 == Info: Rebuilt URL to: localhost:8080/
08:01:57.605768 == Info: Hostname was NOT found in DNS cache
08:01:57.610090 == Info:   Trying 127.0.0.1...
08:01:57.611293 == Info: Connected to localhost (127.0.0.1) port 8080 (#0)
08:01:57.612398 => Send header, 208 bytes (0xd0)
0000: POST / HTTP/1.1
0011: User-Agent: curl/7.35.0
002a: Host: localhost:8080
0040: Accept: */*
004d: Content-Length: 143

なお、-v --trace --trace-ascii は、どれか一つしか作用しません。これらを同時に指定した場合、最後に指定したオプションのみ有効になります。

POST

POSTリクエストを送るには、-X POST を付与します。

curl -sS -w '\n' -X POST 'localhost:8080/'

パラメータ付きPOST

POSTする際は、何らかのパラメータやデータを付与してリクエストすることが大多数だと思います。
--data またはその省略系である -d で、POSTで送信するデータを記述できます。
実際にJenkinsにPOSTし、ジョブの作成を試してみます。

# Jobを作成するPOST
$ curl -w '\n' 'http://localhost:8080/createItem' --data 'name=sample&mode=hudson.model.FreeStyleProject&Submit=OK' -XPOST

# 作成されたことを確認
$ curl -sS 'http://localhost:8080/api/json' | jq .jobs
[
  {
    "name": "sample",
    "url": "http://localhost:8080/job/sample/",
    "color": "notbuilt"
  }
]

パラメータ付きPOSTとURLエンコード

--data はURLエンコードしてくれませんので、あらかじめ自分でエンコードしておく必要があります。
試しに、上で作成したジョブ「sample」に、ファイルパラメータの設定を追加してみます。

# URLエンコード済みのパラメータを付与して、ジョブの設定を更新するPOST
$ curl -w '\n' 'http://localhost:8080/job/sample/configSubmit' --data 'json=%7b%22properties%22%3a+%7b%22hudson-model-ParametersDefinitionProperty%22%3a+%7b%22parameterized%22%3a+%7b%22parameter%22%3a+%7b%22name%22%3a+%22FileParameter%22%2c+%22description%22%3a+%22%22%2c+%22stapler-class%22%3a+%22hudson.model.FileParameterDefinition%22%2c+%22%24class%22%3a+%22hudson.model.FileParameterDefinition%22%7d%7d%7d%7d%7d%0d%0a&Submit=Save' -XPOST

# ジョブの中身を確認し、更新されていることを確認
$ curl -sS 'http://localhost:8080/job/sample/api/json' | jq .actions
[
  {
    "parameterDefinitions": [
      {
        "defaultParameterValue": null,
        "description": "",
        "name": "FileParameter",
        "type": "FileParameterDefinition"
      }
    ]
  }
]

自前でURLエンコードするのは面倒ですし、ぱっと見て何かわかりにくいです。
--data-urlencode を使うと、curlがURLエンコードしてくれるので、そのまま書いてしまうことができます。
試しに、上で追加したパラメータにDescriptionを追加してみます。

# URLエンコードはcurlに任せてPOST
$ curl -w '\n' 'http://localhost:8080/job/sample/configSubmit' --data-urlencode 'json={"properties": {"hudson-model-ParametersDefinitionProperty": {"parameterized": {"parameter": {"name": "FileParameter", "description": "Upload file to Jenkins.", "stapler-class": "hudson.model.FileParameterDefinition", "$class": "hudson.model.FileParameterDefinition"}}}}}' -d 'Submit=Save' -XPOST

# descriptionが "Upload file to Jenkins." に更新されてることを確認
$ curl -sS 'http://localhost:8080/job/sample/api/json' | jq .actions
[
  {
    "parameterDefinitions": [
      {
        "defaultParameterValue": null,
        "description": "Upload file to Jenkins.",
        "name": "FileParameter",
        "type": "FileParameterDefinition"
      }
    ]
  }
]

この時、&で複数のパラメータを定義しようとしても、肝心の&がエンコードされてしまいます。そのためSubmit=Saveは別途-dで付与しています。

ファイルをUploadするPOST

次は、POSTでJenkinsジョブをビルドしてみます。
JenkinsでPOSTと言ったらジョブのビルドですからね。

Jenkinsのファイルパラメータは、ローカルのファイルをJenkinsにUploadしてビルドすることができる機能です。
そのため、curlでファイルをUploadするPOSTをコマンドで表現する必要があります。

--form もしくは -F を使用します。

# Upload用ファイルを用意
$ echo "Sample file" > sample.txt

# Fileパラメータにsample.txtを指定してビルド実行
$ curl -sS 'http://localhost:8080/job/sample/build' -X POST -F "file=@sample.txt" -F 'json={"parameter": [{"name":"FileParameter", "file":"file"}]}'

# ビルドが実行され、ファイルがUploadできていることを確認
$ curl -sS 'http://localhost:8080/job/sample/api/json' | jq .builds
[
  {
    "number": 1,
    "url": "http://localhost:8080/job/sample/1/"
  }
]
$ curl -sS 'http://localhost:8080/job/sample/1/parameters/parameter/FileParameter/sample.txt'
Sample file

@以降で、ファイルを相対パスで指定します。

ちなみにJenkinsのparameterizedビルドのcurlの使用例はJenkinsのHPに書いてあります。
下記ページ Submitting jobs の部分です。
https://wiki.jenkins-ci.org/display/JENKINS/Remote+access+API

-F-d は併用できません

$ curl localhost:8080 -X POST -F "hoge=fuga" -d "fuga=piyo"
Warning: You can only select one HTTP request!

こんな感じでエラーになります。同様に --data-urlencode も、-F とは併用できません。
-F を使いつつ、curlにURLエンコードを任せてPOSTするにはどうすれば。。。)

それぞれのオプションを付与した際のHTTPリクエストを観察すると、
-F では Content-Type: multipart/form-data で、
-d では Content-Type: application/x-www-form-urlencoded となります。
-F でマルチパートでPOSTすると設定しているのに、-d で違うContent-Typeで送ろうとしているから実行できない、という説明で良いでしょうか。。。もっと適切な表現があるとは思いますが。

ちなみに、 -F-d を同時に使った場合のエラーメッセージは、-S では表示されません。

$ curl -sS  localhost:8080 -X POST -F "hoge=fuga" --data-urlencode "fuga=piyo"
 # warning 行が表示されない
# 終了コードは 0 ではないです
$ echo $?
4

エラー時に気付くために -S というのに。。

認証とcurl

今までは、アカウント管理のない真っ裸なJenkinsにアクセスしていました。
ユーザアカウントとパスワードが必要な場合のcurlも試してみます。

Jenkinsの設定

詳細は割愛しますが、
Jenkinsのセキュリティ設定のMatrix-based securityで、
特定のユーザ(yasuhiroki)以外からはJenkinsにアクセスできないようにしています。

この設定をした状態でcurlを叩くと下のようになります。

$ curl -sS 'http://localhost:8080/api/json' -I
HTTP/1.1 403 Forbidden
X-Content-Type-Options: nosniff
Set-Cookie: JSESSIONID.827aac98=qv6zzok692pe1397gebsgms19;Path=/;HttpOnly
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Content-Type: text/html;charset=UTF-8
X-Hudson: 1.395
X-Jenkins: 1.619
X-Jenkins-Session: 85e6322e
X-Hudson-CLI-Port: 52325
X-Jenkins-CLI-Port: 52325
X-Jenkins-CLI2-Port: 52325
X-You-Are-Authenticated-As: anonymous
X-You-Are-In-Group: 
X-Required-Permission: hudson.model.Hudson.Read
X-Permission-Implied-By: hudson.security.Permission.GenericRead
X-Permission-Implied-By: hudson.model.Hudson.Administer
Content-Length: 813
Server: Jetty(winstone-2.8)

想定通り、アカウント制限が機能しています。

アカウント名とパスワードを指定してリクエスト -u

いわゆるBASIC認証です。
今回は、ユーザ名はyasuhiroki、パスワードはsampleで作成したので、
-u yasuhiroki:sample と付与することになります。
見ての通り、コンソール上にパスワードがもろ残ってしまいます。

$ curl -sS 'http://localhost:8080/api/json' -I -u yasuhiroki:sample
HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-Jenkins: 1.619
X-Jenkins-Session: 85e6322e
Content-Type: application/json;charset=UTF-8
Content-Length: 444
Server: Jetty(winstone-2.8)

コマンドにベタ書きしなければ、curl実行後に入力を求められます。

$ curl -sS 'http://localhost:8080/api/json' -I -u yasuhiroki
Enter host password for user 'yasuhiroki':
HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-Jenkins: 1.619
X-Jenkins-Session: 85e6322e
Content-Type: application/json;charset=UTF-8
Content-Length: 444
Server: Jetty(winstone-2.8)

別に-uオプションを使わなくても、http://user:pass@hostnameでやってしまう方法もあります。

$ curl -sS 'http://yasuhiroki:sample@localhost:8080/api/json' -I
HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-Jenkins: 1.619
X-Jenkins-Session: 85e6322e
Content-Type: application/json;charset=UTF-8
Content-Length: 444
Server: Jetty(winstone-2.8)

ちなみにJenkins自体に、パスワードとは別に使えるAPIトークンがあるので、そちらを使う手もあります。(むしろ、そちらを使うべき)
トークンはJenkinsのアカウントの設定で確認、変更ができます。

# JenkinsのAPIトークンを使用した例
$ curl -sS 'http://localhost:8080/user/yasuhiroki/api/json' -I -u yasuhiroki:a752ad2b9fc7b314562f386b603fc11f
HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-Jenkins: 1.619
X-Jenkins-Session: 85e6322e
Content-Type: application/json;charset=UTF-8
Content-Length: 214
Server: Jetty(winstone-2.8)

SessionをCookieから取得して使用 -c -b

Sessionを保持して使用する必要がある場合、curlを単発で叩いては実現が難しい動作もあるでしょう。
-c cookie.txt で、レスポンスのCookieをcookie.txtに保存し、
-b cookie.txt で、cookie.txtの中身をリクエストのCookieに含めることができます。

Jenkinsの操作をSessionでどうにかできないか試しましたが、
何となくできそうな気がするものの、時間が掛かりそうなので割愛します...。
いつかリベンジしたいですね。

ところで、認証に失敗した時の終了コードは? --fail -f

たとえば、-u で渡すパスワードを間違えたとします。

$ curl -sS 'http://localhost:8080/api/json' -I -u yasuhiroki:miss
HTTP/1.1 401 Invalid password/token for user: yasuhiroki
X-Content-Type-Options: nosniff
WWW-Authenticate: Basic realm="Jenkins"
Content-Type: text/html;charset=ISO-8859-1
Cache-Control: must-revalidate,no-cache,no-store
Content-Length: 1441
Server: Jetty(winstone-2.8)

$ echo $?
0

終了コードは0なのです。
もし、何かエラーがあった時は、終了コードを 0 以外のを返して欲しい場合は、 --fail (-f) オプションが利用できます。

$ curl -sS 'http://localhost:8080/api/json' -u yasuhiroki:miss -f
curl: (22) The requested URL returned error: 401
$ echo $?
22

ただし、 401 407 エラーのような、認証関連の場合は確実性に欠けているそうです。

This method is not fail-safe and there are occasions where non-successful response codes will slip through,
especially when authentication is involved (response codes 401 and 407).

他のTips

-w でいろんな情報を表示する

curlの実行結果に、追加してさらに情報を出力することが可能です。

$ curl -sSO 'http://localhost:8080/api/json' -u yasuhiroki:a752ad2b9fc7b314562f386b603fc11f -w 'hogefuga'
hogefuga

-w では、特定の変数を使用すると、その変数が持つ値を表示できます。

例えば、HTTPステータスだけを表示したいなら、-w '%{http_code}\n' でOKです。改行はお好みで。

$ curl -sS -w '%{http_code}\n' 'http://localhost:8080/' -o /dev/null
200

ちなみに、manを探ったところ、27の変数が見つりました。

URLエンコードするだけ

-w '%{url_effective}' --data-urlencode -Gを使用して、文字列をURLエンコードして表示するだけのシェルスクリプトです。

-G (--get) は、-d--data-urlencode で指定した値を、クエリーとして自動的に付与しなおしてくれるオプションです。
例えば、-d 'val=A' -G としておけば、リクエストURLに、host/?val=A などとクエリーとして付与したうえで送信してくれます。
これと、-w を組み合わせることで、curlがURLエンコードしてくれた結果を出力することができます。/?がくっつくのが玉に瑕です。

$ curl -s -w '%{url_effective}\n' --data-urlencode 'じぇんきんす' -G ''
/?%E3%81%98%E3%81%87%E3%82%93%E3%81%8D%E3%82%93%E3%81%99

/?が邪魔な場合は、例えばこんな感じでしょうか。

$ urlencoded_str=$(curl -s -w '%{url_effective}\n' --data-urlencode 'じぇんきんす' -G '')
$ urlencoded_str=${urlencoded_str:2}
$ echo ${urlencoded_str}
%E3%81%98%E3%81%87%E3%82%93%E3%81%8D%E3%82%93%E3%81%99

他によく使うオプション

-k SSL証明書を無視する。主に、オレオレ証明書を使っているWebサーバーにアクセスする時に。

-x Proxyを指定。

-H Request Headerを追加する。Content-Typeを指定する時など
- 例: -H "Content-Type: application/json"

-L リダイレクト先までアクセスする。

おまけ

発音、何て読む?

初めて見た時から「カール」と呼んでいましたが、公式サイトでは、

The fact it can also be pronounced 'see URL' also helped
- http://curl.haxx.se/docs/faq.html#What_is_cURL

'see URL' と同じ、つまり、「シーユーアールエル」だそうです。
と、いいつつドキュメントの続きをよく読むと、

We pronounce curl with an initial k sound. It rhymes with words like girl and earl.

なんて書いてあり、おまけに発音例を .wav ファイルで提供しており、「カール」と呼んでいます。
(じゃあもう最初から カール で良いじゃないか。。。)

User-Agentを偽装する

Webサイトによっては、curl コマンドによるアクセスを制御している場合があるそうです。
そういう時は、 -A オプションを指定して、User-Agentを空にするとうまく行くかもしれません。

$ curl -s -w '%{http_code}\n' http://www.amazon.co.jp/dp/B00JEYPPOE/ -o /dev/null 
503
$ curl -s -w '%{http_code}\n' http://www.amazon.co.jp/dp/B00JEYPPOE/ -o /dev/null  -A ''
200

参考) http://jarp.does.notwork.org/diary/201508c.html#20150825

Optionの数

どれくらいあるのか、ざっくり調べたところ、170ありました。

$ man curl | egrep -- '^[[:space:]]{7}-' | wc -l
170
$ curl -h | egrep -- '^[[:space:]]+-' | wc -l
168
# helpには、 --environment と --proxy-header がなかった

もっと便利そうな http コマンド (httpie)

この記事を書き始めた後、 httpie というものを知りました。
https://github.com/jkbrzt/httpie

例えば、json形式のファイルをPOST時に渡せば勝手に Content-Type: application/json を設定してくれるなど、curl よりも気が利いています。