バッチファイルで「ネットワークにつながっているか」を判定してオンライン・オフラインで処理を切り替えたい場面はよくあります。本記事では ping の基本から findstr による精密判定、複数ホストのチェック、リトライループ、ポート疎通確認、よくある落とし穴まで体系的に解説します。
- ping の ERRORLEVEL でネットワーク接続を判定する基本パターン
- ping がブロックされる環境での代替判定方法
- findstr で ping 結果を文字列で精密に判定する方法
- 特定ポートの疎通確認(telnet / PowerShell)
- 複数ホストを順番にチェックして1つでも応答があれば続行する方法
- リトライ付き待機ループで接続回復を待つ方法
判定方法の選び方
ネットワーク接続の確認方法は目的によって使い分けます。
| 確認したいこと | 推奨方法 |
|---|---|
| インターネット接続の有無 | ping 8.8.8.8 または 1.1.1.1 |
| 社内サーバーへの到達確認 | ping サーバーIP・ホスト名 |
| 特定サービスのポート確認 | PowerShell Test-NetConnection / telnet |
| ネットワークドライブのマウント確認 | if exist でパスを確認 |
| ping がブロックされる環境 | curl / PowerShell Invoke-WebRequest |
基本パターン:ping の ERRORLEVEL で分岐
最もシンプルな判定
@echo off
REM ping を1回だけ送り、結果を画面に出さない
ping -n 1 8.8.8.8 >nul 2>&1
if errorlevel 1 (
echo [オフライン] ネットワークに接続されていません。
) else (
echo [オンライン] ネットワークに接続されています。
)
ping コマンドは応答があれば終了コード 0、タイムアウト・到達不能なら 1 を返します。if errorlevel 1 は「終了コードが 1 以上」という意味なので、接続失敗を正しく検出できます。
タイムアウトを短く設定する(高速判定)
@echo off
REM -n 1: 1回送信 / -w 1000: タイムアウトを1000ミリ秒(1秒)に短縮
ping -n 1 -w 1000 8.8.8.8 >nul 2>&1
if errorlevel 1 (
echo ネットワーク接続なし
) else (
echo ネットワーク接続あり
)
-w オプションを省略すると、ping は1回あたり最大4秒待ちます。スクリプトをすばやく動かしたい場合は -w 1000(1秒)などに短縮してください。
精密判定:findstr で ping 結果の文字列を解析する
ERRORLEVEL では「ホストが存在しない」と「パケットロス 100%」を区別できません。findstr で出力文字列を調べると、より正確な判定ができます。
@echo off
setlocal
REM ping 結果を一時変数に取り込んで解析する
set ONLINE=0
for /f "delims=" %%L in ('ping -n 1 8.8.8.8') do (
echo %%L | findstr /i "TTL=" >nul
if not errorlevel 1 set ONLINE=1
)
if "%ONLINE%"=="1" (
echo [オンライン] TTL 応答あり
) else (
echo [オフライン] TTL 応答なし
)
endlocal
ping の応答行には必ず
TTL=(Time To Live)の文字列が含まれます。これで判定すると「要求がタイムアウトしました」「宛先ホストに到達できません」を確実に除外できます。ERRORLEVEL だけでは区別できないケースをカバーできる精密な方法です。
社内サーバーへの接続確認
@echo off
REM 社内サーバーのIPまたはホスト名で確認
set SERVER=192.168.1.10
ping -n 1 -w 2000 %SERVER% >nul 2>&1
if errorlevel 1 (
echo [ERROR] サーバー %SERVER% に到達できません。
echo 処理を中断します。
exit /b 1
) else (
echo [OK] サーバー %SERVER% に接続確認できました。
echo 処理を開始します。
)
複数ホストを順番にチェックする
1つのサーバーがメンテナンス中でも別のサーバーで続行したい場合、複数ホストを順番に試します。
@echo off
setlocal
REM チェックするホストを順番に定義
set HOSTS=192.168.1.10 192.168.1.11 192.168.1.12
set CONNECTED_HOST=
for %%H in (%HOSTS%) do (
ping -n 1 -w 1000 %%H >nul 2>&1
if not errorlevel 1 (
set CONNECTED_HOST=%%H
goto :found
)
echo %%H: 応答なし
)
echo [ERROR] すべてのホストに接続できませんでした。
exit /b 1
:found
echo [OK] %CONNECTED_HOST% に接続しました。処理を開始します。
endlocal
リトライ付き待機ループ
ネットワークが一時的に切れた場合に接続回復を待ってから処理を再開するパターンです。
@echo off
setlocal enabledelayedexpansion
set TARGET=8.8.8.8
set RETRY_MAX=10
set INTERVAL=5
set /a RETRY=0
:retry_loop
ping -n 1 -w 2000 %TARGET% >nul 2>&1
if not errorlevel 1 goto :connected
set /a RETRY+=1
if !RETRY! GEQ !RETRY_MAX! (
echo [ERROR] %RETRY_MAX% 回試みましたが接続できませんでした。
exit /b 1
)
echo 接続待機中... (!RETRY!/%RETRY_MAX%) %INTERVAL% 秒後に再試行します
timeout /t %INTERVAL% /nobreak >nul
goto :retry_loop
:connected
echo [OK] ネットワーク接続を確認しました。
endlocal
特定ポートの疎通確認
ping が通っても特定のサービスポートが開いているかどうかは別問題です。ポートレベルの確認には PowerShell を使うのが最も確実です。
PowerShell の Test-NetConnection でポート確認
@echo off
REM PowerShell の Test-NetConnection でポート 1521(Oracle)を確認
powershell -NoProfile -Command "if ((Test-NetConnection -ComputerName 192.168.1.10 -Port 1521 -InformationLevel Quiet) -eq $true) { exit 0 } else { exit 1 }"
if errorlevel 1 (
echo [ERROR] ポート 1521 に接続できません。
exit /b 1
) else (
echo [OK] ポート 1521 が開いています。
)
REM ポート番号を変えれば他のサービスも確認できる
REM 80 : HTTP
REM 443 : HTTPS
REM 3389 : RDP
REM 1521 : Oracle DB
REM 3306 : MySQL
REM 5432 : PostgreSQL
telnet でポート確認(古い環境向け)
@echo off
REM telnet でポート確認(telnet クライアントが有効な場合)
echo. | telnet 192.168.1.10 80 >nul 2>&1
if errorlevel 1 (
echo [ERROR] ポート 80 に接続できません。
) else (
echo [OK] ポート 80 が開いています。
)
Windows Server 2008 以降・Windows Vista 以降では telnet クライアントはデフォルトで無効です。有効化するには「コントロールパネル → プログラムと機能 → Windows の機能の有効化または無効化 → Telnet クライアント」で有効にする必要があります。本番環境では PowerShell の
Test-NetConnection を使う方が確実です。
ping がブロックされる環境での代替判定
ファイアウォールで ICMP(ping)が遮断されている環境では、curl や PowerShell で HTTP 疎通を確認します。
@echo off
REM PowerShell で HTTP 接続を確認(ICMP ブロック環境)
powershell -NoProfile -Command "try { $r=(New-Object Net.WebClient).DownloadString('http://www.gstatic.com/generate_204'); exit 0 } catch { exit 1 }"
if errorlevel 1 (
echo [オフライン] HTTP 接続できません。
) else (
echo [オンライン] HTTP 接続できます。
)
REM curl が使える環境(Windows 10 1803 以降に標準搭載)
curl -s -o nul -w "%%{http_code}" --max-time 3 http://www.gstatic.com/generate_204 >nul 2>&1
if errorlevel 1 (
echo [オフライン]
) else (
echo [オンライン]
)
ネットワークドライブの存在確認
@echo off
REM ネットワークドライブ Z: のマウント確認
if exist Z:\ (
echo [OK] Z ドライブが利用可能です。
) else (
echo [ERROR] Z ドライブが見つかりません。
)
REM UNC パスで直接確認
if exist \\192.168.1.10\share\ (
echo [OK] 共有フォルダに接続できます。
) else (
echo [ERROR] 共有フォルダに接続できません。
)
実践サンプル:接続確認→ログ出力→ファイル転送
@echo off
setlocal enabledelayedexpansion
set LOGFILE=%~dp0sync_%DATE:/=%.log
set SERVER=192.168.1.10
set SRC=C:\data\export
set DST=\\%SERVER%\backup\export
call :log "同期処理開始"
REM ネットワーク確認
ping -n 1 -w 2000 %SERVER% >nul 2>&1
if errorlevel 1 (
call :log "[ERROR] サーバー %SERVER% に接続できません。処理スキップ。"
exit /b 1
)
call :log "[OK] サーバー接続確認"
REM ファイル転送(ROBOCOPY)
robocopy "%SRC%" "%DST%" /MIR /LOG+:"%LOGFILE%" /NP /NFL
if errorlevel 8 (
call :log "[ERROR] ROBOCOPY でエラーが発生しました。ERRORLEVEL=!errorlevel!"
exit /b 1
)
call :log "[OK] 同期完了"
exit /b 0
:log
echo [%DATE% %TIME%] %~1
echo [%DATE% %TIME%] %~1 >> "%LOGFILE%"
exit /b 0
ROBOCOPY のオプション詳細は ROBOCOPY の使い方完全ガイド(ミラーリング・差分コピー・ログ出力) で解説しています。ログ出力の自動管理については バッチファイルのログローテーション実装ガイド を参照してください。
よくある落とし穴と対処法
落とし穴1: ping はブロックされることがある
REM NG: 社内ファイアウォールが ICMP を遮断していると常にオフライン判定になる
ping -n 1 server01 >nul
if errorlevel 1 echo オフライン ← ping ブロック環境では誤判定
REM OK: ポート確認や HTTP 確認で代替する
powershell -NoProfile -Command "if ((Test-NetConnection -ComputerName server01 -Port 445 -InformationLevel Quiet) -eq $true) { exit 0 } else { exit 1 }"
落とし穴2: 名前解決の失敗と通信失敗を区別したい
REM 名前解決に失敗した場合も ping の ERRORLEVEL は 1 になる
ping -n 1 nonexistent.example.com >nul 2>&1
REM 区別したい場合は findstr で出力メッセージを解析する
set PING_OK=0
set DNS_FAIL=0
for /f "delims=" %%L in ('ping -n 1 server01') do (
echo %%L | findstr /i "TTL=" >nul
if not errorlevel 1 set PING_OK=1
echo %%L | findstr /i "ping request could not find host" >nul
if not errorlevel 1 set DNS_FAIL=1
)
if "%PING_OK%"=="1" (
echo [OK] 接続成功
) else if "%DNS_FAIL%"=="1" (
echo [ERROR] DNS 名前解決に失敗しました
) else (
echo [ERROR] ホストに到達できません
)
落とし穴3: 2>&1 を忘れてエラーメッセージが画面に出る
REM NG: 標準出力だけ抑制しても標準エラーが画面に出ることがある ping -n 1 nonexistent.host >nul REM OK: 標準エラーも /nul にリダイレクト ping -n 1 nonexistent.host >nul 2>&1
落とし穴4: ERRORLEVEL の誤った使い方
REM NG: == 0 の比較では動かないケースがある(環境依存) if %errorlevel%==0 echo 成功 ← 動くが not errorlevel 1 の方が確実 REM OK: not errorlevel 1 で「0の場合」を表現する(バッチの正式な書き方) if not errorlevel 1 echo 成功 REM OK: if errorlevel 1 で「1以上の場合(失敗)」 if errorlevel 1 echo 失敗
よくある質問(FAQ)
目的に合わせて使い分けてください。
| 確認したいこと | 推奨する宛先 |
|---|---|
| インターネット接続 | 8.8.8.8(Google DNS)/ 1.1.1.1(Cloudflare) |
| 社内ネットワーク接続 | 社内のファイルサーバーや DC の IP |
| 特定サーバーへの接続 | 対象サーバーのIPまたはホスト名 |
インターネット確認に www.google.com などドメイン名を使うと DNS 障害時に誤判定することがあります。IP アドレスを使う方が確実です。
-w オプションで 1 ミリ秒単位で指定できます。ただし、あまり短くすると LAN 内でも失敗することがあります。
REM タイムアウトを 500ms に設定(LAN 内で十分な速さ) ping -n 1 -w 500 192.168.1.10 >nul 2>&1 REM インターネット向けは 2〜3 秒が安定 ping -n 1 -w 2000 8.8.8.8 >nul 2>&1
複数回送って1回でも成功すれば OK とする場合は findstr 判定が使いやすいです。
@echo off
setlocal
set ONLINE=0
REM 3回送って1回でも TTL= が返れば接続あり
for /f "delims=" %%L in ('ping -n 3 -w 1000 8.8.8.8') do (
echo %%L | findstr /i "TTL=" >nul
if not errorlevel 1 set ONLINE=1
)
if "%ONLINE%"=="1" (
echo [OK] 応答あり(3回中1回以上)
) else (
echo [ERROR] すべてタイムアウト
)
endlocal
ログ出力サブルーチンを作っておくと管理しやすくなります。
@echo off
setlocal
set LOGFILE=%~dp0network_check.log
ping -n 1 -w 2000 8.8.8.8 >nul 2>&1
if errorlevel 1 (
call :log "OFFLINE" "8.8.8.8 に到達できません"
) else (
call :log "ONLINE" "8.8.8.8 接続確認OK"
)
exit /b 0
:log
echo [%DATE% %TIME%] [%~1] %~2
echo [%DATE% %TIME%] [%~1] %~2 >> "%LOGFILE%"
exit /b 0
exit /b 0(接続あり)/ exit /b 1(接続なし)で戻り値を返し、呼び出し元で if errorlevel を使って分岐できます。詳細は EXIT /B 完全解説(戻り値・ウィンドウを閉じない仕組み) を参照してください。
REM check_network.bat
@echo off
ping -n 1 -w 2000 8.8.8.8 >nul 2>&1
if errorlevel 1 (exit /b 1) else (exit /b 0)
REM main.bat から呼び出す側
call check_network.bat
if errorlevel 1 (
echo オフライン - 処理スキップ
) else (
echo オンライン - 処理実行
)
まとめ
| 判定方法 | コマンド | 特徴 |
|---|---|---|
| ping ERRORLEVEL | ping -n 1 -w 1000 HOST >nul 2>&1 |
シンプル・標準的 |
| ping + findstr TTL= | for /f ... | findstr "TTL=" |
精密・タイムアウトと区別可 |
| ポート確認 | powershell Test-NetConnection -Port N |
サービス疎通まで確認 |
| HTTP 確認 | powershell Invoke-WebRequest |
ICMP ブロック環境向け |
| ネットワークドライブ | if exist Z:\ |
マウント状態の確認 |
| UNC パス | if exist \\server\share\ |
共有フォルダの存在確認 |
ネットワーク確認後のファイル転送には ROBOCOPY の使い方完全ガイド(ミラーリング・差分コピー・ログ出力)、判定結果の返し方の詳細は EXIT /B 完全解説(戻り値・ウィンドウを閉じない仕組み)、ループ内での変数管理は setlocal enabledelayedexpansion 完全ガイド(FOR内変数・遅延展開) を参照してください。

