PowerShell 远程处理:控制目标版本(PowerShell Core 或 Windows PowerShell);跨平台远程处理的状态

mkl*_*nt0 4 powershell powershell-remoting winrm wsman powershell-core

这个自我回答的问题侧重于 Windows [1],解决了以下几个方面:

现在有两个PowerShell 版本- 传统的、仅限Windows 的 Windows PowerShell跨平台的 PowerShell Core,两者都可以安装在给定的 Windows 机器上:

  • 如何判断哪个 PowerShell 版本将执行远程命令,例如 via Invoke-Command -ComputerName

  • 我如何通过配置针对特定版本,包括临时的持久的

笔记:

对于要在给定机器上通过远程处理可定位的版本,必须将其设置为远程处理

  • 只有Windows PowerShell中自动设置为远程处理,但只能在服务器上运行Windows Server 2012或更高版本。

  • 从 v7 开始,PowerShell Core还没有随 Windows 一起提供;如果您使用的是官方安装程序,则可以选择在安装过程中启用远程处理。

在任何情况下,您都可以根据Enable-PSRemoting需要(重新)启用 PowerShell 远程处理,其中:

  • 必须从相应的版本运行。

  • 必须以管理权限运行


[1] 也就是说,问题集中在基于WinRM的远程处理上(WinRM 是 DTMF WSMan (WS-Management) 标准的 Windows 特定实现)。

至于使用 PowerShell Core进行跨平台远程处理

  • 您已经可以在所有平台上使用基于 SSH 的远程处理

    • 使用基于 SSH 的远程处理与基于 WinRM 的远程处理主要涉及相同的 cmdlet,但所涉及的参数不同;最值得注意的是,您通过-HostName参数而不是-ComputerName参数指定目标计算机。

    • 限制(从 v7 开始):“基于 SSH 的远程处理当前不支持远程端点配置和 Just Enough Administration (JEA)。”

  • 对于Unix 到 Windows远程处理Unix指的是 Unix 类平台,例如 macOS 和 Linux)——也就是说,从类 Unix 机器远程处理到 Windows 机器——您也可以使用基于 WinRM 的远程处理和附加配置:

    • 在 Windows 机器上:

      • 必须通过为 HTTPS 配置 WinRM 来启用 SSL 连接。
      • 如用户帐户要从般的Unix机器必须定义使用本地用户帐户在本地的域帐户将无法正常工作-管理员组。
    • 类 Unix 机器必须使用带有-Authentication Basic -UseSsl参数的远程处理 cmdlet 。

    • 查看about_Remote_Requirements

  • psl-omi-provider 存储库中正在处理基于 Unix WSMan 的实现,它已经使Linux机器能够充当远程处理目标(也就是说,服务器组件已经可用 - 我不清楚它是否也可以安装在macOS 上);然而,在撰写本文时,客户端组件尚未准备好投入生产。
    一旦客户端客户端组件可用,基于 WSMan 的统一跨平台远程处理将成为可能,无论是在类 Unix 机器(Linux、macOS)之间还是在类 Unix 机器和 Windows 机器之间。

mkl*_*nt0 6

注意:正在考虑更改默认情况下远程端点 PowerShell [Core] 的目标从 7.0 开始仍然是Window PowerShell):请参阅此 GitHub 问题


本地指定的远程会话配置决定了远程计算机上将使用的 PowerShell 版本(以及可能的版本)

  • Ad hoc,您可以使用远程 cmdlet的-ConfigurationName参数(例如Invoke-CommandNew-PSSession、 和 )Enter-PSSession来明确指定会话配置。

  • 持久地,通过配置,您可以通过首选项变量设置默认会话配置(链接的帮助主题还讨论了其他与远程会话相关的首选项变量,即和)$PSSessionConfigurationName$PSSessionApplicationName$PSSessionOption

    • 默认情况下,客户端连接到microsoft.powershell远程机器上的会话配置(见下文)。因此,您也可以在远程目标机器上更改此配置的定义,但请注意,这意味着所有使用默认值的客户端都将使用重新定义的配置- 有关如何实现此重新定义的信息,请参见底部。

在远程操作的目标计算机Get-PSSessionConfigurationcmdlet 列出客户端可用于连接的所有已注册会话配置,您可以使用Register-PSSessionConfiguration和管理这些配置Unregister-PSSessionConfiguration

  • 警告Get-PSSessionConfiguration必须在提升的会话中运行(以管理员身份),并且由于Windows PowerShell 5.1 中的错误,您可能必须首先运行以下虚拟命令:$null = Get-Command Test-WSMan,以确保wsman:驱动器已定义)。

  • 名称以'microsoft.powershell'为前缀的会话配置属于Windows PowerShell

  • 前缀'PowerShell.'是指 PowerShell Core

$PSSessionConfigurationName'http://schemas.microsoft.com/powershell/Microsoft.PowerShell'两个版本中默认为,这意味着Windows PowerShell默认针对远程计算机,即使您从 PowerShell Core 运行

  • Microsoft.PowerShell部分指的是(64 位)Windows PowerShell 会话配置,如Get-PSSessionConfiguration(以小写形式)列出的。

  • http://schemas.microsoft.com/powershell/前缀是可选的并且可以省略; 注意,使用https:的前缀并不能工作,将不会自动切换到基于SSL的运输; 对于后者,需要显式配置。请注意,如果所有远程处理都发生在 Windows 域中,则不需要基于 HTTPS/SSL 的远程处理。

要在远程计算机上定位 PowerShell Core (PowerShell v6+)

  • 通常,PowerShell Core会话配置是特定于版本的,您有两种选择:

    • 定位一个主要的PowerShell Core 版本- 例如PowerShell.7- 使用目标机器上安装的最新 v7.x 版本。

      • 这是可取的,因为您的代码不需要在每次在目标机器上安装补丁或次要版本更新时更新。
    • 针对特定版本 - 例如,PowerShell.7.1.2

      • 仅当您有多个共享相同主要版本的并行安装,并且您明确需要定位其中一个时,才执行此操作。
    • 同样,Get-PSSessionConfiguration提升的会话在目标机器上运行,会告诉您所有已注册会话配置的名称。

  • 要针对 PowerShell Core ad hoc,请使用-ConfigurationName PowerShell.7,例如:

# Connect to computer $comp and make it execute $PSVersionTable 
# in PowerShell Core v7.x, which tells you what PowerShell edition 
# and version is running.
Invoke-Command -ComputerName $comp -ConfigurationName PowerShell.7 { $PSVersionTable }
Run Code Online (Sandbox Code Playgroud)
  • 默认以 PowerShell Core 为目标,持久地,从给定的客户端机器,将如下内容添加到您的$PROFILE文件中:
# When remoting, default to running PowerShell Core v7.x on the
# the target machines:
$PSSessionConfigurationName = 'PowerShell.7'
Run Code Online (Sandbox Code Playgroud)
  • 让给定远程服务器机器的所有客户端默认情况下始终以PowerShell Core目标,您必须重新定义服务器的microsoft.powershell会话配置,这需要管理权限;您可以修改以下代码段:
# Run WITH ELEVATION (as administrator) and
# ONLY IF YOU UNDERSTAND THE IMPLICATIONS.

$ErrorActionPreference = 'Stop'

# The configuration whose definition you want to make the new default.
$newDefaultConfigSource = 'PowerShell.7'

# Standard registry locations and names.
$defaultConfigName = 'Microsoft.PowerShell'
$configXmlValueName = 'ConfigXml'
$configRootKey = 'registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WSMAN\Plugin'

# Rename the current default configuration XML to "ConfigXml.OLD" to keep a backup.
Rename-ItemProperty $configRootKey\$defaultConfigName $configXmlValueName -NewName "$configXmlValueName.OLD"

# Get the configuration XML from the configuration that should become the new default.
# Modify it to replace the source configuration name with the default configuration name.
$xmlText = (Get-ItemPropertyValue $configRootKey\$newDefaultConfigSource $configXmlValueName) -replace 
             ('\b{0}\b' -f [regex]::Escape($newDefaultConfigSource)), $defaultConfigName

# Save the modified XML as the default configuration's config XML.
Set-ItemProperty $configRootKey\$defaultConfigName $configXmlValueName $xmlText

# Restart the WinRM service for changes to take effect.
Restart-Service WinRM
Run Code Online (Sandbox Code Playgroud)