Windows で Ping のように HTTP リクエストを定期的に送る方法

ネットワーク基盤を構築した後に単体試験、結合試験を経て可用性チェックをするために障害試験を行うケースがあると思います。

障害試験の際にはコマンドプロンプト等のツールで Ping を打ち続けて障害復旧までの時間を計測します。

Ping は Layer 3レベルの復旧を確認できますが、Layer 7(HTTP)レベルの復旧まで確認してその所要時間を可視化したいケースがあると思います。

インターネット上に公開されているフリーソフトを利用する方法もありますが、社内のセキュリティ規則によりダウンロード禁止になっているケースもあるのではないでしょうか。

Windows OS 標準機能のみで HTTP リクエストを定期的に送信してその時刻を表示する手法を確立できれば、フリーソフトを入れるリスクを負わなくて済みます。

本記事では Windows OS で PowerShell を使った定期的な HTTP リクエストの実行とレスポンス時刻を表示する方法についてご紹介します。

前提条件

本記事では筆者のように PowerShell やスクリプトの経験が浅い方でも手軽に行えるように、コマンド1行で実行できることを目標とします。

出力結果も Ping のように1行で出力することで通信試験や障害試験の際に容易に確認できるようにします。

以下の条件を満たすようなコマンドを実行します。

  • 1秒ごとに HTTP GET リクエストを送信する
  • 正常時はステータスコード200を標準出力する
  • 異常時もステータスコードを標準出力する
  • 接続不可時は1秒でタイムアウトとする
  • ダウンロード処理中でも1秒でタイムアウトとする
    • サーバの復旧時刻を正しく確認するためにタイムアウトを短く設定してリクエスト送信間隔を短くする
  • 接続不可時のエラーメッセージは表示しない
  • リクエストの送信時刻を出力する
  • サーバのレスポンス時刻を出力する

実行環境

  • OS:Windows 11 Enterprise
  • PowerShell:5.1.22000.2600
  • curl:8.4.0

実行コマンド

while

定期的なコマンド実行の手法としてwhileステートメントを使用します。

条件が 真 である場合に処理を繰り返します。

今回はとくに条件を設けず常に処理を繰り返すため($true)として常に 真 にします。

PS C:\Windows\System32> while ($true) {Get-Date}

curl.exe

Windows OS で Web アクセス可能なコマンドは以下の通りです。

  • curl
  • Invoke-WebRequest

今回は Web アクセスのコマンドとしてcurlを利用します。

未だに Linux で利用するイメージが強いですが、Windows 10 以降では標準搭載されているコマンドです。

PowerShell では curl コマンドは Invoke-WebRequest のエイリアスとして設定されていますので、curl を実行するには curl.exeと実行ファイルを指定する必要があります。

今回は以下のオプションを利用します。

オプション 説明
-m curl 実行時間のタイムアウトを指定します。指定した秒数経過すると処理途中でもタイムアウトされます。
ファイルのダウンロード中やサーバから応答が無い場合でも処理はタイムアウトして、その後 while によるループ処理で再度 curl コマンドが実行されます。
障害試験による復旧時間を正確に確認するためにタイムアウト時間は「1秒」と短めに設定します。
-o GET した HTTP レスポンスボディをファイル出力するオプションですが、今回は出力先に"NUL" を指定することで HTTP レスポンスボディを非表示にします。
-s エラーメッセージやダウンロードの進捗状況を表示しないオプションです。
今回はサーバからの応答有無を確認する目的なので、これらの表示は不要のためオプションを有効にします。
-w 出力結果をカスタマイズするオプションです。
%{http_code} :ステータスコードを表示します。
%header{date}:HTTP レスポンスに含まれる Date ヘッダを表示します。
PS C:\Windows\System32> while ($true) {curl.exe -m 1 -s -o NUL -w "%{http_code} %header{date}\n" https://www.jbs.co.jp}

Get-Date

コマンド実行時の日付・時刻を表示するコマンドレットです。

今回はcurl.exeと同時実行して HTTP リクエストの送信時刻として表示します。

PS C:\Windows\System32> while ($true) {Get-Date ; curl.exe -m 1 -s -o NUL -w "%{http_code} %header{date}\n" https://www.jbs.co.jp}

この出力結果は問題ないように見えますが、Get-Date の結果が OS のタイムゾーン(JST)の時刻、%header{date}のタイムゾーンは GMT のため、およそ9時間の差があります。

Date ヘッダのタイムゾーンが GMT で出力されるのは RFC7231で定められているので変更できません。*1

Get-Dateの結果から9時間マイナスして時刻表示が合うように、.AddHours(-9)オプションを追加します。

PS C:\Windows\System32> while ($true) {(Get-Date).AddHours(-9) ; curl.exe -m 1 -s -o NUL -w "%{http_code} %header{date}\n" https://www.jbs.co.jp}

Start-Sleep

1秒ごとに curlを実行するにはループする前に1秒間隔を設ける必要があります。

Start-Sleepコマンドレットを curl の後に指定すると、指定した間隔でスリープします。

PS C:\Windows\System32> while ($true) {(Get-Date).AddHours(-9) ; curl.exe -m 1 -s -o NUL -w "%{http_code} %header{date}\n" https://www.jbs.co.jp ; start-sleep 1}

Write-Output

ここまでの出力結果でも条件を満たしているので、通信試験や障害試験で利用できると思います。

ただ冒頭で記した「出力結果を Ping のように1行で出力する」条件を満たすには、一工夫が必要です。

Write-Outputコマンドレットを利用すると、ダブルクォーテーションで囲んだ変数や文字列を1行で表示できます。

PS C:\Windows\System32> while ($true) {Write-Output "$((Get-Date).AddHours(-9)) $(curl.exe -m 1 -s -o NUL -w "%{http_code} %header{date}\n" https://www.jbs.co.jp)" ; start-sleep 1}

動作確認

正常通信

上記の出力結果通り、ステータスコード200が応答されました。

左から以下の順序で表示されます。

  • [HTTP リクエスト送信時刻]:01/24/2024 10:03:48
  • [ステータスコード] :200
  • [サーバレスポンス時刻]:Wed, 24 Jan 2024 10:03:49 GMT
01/24/2024 10:03:48 200 Wed, 24 Jan 2024 10:03:49 GMT

異常通信(ステータスコード4xx)

認証が必要なサイトやアクセス禁止のサイトにアクセスすると、ステータスコード4xxが応答されました。

異常通信(ステータスコード無し)

Webサービスに異常がありポートが開いてない場合、ステータスコード000(無し)が表示されます。

1秒のタイムアウト後に1秒スリープしてからリクエストを送っているため、2秒ごとにリクエスト送信されています。

おわりに

PowerShell も curl も検証で少し使った程度の知識でしたが、何とか試験で利用できそうなコマンドになったと思います。

curl はオプションが豊富にあり、とくに-w %header{}は任意のレスポンスヘッダを出力可能なので、利用用途に応じた出力結果を表示できます。

他にも有用なオプションがありましたら記事にできればと思います。

執筆担当者プロフィール
菅原 丈晴

菅原 丈晴(日本ビジネスシステムズ株式会社)

ネットワーク機器の設計/構築エンジニア。最近は仮想基盤・クラウドを触っています。

担当記事一覧