Nevets82 / Posh-Cisco

PowerShell module that provides some functionality to facilitate automating backup actions of a Cisco device over SSH. This module also provides some basic functionality for troubleshooting Cisco devices.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Timout when wait for action when is "more" prompt

Wolvverine opened this issue · comments

You have to turn off pagination and question whether to show more.

terminal datadump
show running-config

I rewrote the Get-CiscoSSHResponse function to use ShellStream if you're interested. It's largely lifted from this post by MKANET. Some of the things I included were removal of the input command and removal of the new console input line at the start and end of the return as well as avoiding infinite loops in case of empty returns.

It's quite a bit slower than the original function as the only way I figured out how to handle empty responses was via arbitrarily determined timeout, but does work.

function Get-CiscoSSHResponse
{
    [OutputType([String])]
    param
    (
		[Parameter(Mandatory=$true)]
		[String]$HostAddress,
		[Parameter(Mandatory=$false)]
		[Int]$HostPort = 22,
		[Parameter(Mandatory=$true)]
		[PSCredential]$Credential,
		[Parameter(Mandatory=$false)]
		[Switch]$AcceptKey,
		[Parameter(Mandatory=$true)]
		[String]$Command,
		[Parameter(Mandatory=$false)]
		[String]$StripHeaderAt = $null
    )

    $SSHSession = New-SSHSession -ComputerName $HostAddress -Port $HostPort -Credential $Credential -AcceptKey:$AcceptKey;
    $SSHStream = $SSHSession.Session.CreateShellStream("dumb", 0, 0,0, 0, 10000) #increased the buffer size to handle long returns from sh run/start
        
    if ($SSHSession.Connected)
    {
        $SSHStream.Read() | Out-Null
        # Retrieve the hostname of the device. Needed if using IP instead of host name to connect
        $SSHStream.Write("sh run | include hostname`n")
        Sleep -Milliseconds 2000 # Needs a timeout to return the running-config completely
        $HostNameRaw = ($SSHStream.Read() -split "`r`n") | %{$_.trim()}
        
        foreach ($line in $HostNameRaw) {
            if ($line -match "^hostname.*") {
                $HostName = ($line -split " ")[-1]
            }
        }
        
        $SSHStream.Write("terminal Length 0`n"); # remove the --more-- prompting
        Sleep -Milliseconds 100
        $SSHStream.Read() | Out-Null
        $SSHStream.Write($Command + "`n");
        $ResultRaw = $SSHStream.Read()

        # Remove first line (input command)
        $Input, $Result = $ResultRaw -split "`r`n" | %{$_.trim()}
        
        # Wait until either a return or new console input line appears
        while(!$Result) {
            Sleep -Milliseconds 100
            $ResultRaw = $SSHStream.Read()
            $Input, $Result = $ResultRaw -split "`r`n" | %{$_.trim()}
        }
        # Iterate over Read() until console is a new input line or 3 seconds if no return
        $counter = 0
        while (($Result[$Result.Count - 1] -ne "$($HostName)#") -and ($counter -lt 30)) {
            sleep -Milliseconds 100
            $counter++
            $ResultRaw = $SSHStream.Read()
            $Result = $ResultRaw -split "`r`n" | %{$_.trim()}
        }
        # Remove last line (empty console input line)
        return $Result[0..($Result.Length-2)];
    }
    else
    {
        throw [System.InvalidOperationException]"Could not connect to SSH host: $($HostAddress):$HostPort.";
    }
    
    $SSHSessionRemoveResult = Remove-SSHSession -SSHSession $SSHSession;

    if (-Not $SSHSessionRemoveResult)
    {
        Write-Error "Could not remove SSH Session $($SSHSession.SessionId):$($SSHSession.Host).";
    }
}