在PowerShell版本2中是否有与tracert等效的命令?

14

我正在使用 PSVersion 2.0,想知道是否有类似于 traceroute 的功能?

我知道在 PowerShell v4 中有 Test-NetConnection 命令来执行 tracert,但是在 v2 中怎么办?可以这样做:

Test-NetConnection "IPaddress/HOSTaname" -TraceRoute

谢谢


1
你可以在PowerShell中使用原始的tracert.exe,只需要自己解析输出即可。 - Mathias R. Jessen
谢谢你,你帮了我很多!!! - Sylca
4个回答

27

正如评论中提到的那样,您可以通过解析tracert.exe的输出来制作自己的“简易版PowerShell tracert”:

function Invoke-Tracert {
    param([string]$RemoteHost)

    tracert $RemoteHost |ForEach-Object{
        if($_.Trim() -match "Tracing route to .*") {
            Write-Host $_ -ForegroundColor Green
        } elseif ($_.Trim() -match "^\d{1,2}\s+") {
            $n,$a1,$a2,$a3,$target,$null = $_.Trim()-split"\s{2,}"
            $Properties = @{
                Hop    = $n;
                First  = $a1;
                Second = $a2;
                Third  = $a3;
                Node   = $target
            }
            New-Object psobject -Property $Properties
        }
    }
}

默认情况下,PowerShell会以列表形式格式化具有5个或更多属性的对象,但是您可以使用Format-Table获得类似于tracert的输出:

输入图像说明


你在这里绝对付出了额外的努力。干得好! - Mike Shepard

4

修复了“中等工资男子的Tracert”版本中的一些错误,对其进行了模块化,并添加了一些定制部分。@MrPaulch提供了一个很棒的PoC。

function Invoke-Traceroute{
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true,Position=1)]
        [string]$Destination,

        [Parameter(Mandatory=$false)]
        [int]$MaxTTL=16,

        [Parameter(Mandatory=$false)]
        [bool]$Fragmentation=$false,

        [Parameter(Mandatory=$false)]
        [bool]$VerboseOutput=$true,

        [Parameter(Mandatory=$false)]
        [int]$Timeout=5000
    )

    $ping = new-object System.Net.NetworkInformation.Ping
    $success = [System.Net.NetworkInformation.IPStatus]::Success
    $results = @()

    if($VerboseOutput){Write-Host "Tracing to $Destination"}
    for ($i=1; $i -le $MaxTTL; $i++) {
        $popt = new-object System.Net.NetworkInformation.PingOptions($i, $Fragmentation)   
        $reply = $ping.Send($Destination, $Timeout, [System.Text.Encoding]::Default.GetBytes("MESSAGE"), $popt)
        $addr = $reply.Address

        try{$dns = [System.Net.Dns]::GetHostByAddress($addr)}
        catch{$dns = "-"}

        $name = $dns.HostName

        $obj = New-Object -TypeName PSObject
        $obj | Add-Member -MemberType NoteProperty -Name hop -Value $i
        $obj | Add-Member -MemberType NoteProperty -Name address -Value $addr
        $obj | Add-Member -MemberType NoteProperty -Name dns_name -Value $name
        $obj | Add-Member -MemberType NoteProperty -Name latency -Value $reply.RoundTripTime

        if($VerboseOutput){Write-Host "Hop: $i`t= $addr`t($name)"}
        $results += $obj

        if($reply.Status -eq $success){break}
    }

    Return $results
}

3

我必须承认我想看看是否已经有人做过这个。

您可以使用 .Net Framework 作为 Powershell 脚本来实现一个“不太差的路由追踪”。

以下是一份快速但危险的入门指南。同时也没有统计数据。

# 
# Mid-Waged-Mans-Tracert
#

$ping = new-object System.Net.NetworkInformation.Ping
$timeout = 5000
$maxttl  = 64
$address = [string]$args
$message = [System.Text.Encoding]::Default.GetBytes("MESSAGE")
$dontfragment = false
$success = [System.Net.NetworkInformation.IPStatus]::Success

echo "Tracing $address"
for ($ttl=1;$i -le $maxttl; $ttl++) {
    $popt = new-object System.Net.NetworkInformation.PingOptions($ttl, $dontfragment)   
    $reply = $ping.Send($address, $timeout, $message, $popt)


    $addr = $reply.Address
    $rtt = $reply.RoundtripTime
    try {
        $dns = [System.Net.Dns]::GetHostByAddress($addr)
    } catch {
        $dns = "-"
    }

    $name = $dns.HostName

    echo "Hop: $ttl`t= $addr`t($name)"
    if($reply.Status -eq $success) {break}
}

编辑:

通过添加catch语句,移除了一些危险。唯一仍然存在的危险是我们每次只发送一个请求,这可能意味着我们由于无辜的包丢失而无法到达下一跳。 解决这个问题需要读者自行思考。 提示:(考虑嵌套循环)

额外:现在我们尝试获取每个跳点的DNS条目!


很棒的“本地”方法,太好了!也许可以解释一下其中的“危险”? :-) - Mathias R. Jessen
1
尽管存在危险,但缺乏冗余是主要问题(如果单个icmp消息丢失,我们将完全无法获得该特定跳数的结果),而且我们没有捕获PingException异常。 - MrPaulch

3

使用至少PS 5,您可以

Test-NetConnection stackoverflow.com -TraceRoute


1
有一个 Test-NetConnection 的别名叫做 tnc。在这种情况下,可以这样使用:tnc stackoverflow.com -t(pwsh 7)。 - NanoNova

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接