摘要:本文介绍如何实现通过 SSH 远程连接到 PowerShell。其使用场景主要在 Linux 环境下远程访问 Windows 下的 PowerShell,从而能够将 Windows 的相关操作和部署脚本自动化。
本文主要参考微软官方文档:PowerShell Remoting Over SSH,同时介绍在配置过程中遇到的问题。该文档十分详细,并且介绍了各种操作系统之间的配置,这里我们主要介绍 Windows 作为服务器,Linux 作为客户端的场景。
另外这篇文章Configure SSH-based PowerShell Core remoting between Windows and Linux也比较详细,可以对比参考。
安装 PowerShell Core for Windows
目前最新的 Windows 已经集成了 PowerShell,但是这里还是需要单独安装一份,因为这个 PowerShell 将会配置为 SSH 的子系统。而且新安装的 PowerShell 和内置的是独立。
单独安装的好处:
- 版本统一,我们可以使用当前 GitHub 最新的 PowerShell,并且在客户端和服务器端部署一致的版本。
- 配置简单,不需要知道内置的 PowerShell 的属性。
安装过程很简单,一般情况下我们字需要到 GitHub 的 Release 页面上下载 MSI 安装包 PowerShell-版本号-win-x64.msi,直接下一步就可以了。
默认安装完成后我们会在 C:\Program Files\PowerShell\6-preview 路径下看到 PowerShell 的相关文件。最后一层文件夹是版本号。
安装完成后,我们需要测试一下是否支持 SSH Remoting
1 | Get-Command New-PSSession -syntax |
预期的结果应该包含:
1 | New-PSSession [-HostName] <string[]> [-Name <string[]>] [-UserName <string>] [-KeyFilePath <string>] [-SSHTransport] [<CommonParameters>] |
安装 Win32 OpenSSH
通过 GitHub 的 Release 页面上下载 ZIP,解压到指定文件夹,一般为:C:\Program Files\OpenSSH。
然后通过参考官方安装文档 Install Win32 OpenSSH 进行安装,这里使用命令行进行安装
执行安装 PowerShell 脚本
1 | powershell.exe -ExecutionPolicy Bypass -File install-sshd.ps1 |
配置防火墙
1 | # Windows 2012 above |
启动服务,并且配置自动启动
1 | net start sshd |
配置 sshd
这一步是最关键的,也是最容易报错的。
基础配置项
在 Windows 环境下,sshd 的配置文件和相关的证书日志,都会存放在 C:\ProgramData\ssh 下,这点需要注意,安装路径存放这一份默认的配置,这个只是为了恢复使用的。官方的安装手册的第7条有介绍:
To use existing customized sshd_config, you need to copy it from binary location to %programdata%\ssh\sshd_config (Note that %programdata% is a hidden directory).
使用 password authentication
1 | PasswordAuthentication yes |
使用 key authentication (可选)
1 | PubkeyAuthentication yes |
配置子系统
1 | Subsystem powershell c:/program files/powershell/6.0.4/pwsh.exe -sshs -NoLogo -NoProfile |
这里需要说明,如果遇到问题,可以是因为配置子系统的路径中有空格导致,这也是一个目前还是 Open 的 Issue。可以通过创建 symlink 来解决这个问题。
首先我们将原始 PowerShell 的安装路径创建一个 symlink,这里注意,如果在 PowerShell 中执行 mklink 需要加 cmd /c 因为这个执行不是 PowerShell 的,参考该回答。
1 | cmd /c mklink /D c:\pwsh "C:\Program Files\PowerShell\6-preview" |
然后我们就用 symlink 来配置子系统,这样就排除了空格的问题。
1 | Subsystem powershell c:\pwsh\pwsh.exe -sshs -NoLogo -NoProfile |
https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH
重启服务
1 | Restart-Service sshd |
问题排查
我们一般通过开启调试日志的方式调试 sshd,官方有专门的 Troubleshooting 页面,一般我们开启调试配置。
删除原有的日志文件,在配置文件 sshd_config 增加如下条目
1 | SyslogFacility LOCAL0 |
然后重启
1 | Stop-Service sshd |
这时候访问就会产生日志文件,写入 log 文件夹中。
Linux 客户端配置
本人使用 Fedora,其他的发行版基本是一样的。
首先在 Linux 上安装 PowerShell, 参考该文:Installing PowerShell Core on Linux。
Ubuntu, Debian
1 | sudo apt-get install -y powershell |
CentOS, RedHat1
2sudo yum install -y powershell
sudo yum install -y powershell-preview
OpenSUSE1
2sudo zypper install powershell
sudo zypper install powershell-preview
Fedora1
2sudo dnf install -y powershell
sudo dnf install -y powershell-preview
安装好后就可以使用 PowerShell,直接使用 pwsh 命令进入 PowerShell 的命令行窗口。
然后使用如下指令远程连接到服务器:
1 | Enter-PSSession -HostName [IP or HostName] -UserName Administrator |
当然按照官方文档所述,还可以定义 $session 变量,然后通过变量登陆。
1 | $session = New-PSSession -HostName UbuntuVM1 -UserName TestUser |
常见问题
subsystem request failed on channel 0
检查 sshd 的子系统的配置,有可能是空格问题,使用 symlink 配置。
sshd 日志:CreateProcessAsUser failed error:1314
“To resolve this problem, you’ll need to elevate the rights of the account calling CreateProcessAsUser with the “Replace a process level token” right. To do so, open the Control Panel / Administrative Tools / Local Security Policy and add the user account to the “Replace a process level token” right. (You may have to logout or even reboot to have this change take effect.)”
主要就是在 Control Panel / Administrative Tools / Local Security Policy 找到 Replace a process level token 权限,然后将需要远程连接的用户的加入到这个权限中. 需要重启电脑.

总结
通过这个配置,我们就可以针对 Windows 服务器进行 Devops,比如 GitLab 就支持执行 PowerShell 脚本,参考:Shells supported by GitLab Runner