First, PowerShell Core have to be installed on every target Linux machine and added to its /etc/ssh/sshd_config:

Subsystem powershell /usr/bin/pwsh -sshs -NoLogo -NoProfile

Probably, in a script you have the remote session to that target box started like:

$s = New-PSSession -HostName $deployHostname -UserName $login -KeyFilePath $keyfile

If you have to execute a sudo command in that session, you could do like:

Invoke-Command -Session $s {
Invoke-Expression "sudo ..."
}

Imagine you put your script into CI / CD pipeline and want to see its output in a log. In case of failure of a command invoked like shown above, probably, you’ll be frustrated with the error output like this:

NotSpecified: (:String) [], RemoteException
script returned exit code 1

Such useless output originate from the fact that fail happens in a remote session. You can’t cope with that by just adding a conversion of an output error to exception with -ErrorAction Stop parameter for Invoke-Expression, because the output of the invoked shell command is not a PowerShell error output.

But throwing exceptions is the right way of passing errors. So, the working solution includes writing output to a file and throwing its content with the exception this way:

Invoke-Command -Session $s {
$errFile = "/tmp/$($(New-Guid).Guid).err"
Invoke-Expression "sudo ... 2>${errFile}" -ErrorAction Stop
$err = Get-Content $errFile -ErrorAction SilentlyContinue
Remove-Item $errFile -ErrorAction SilentlyContinue
If (-Not $null -eq $err)
{
throw $err
}
}

Perfect, but has too many lines of code for just copying and pasting it all over the script. So, let’s introduce a function:

function Invoke-SudoCommand {
<#
.SYNOPSIS
Invokes sudo command in a remote session to Linux
#>
param (
[Parameter(Mandatory=$true)]
[PSSession]
$Session,
[Parameter(Mandatory=$true)]
[String]
$Command
)
Invoke-Command -Session $Session {
$errFile = "/tmp/$($(New-Guid).Guid).err"
Invoke-Expression "sudo ${using:Command} 2>${errFile}" -ErrorAction Stop
$err = Get-Content $errFile -ErrorAction SilentlyContinue
Remove-Item $errFile -ErrorAction SilentlyContinue
If (-Not $null -eq $err)
{
throw $err
}
}
}

Using this function you can invoke sudo commands with a single line of code:

Invoke-SudoCommand -Session $s -Command "..."

Script variables can also be used:

Invoke-SudoCommand -Session $s -Command "rm -rf ${targetFolder}"
Invoke-SudoCommand -Session $s -Command "unzip ${zipName} -d ${targetFolder}"

PowerShell allows you to wrap things in a pretty neat way, isn’t it?

Guessing can you use this function inside of a 1st level remote session to execute the sudo commands in the nested remote sessions? Sure, export a function to the remote session and invoke it there. Look in this repository for the implementation and usage of Export-FunctionRemote.