Yet Another Invoke-SSH PowerShell Function (thanks PS Fab)

As part of a writing a decommission server PowerShell script at work, I had a requirement for a quick and easy SSH function to connect to our NetBackup server at work and remove the server from the backup system (Symantec if you’re reading this, please can we have a PowerShell module? *wishful thinking*…). Not quite needing the entire functionality provided by this module (based on the SSH.NET Library), I came across a function on PS Fab. One fantastic thing about this function is that supports the automatic acceptance of an SSH key when you connect to a host for the first time.

I made a few changes to the code, amended comments that referenced plist rather than plink and put it into a more standard function form with examples (that you might be able to add to an existing library). This is the result:

Function Invoke-SSH 
{
	<#
	.SYNOPSIS 
	Uses Plink.exe to SSH to a host and execute a list of commands.
	.DESCRIPTION
	Uses Plink.exe to SSH to a host and execute a list of commands.
	.PARAMETER hostname
	The host you wish to connect to.
	.PARAMETER username
	Username to connect with.
	.PARAMETER password
	Password for the specified user account.
	.PARAMETER commandArray
	A single, or list of commands stored in an array object.
	.PARAMETER plinkAndPath
	The location of the plink.exe including the executable (e.g. F:\tools\plink.exe)
	.PARAMETER connectOnceToAcceptHostKey
	If set to true, it will accept the remote host key (use when connecting for the first time)
	.EXAMPLE
	Invoke-SSH -username root -hostname centos-server -password Abzy4321! -plinkAndPath "F:\tools\plink.exe" -commandArray $commands -connectOnceToAcceptHostKey $true
	.EXAMPLE
	Invoke-SSH -username root -hostname centos-server -password Abzy4321! -plinkAndPath "F:\tools\plink.exe" -commandArray ifconfig -connectOnceToAcceptHostKey $true
	.NOTES
	Author: Robin Malik
	Source: Modified from: http://www.zerrouki.com/invoke-ssh/
	#>
	
	Param(
		[Parameter(Mandatory=$true,HelpMessage="Enter a host to connect to.")]
		[string]
		$hostname,
		
		[Parameter(Mandatory=$true,HelpMessage="Enter a username.")]
		[string]
		$username,
		
		[Parameter(Mandatory=$true,HelpMessage="Enter the password.")]
		[string]
		$password,
		
		[Parameter(Mandatory=$true,HelpMessage="Provide a command or comma separated list of commands")]
		[array]
		$commandArray,
		
		[Parameter(Mandatory=$true,HelpMessage="Path to plink (e.g. F:\tools\plink.exe).")]
		[string]
		$plinkAndPath,
		
		[Parameter(HelpMessage="Accept host key if connecting for the first time (the default is `$false)")]
		[string]
		$connectOnceToAcceptHostKey = $false
	)
	
	$target = $username + '@' + $hostname
	$plinkoptions = "-ssh $target -pw $password"
	 
	# On first connect to a host, plink will prompt you to accept the remote host key. 
	# This section will login and accept the host key then logout:
	if($ConnectOnceToAcceptHostKey)
	{
		$plinkCommand  = [string]::Format('echo y | & "{0}" {1} exit', $plinkAndPath, $plinkoptions )
		$msg = Invoke-Expression $plinkCommand
	}
	
	# Build the SSH Command by looping through the passed value(s). Append exit in order to logout:
	$commandArray += "exit"
	$commandArray | % { $remoteCommand += [string]::Format('{0}; ', $_) }
	
	# Format the command to pass to plink:
	$plinkCommand = [string]::Format('& "{0}" {1} "{2}"', $plinkAndPath, $plinkoptions , $remoteCommand)
	 
	# Execute the command and display the output:
	$msg = Invoke-Expression $plinkCommand
	Write-Output $msg
}

Copy and paste this function into a PowerShell window, and then test it with the below code (changing where appropriate of course):

$plinkAndPath = "F:\tools\plink\plink.exe"
$username = "root"
$password = "Adk3453#5341!"
$hostname = "centos-server"
# Commands to execute:
$Commands = @()
$Commands += "ifconfig"
$Commands += "ls"
Invoke-SSH -username $username -hostname $hostname -password $password -plinkAndPath $plinkAndPath -commandArray $Commands -connectOnceToAcceptHostKey $true

4 thoughts on “Yet Another Invoke-SSH PowerShell Function (thanks PS Fab)

  1. Hi, thanks for the post.
    Is there a way to retrieve this information as properties with invoke-ssh?
    It returns the correct info but it is impossible to to parse the text to get what you want..

    Thanks

    1. Not unless you write your own custom text parsing function to create objects from the returned text. It’s a pain, but you can usually get what you want with parsing. Make sure you error handle appropriately because if the output isn’t what you expect then things are likely to go wrong…

  2. Hey
    I copied you script to my environment. but i get the folowing error
    “plink.exe : New Server Encountered
    At line:1 char:10”
    I believe that the -connectOnceToAcceptHostKey didn’t work for some reason

    1. Hi Lena,

      There isn’t enough information to help you troubleshoot this. Please provide your PowerShell version, operating system you’re running on, what version of plink you’re using, and post the entire script with your modifications (including the line you’re specifying to run the function) to pastebin or gist.github so I can help :)

      The PowerShell team are looking to support SSH natively at some point. You can read about this here: https://blogs.msdn.microsoft.com/powershell/2015/10/19/openssh-for-windows-update/

      Thanks,
      Robin

Leave a Reply