有兩種方法來檢查ping命令的研製成功或失敗:測試錯誤級別執行後或測試命令的輸出。對於這兩種情況,檢查ipv4或ipv6地址是不一樣的。
問題是:ping
如何表現?,它的輸出是什麼? errorlevel
是什麼時候設置的?
的errorlevel
如果我們與IPv6工作,規則是當存在對所有發送的數據包沒有回覆(所有數據包丟失)
ipv6具有一致的行爲,並檢查errorlevel是知道機器是否在線的可靠方法。
在IPv4中的規則不同
但是,在IPv4中,在同一個子網查驗的非可用機器並沒有固定的日e errorlevel
,你會得到一個「無法達到」的答案,n packets sent, n packed received, 0 packets lost
,所有的數據包都會從發送數據包的同一臺機器得到答覆。
當機器位於同一子網中時,此行爲在ipv4中使錯誤級別檢查失敗。
如何解決IPv4中的問題?輸出檢查
可以檢查ping
命令的輸出,如果輸出中存在字符串TTL=
,目標機器處於聯機狀態。
ping -n 1 10.0.0.1 | find "TTL=" >nul
if errorlevel 1 (
echo offline
) else (
echo online
)
但是,這種方法是在IPv4中可以作爲這個領域還沒有被列入平輸出將與IPv6的失敗(並改名,在IPv6中它被稱爲跳限制)
對於「一般」解決方案,可以使用(從先前的答案改編而來)(似乎有很多代碼,但幾乎都是註釋)。 ping
操作和輸出處理被封裝在一個子例程中,該子例程使用作爲批處理文件的第一個參數傳遞的地址/主機名稱進行調用。
@echo off
setlocal enableextensions disabledelayedexpansion
if "%~1"=="" goto :eof
call :isOnline "%~1"
if not errorlevel 1 (echo ONLINE) else (echo OFFLINE)
endlocal
exit /b
:isOnline address pingCount
setlocal enableextensions disabledelayedexpansion
:: send only one ping packed unless it is indicated to send more than one
set /a "pingCount=0", "pingCount+=%~2" >nul 2>nul
if %pingCount% lss 1 set "pingCount=1"
:: a temporary file is needed to capture ping output for later processing
set "tempFile=%temp%\%~nx0.%random%.tmp"
:: ping the indicated address getting command output and errorlevel
ping -w 1000 -n %pingCount% "%~1" > "%tempFile%" && set "pingError=" || set "pingError=1"
::
:: When pinging, the behaviours of ipv4 and ipv6 are different
::
:: we get errorlevel = 1 when
:: ipv4 - when at least one packet is lost. When sending more than one packet
:: the easiest way to check for reply is search the string "TTL=" in
:: the output of the command.
:: ipv6 - when all packet are lost.
::
:: we get errorlevel = 0 when
:: ipv4 - all packets are received. BUT pinging a inactive host on the same
:: subnet result in no packet lost. It is necessary to check for "TTL="
:: string in the output of the ping command
:: ipv6 - at least one packet reaches the host
::
:: We can try to determine if the input address (or host name) will result in
:: ipv4 or ipv6 pinging, but it is easier to check the result of the command
::
:: +--------------+-------------+
:: | TTL= present | No TTL |
:: +-----------------------+--------------+-------------+
:: | ipv4 errorlevel 0 | OK | ERROR |
:: | errorlevel 1 | OK | ERROR |
:: +-----------------------+--------------+-------------+
:: | ipv6 errorlevel 0 | | OK |
:: | errorlevel 1 | | ERROR |
:: +-----------------------+----------------------------+
::
:: So, if TTL= is present in output, host is online. If TTL= is not present,
:: errorlevel is 0 and the address is ipv6 then host is online. In the rest
:: of the cases host is offline.
::
:: To determine the ip version, a regular expresion to match a ipv6 address is
:: used with findstr. As it will be only tested in the case of no errorlevel,
:: the ip address will be present in ping command output.
set "exitCode=1"
>nul 2>nul (
find "TTL=" "%tempFile%" && (set "exitCode=0") || (
if not defined pingError (
findstr /r /c:" [a-f0-9:][a-f0-9]*:[a-f0-9:%%]*[a-f0-9]: " "%tempFile%" && set "exitCode=0"
)
)
del /q "%tempFile%"
)
:: cleanup and return errorlevel: 0=online , 1=offline
endlocal & exit /b %exitCode%
> tempfile是做什麼的?我會假設它創建一個臨時文件,但爲什麼? – Konan
'>'是'重定向器'。與'''重定向命令的輸出一樣,作爲下一個輸入的輸入,'>'將輸出重定向到一個新文件(或者替換現有文件)'>>'將輸出重定向到一個新文件(或者附加一個新文件現有文件)和'<'重定向來自文件而不是來自鍵盤的輸入。 – Magoo
謝謝,這是很好的信息! – Konan