Как проверить, открыт ли порт на удаленном сервере с пакетным файлом и без стороннего программного обеспечения?
Поскольку этот вопрос закрыт (где я собирался ответить первым), я открываю этот.
На некоторых машинах запрещено устанавливать / загружать двоичные файлы, поэтому я хочу знать, как я могу проверить, открыт ли порт на удаленной машине, используя только собственные возможности сценариев Windows.
3 ответа
К сожалению, Windows не предлагает простых инструментов для проверки, открыт ли порт на удаленном сервере.
Одним из вариантов является telnet, но он не может быть записан в сценарии, поскольку он закрывается, когда его вывод перенаправляется или захватывается. Когда-то давно на компьютерах Windows был установлен COM-объект MSWinsock.Winsock.1, который можно было использовать в сценарии, но не более того. PortQry и PsPing - замечательные инструменты, но вам все равно придется их загружать (несмотря на то, что они предоставляются Microsoft).
Поэтому проще всего полагаться на PowerShell.
Вот код для простого скрипта .bat, внутренне использующий Powershell для выполнения работы:
@echo off
::Must be without quotes. If you intend to use command line arguments use %~1
set "host=google.com"
set /a port=443
for /f %%a in ('powershell "$t = New-Object Net.Sockets.TcpClient;try{$t.Connect("""%host%""", %port%)}catch{};$t.Connected"') do set "open=%%a"
:: or simply
:: powershell "$t = New-Object Net.Sockets.TcpClient;try{$t.Connect("""%host%""", %port%)}catch{};$t.Connected"
echo Open: %open%
На некоторых машинах есть.NET Framework без установленного PowerShell, поэтому в этом случае код C# может быть встроен в пакетный скрипт с помощью msbuild:
<!-- :
@echo off
:: checks if a port on a remote server is open
:: returns errorlevel 1 if it's closed
setlocal
for %%h in (/h /help -help -h "") do (
if /I "%~1" equ "%%~h" (
goto :printHelp
)
)
if "%~2" equ "" goto :printHelp
set "HOST=%~1"
set /a PORT=%~2
:::::: Starting C# code :::::::
:: searching for msbuild location
for /r "%SystemRoot%\Microsoft.NET\Framework\" %%# in ("*msbuild.exe") do set "msb=%%#"
if not defined msb (
echo No .NET framework installed
endlocal & exit /b 10
)
rem :::::::::: calling msbuid :::::::::
call %msb% /nologo /noconsolelogger "%~dpsfnx0"
rem ::::::::::::::::::::::::::::::::::::
endlocal & exit /b %errorlevel%
:printHelp
echo Checks if port is open on a remote server
echo(
echo Usage:
echo %~nx0 host port
echo(
echo If the port is not accessible an errorlevel 1 is set
endlocal & exit /b 0
-->
<Project ToolsVersion="$(MSBuildToolsVersion)" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="_"><_/></Target>
<UsingTask TaskName="_" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll" >
<Task>
<Using Namespace="System" />
<Using Namespace="System.Net.Sockets" />
<Code Type="Method" Language="cs"><![CDATA[
public override bool Execute(){
String host=Environment.GetEnvironmentVariable("HOST").ToLower();
int port=Int32.Parse(Environment.GetEnvironmentVariable("PORT"));
Console.WriteLine("Checking host {0} and port {1}",host,port);
using(TcpClient client = new TcpClient()) {
try {
client.Connect(host, port);
} catch(Exception) {
Console.WriteLine("Closed");
return false;
}
client.Close();
Console.WriteLine("Open");
return true;
}
}
]]>
</Code>
</Task>
</UsingTask>
</Project>
Что касается машин без.NET Framework, я не знаю ни одного собственного метода проверки удаленных портов.
Если вы хотите проверить только TCP-порты, вы можете использовать Test-NetConnection. Если предлагает -Port
параметр для определения порта TCP.
Эти команды могут быть использованы в Powershell:
New-Object System.Net.Sockets.TcpClient("123.12.12.123", 22)
New-Object System.Net.Sockets.UdpClient("123.12.12.123", 22)