前言
使用ssh连接操控linux主机是很常见的做法,但在win系统却比较少
刚好业务有需求,所以记录下为win10系统搭建ssh server的方法
win11可用,操作相同
安装ssh服务
找到3种安装方法,进行三选一即可
推荐直接使用“系统-界面安装即可”
综上
建议使用“系统-界面安装”重启,如果不行考虑“外部-Github安装”
系统-界面安装(优先尝试)
在网上最多的方法,win10已经集成openssh,客户端已安装,服务端是可选件
参考文章:win10/11 安装ssh并作为服务器使用-腾讯云开发者社区-腾讯云
但是发现不同版本有差异,添加可选功能的位置不同,可以都看看
- 应用 -> 应用和功能 -> 可选功能
- 系统 -> 可选功能
或者直接在win搜索框搜索“可选功能” -> 添加可选功能,选择 openssh服务端安装重启
安装完务必在“服务”,查看“OpenSSH SSH Server”、“OpenSSH Authentication Agent”
右键启动,右键属性改为自动启动
额外
可以打开开发者选项:更新和安全 -> 开发者选项 -> 开发人员模式按钮
据说虽然不影响主流程,但是在某些权限问题上会减少错误
系统-命令行安装(仅供参考)
管理员启动powershell执行
安装
# 查看ssh client、server安装情况
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
# 安装 OpenSSH 客户端
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
# 安装 OpenSSH 服务器
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
# 设置自启动
Set-Service -Name sshd -StartupType 'Automatic'
# 启动服务
Start-Service sshd
检查状态
# 查看服务状态
Get-Service sshd | Select-Object Name, StartType, Status
# 查看22端口是否在监听
netstat -ano | findstr :22
检查防火墙
# 防火墙是否放行(安装完一般会有,不用管)
Get-NetFirewallRule -Name *OpenSSH-Server* | select Name, DisplayName, Description, Enabled
# (可选)手动添加放行22入站端口
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
额外(如需卸载)
#卸载服务端(需要重启)
Remove-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
外部-Github安装(最后方案)
Releases · PowerShell/Win32-OpenSSH
上面的系统方式,无论是界面还是命令行,他们都可能有奇怪的bug,比如:安装失败、安装成功但无法启动等等
可以尝试卸载掉后,去Github直接下载msi安装包手动安装
下载win64的msi安装,安装后在“服务”可以找到,为已运行状态,并且已经配置好自动启动
额外说明
使用此方法安装的sshd,以下检测命令无效
# 此命令会显示未安装,因为不是通过系统安装的
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
连接ssh服务
确定本机账户密码(重要)
win10的ssh连接账户密码有大坑!!
需要清楚以下概念:
本地账户:本地文件系统的账户,打开cmd,默认在 C:\Users\26211>,那么本地账户就是26211
微软账户:登录此笔记本的微软账户,在系统-账户里可以看到,一般是个邮箱
假设
-
本地账户:26211、2333(屏幕解锁密码)
-
微软账户:12345@qq.com、abc123
那么ssh连接就是:本地账户+微软密码
也就是在ssh连接工具要填写,用户=26211,密码=abc123
连接本机测试
知道规则是 本地账户+远程密码后
打开cmd
# 尝试连接本机
ssh summer@127.0.0.1
# 输入密码:abc123
如果没有提示密码错误,之后成功会闪一下,cmd刷新,顶部栏变成是 conhost.exe
这样就已经算是连接上了
拓展配置
配置免密登录
- 配置允许密钥登录
打开编辑 C:\ProgramData\ssh\sshd_config
# 确保以下2条没有被注释
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
# 确保以下2条有注释掉
#Match Group administrators
#AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
保存后在powershell重启服务
Restart-Service sshd
- 确保ssh-agent服务正常运行
打开服务,找到 OpenSSH Authentication Agent,查看是否已启用并正在运行
- 将客户端密钥加入服务端
(可选)如果没有公钥,使用 ssh-keygen -t rsa 然后一直回车即可生成
客户端公钥位置:C:\Users\summer\.ssh\id_rsa.pub(此电脑用户是summer,其他电脑酌情修改)
将其复制一份出来,改名为 authorized_keys,然后上传到服务端同目录(.ssh下)即可
(可选)如果有多台机器需要免密登录不想覆盖
可以把客户端id_rsa.pub的内容复制出来,追加到服务端的authorized_keys
额外
- 如果服务端变动,重装了ssh server
如果服务端重装系统或者重新配置ssh server,则客户端需要清理此文件后再试
C:\Users\summer\.ssh\known_hosts
- 如果还要输密码,再看看文章,里面讲到一个.ssh文件夹权限的问题
Windows配置ssh免密码登录 - 猴子吃桃_Q - 博客园
修改默认shell
默认ssh连接到win的默认shell是cmd,功能较弱,建议修改为git bash或者powershell
我选择git bash,因为可以使用如cat、find、grep等 linux bash命令,并且git bash兼容cmd命令,但是不兼容powershell
可以把git bash作为默认shell,当需要执行powershell命令时,命令行输入powershell回车切换,执行完可以命令行输入bash切回来(前提是把git bash配置进了环境变量)
git bash
前提条件:1.安装git(自带git bash)、2.配置bash进环境变量
我的Git安装在D:\Code\Env\Git,bash位置在其下 bin\bash.exe
将 D:\Code\Env\Git\cmd 、D:\Code\Env\Git\bin 加入系统Path变量
然后就可以在powershell执行以下命令,把bash设置为默认ssh shell
(警告:一定要确保路径没有填错,否则ssh将彻底连接不上)
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "D:\Code\Env\Git\bin\bash.exe" -PropertyType String -Force
- 添加中文支持
ssh登录bash后会发现不支持中文,用记事本打开在Git安装目录下的 etc\bash.bashrc,末尾追加:
export LANG="zh_CN.UTF-8"
重启ssh终端连接后,可以显示中文了
- 兼容cmd的 /xx 格式参数
例如 taskkill /f /im nginx* 在cmd、powershell都是正常的
但是在git bash,会把命令里的/f、/im理解成路径,毕竟linux里/就是路径分隔符
临时解决方法:
# 方法1:对此命令不把 / 解释为路径分隔符
MSYS_NO_PATHCONV=1 taskkill /f /im nginx.exe
# 方法2:转义
taskkill //f //im nginx.exe
永久解决方法:
用记事本打开在Git安装目录下的 etc\bash.bashrc,末尾追加:
alias taskkill=MSYS_NO_PATHCONV=1 taskkill
相当于取别名,为此命令永久添加 MSYS_NO_PATHCONV=1 前缀
powershell
简单,执行1行命令即可
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force
powershell 7
powershell7需要手动安装,要去官网下载,相比系统自带的powershell(一般是5.1.xx版本),功能更加强大,支持命令提示,可以尝试
如果想把pwsh7设置为ssh默认shell,可以执行以下命令设置
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Program Files\PowerShell\7\pwsh.exe" -PropertyType String -Force
使用技巧:
使用 bash -c "<bash才支持的命令>",可以在pwsh中执行bash才能执行的类linux命令
ssh终端管理员权限
在ssh终端使用此命令检测当前是否为管理员权限:
# true 为拥有管理员权限
([Security.Principal.windowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
发现ssh连接已经是管理员权限,无需配置(ssh自带管理员?)
允许远程执行脚本
默认我们不允许在远程终端执行脚本,可以配置开启
管理员模式启动 powershell(或者通过ssh终端-默认shell为powershell后)
# 查看执行策略,默认是 Restricted(禁止脚本运行)
Get-ExecutionPolicy
# 修改为允许运行脚本
Set-ExecutionPolicy RemoteSigned
# 此时应该可以运行了
.\test.ps1
永久运行程序(nohup)
在ssh终端启动的进程,会随着ssh终端关闭而销毁
而 win 下没有 linux 那样的 nohup 命令,但是可以使用“计划任务”达到类似效果
以常驻运行dufs文件服务器为例:
启动计划任务有两种方式(二选一):
-
命令方式:直接把运行命令写入 /tr 参数后,双引号括起来
-
脚本方式:复杂命令可以写入ps1脚本,使用powershell运行
# (脚本方式) 启动一个计划任务:执行运行dufs的脚本
schtasks /create /tn "DufsService" /tr "powershell -ExecutionPolicy Bypass -File E:\dufs.ps1" /sc onstart /ru SYSTEM /f
# (命令方式) 启动一个计划任务:执行运行dufs的命令
schtasks /create /tn "DufsService" /tr "dufs E:\share --allow-upload --allow-search --allow-archive --assets 'D:\Program Files\dufs\dufs-material-assets'" /sc onstart /ru SYSTEM /f
# 立刻启动计划任务
schtasks /run /tn "DufsService"
# 查看是否创建成功
schtasks /query /tn "DufsService"
tasklist | findstr dufs
# 查看是否创建成功(详细,可看见创建时的命令行)
schtasks /query /tn "DufsService" /v /fo list
关闭ssh终端,发现dufs文件服务仍正常运行,试验成功
需要销毁时:
# 停止程序
taskkill /f /im dufs*
# 销毁创建的计划任务
schtasks /delete /tn "DufsService" /f