Je peux exécuter une seule commande pour voir si un port est ouvert:
portqry -n servername -e 80
Je veux lancer ceci contre une liste de serveurs:
Je veux tous les tester en utilisant un seul script de lot Windows et voir quels ports sont ouverts et lesquels sont fermés. (Et je ne veux pas que ça tombe sur le premier port fermé).
Ma question est la suivante: existe-t-il un script de lot Windows pour voir si une séquence de serveurs / ports est ouverte?
Supplémentaire: Je suis conscient qu’il existe d’autres questions demandant comment vérifier si un port est ouvert. Aucun d’entre eux ne concerne le script pour une séquence de ports de manière fiable.
Voici. Payez-le en avant. 🙂 Pour répondre directement à votre question, utilisez simplement une boucle for
pour parcourir vos serveurs et effectuez un portqry
sur chacun. Edit: Cet extrait de PowerShell trouvé est utile pour se débarrasser de la dépendance PortQry.
@echo off setlocal set "servers=dev1 dev2 dev3 test1 test2 test2:8080 prod prod:443" for %%I in (%servers%) do ( for /f "tokens=1,2 delims=:" %%a in ("%%I") do ( set "port=%%~b" if not defined port set "port=80" setlocal enabledelayedexpansion call :handshake "%%~a" "!port!" && ( echo %%a port !port!: OK ) || ( echo %%a port !port!: Error ) endlocal ) ) goto :EOF :handshake powershell "$t=new-object Net.Sockets.TcpClient;$c=$t.BeginConnect('%~1',%~2,{},{});if($c.AsyncWaitHandle.WaitOne(1000)){$t.EndConnect($c);exit 0};exit 1" exit /b %ERRORLEVEL%
Voici la solution originale utilisant PortQry 2.0 :
@echo off setlocal set "servers=dev1 dev2 dev3 test1 test2 test2:8080 prod prod:443" for %%I in (%servers%) do ( for /f "tokens=1,2 delims=:" %%a in ("%%I") do ( set "port=%%~b" if not defined port set "port=80" setlocal enabledelayedexpansion portqry -n "%%~a" -e "!port!" >NUL 2>NUL && ( echo %%a port !port!: OK ) || ( echo %%a port !port!: Error ) endlocal ) )
Si vous testez uniquement des services Web, il serait plus judicieux de procéder de manière différente. Vous pouvez utiliser l’object Microsoft.XMLHTTP
COM pour se débarrasser de cette dépendance de portqry
; Les réponses acquises seront plus pertinentes pour les services HTTP. (Par exemple, si vous avez un serveur VNC exécuté sur le port 8080 où vous attendez qu’un service Web écoute à la place, portqry
renverra probablement un succès lorsque vous en aurez besoin pour retourner en échec.)
Quoi qu’il en soit, enregistrez-le en tant que script .bat et salez au goût.
@if (@CodeSection == @Batch) @then @echo off setlocal set "servers=dev1 dev2 dev3 test1 test2 test2:8080 prod prod:443" for %%I in (%servers%) do ( for /f "tokens=1,2 delims=:" %%a in ("%%I") do ( set "port=%%~b" if not defined port set "port=80" setlocal enabledelayedexpansion cscript /nologo /e:JScript "%~f0" "%%~a" "!port!" && ( echo %%a port !port!: OK ) || ( echo %%a port !port!: Error ) endlocal ) ) goto :EOF @end // end batch / begin JScript chimera var server = WSH.Arguments(0), port = WSH.Arguments(1), protocol = port == 443 ? 'https' : 'http', URL = protocol + '://' + server + ':' + port + '/', XHR = WSH.CreateObject('Microsoft.XMLHTTP'); XHR.open('GET', URL); XHR.setRequestHeader('User-Agent','XMLHTTP/1.0'); XHR.send(''); while (XHR.readyState != 4) WSH.Sleep(25); WSH.Quit(XHR.status - 200);
C’est ce que j’ai fini par remplacer le VBScript ci-dessus par – un fichier appelé porttest.ps1
qui est exécuté avec powershell -f porttest.ps1
param( [ssortingng] $remoteHost = "arbitrary-remote-hostname", [int] $port = 23 ) # Open the socket, and connect to the computer on the specified port write-host "Connecting to $remoteHost on port $port" $tcpobject = new-Object system.Net.Sockets.TcpClient $connect = $tcpobject.BeginConnect($remoteHost,$port,$null,$null) #Configure a timeout before quitting - time in milliseconds $wait = $connect.AsyncWaitHandle.WaitOne(1000,$false) If (-Not $Wait) { 'Timeout' exit 1 } Else { $error.clear() $tcpobject.EndConnect($connect) | out-Null If ($Error[0]) { Write-warning ("{0}" -f $error[0].Exception.Message) exit 1 } Else { 'Port open!' exit 0 } }