从 Sunshine 到平板 SSH:一次远程连接折腾
陈淮锐 · 2026 年 9 月搭建 · 10 月 2 日补充 iPhone 接入 · Windows 11 × vivo Pad × iPhone
GitHub · 0hello-bit/better_todesk我一开始只是想在平板上看到电脑画面,顺便操作电脑。电脑装 Sunshine,平板装 Moonlight,看起来应该配个对就能开始。结果先卡在了“电脑上到底装没装好”,后面又一路折腾到了平板的 SSH 和开机自启动。
这次主要由我提出需求、处理平板上的授权,Codex 在电脑端协助检查、安装和验证。写下来的不是一套每台安卓设备都能照搬的教程,而是这台 Windows 笔记本和 vivo Pad 实际走过的一次过程。
先交代结果:Sunshine 与 Moonlight 已完成配对,电脑主屏、副屏可以在平板上用快捷键切换,触控移动鼠标的回传也已验证。平板 SSH 已连通,息屏后连接和一次真实重启后的自启动都验证过。目前是一次显示一个屏幕,不是双屏并排;实际帧率、操作延迟、温度和长期耗电还没有测量。
文件夹叫 Sunshine,不代表程序已经装好
最开始,我看到电脑里有一个 Sunshine 文件夹,就以为已经安装好了。检查以后才发现,里面主要是虚拟手柄驱动和辅助工具,没有 sunshine.exe,也没有正在运行的 Sunshine 主服务。
当时的目录不具备运行条件,至于是安装未完成还是卸载残留,已有记录无法确定。
我决定重新安装,结果又遇到一个很具体的问题:services 文件夹删不掉。原因找到了,里面的 libvirtualhid_broker.exe 还作为后台服务运行,文件被占用着。停止并移除这个旧服务以后,才继续安装完整程序。
这台电脑是 Windows 11 64 位,带 Intel Iris Xe 核显和 NVIDIA RTX 4060 Laptop GPU。最终使用的是官方 Windows AMD64 安装包,版本 2026.914.233613。这里的 AMD64 指 x86-64 架构,并不是说只有 AMD 处理器能用。安装前核对了下载文件与官方发布的 SHA-256。
安装后分别检查了主程序、自动运行的 Sunshine 服务、防火墙规则,以及本机管理页面。管理页面返回 HTTP 200,日志找到了 H.264、HEVC 和 AV1 的 NVENC 编码器。
这些结果说明电脑端具备继续配对的条件。它们还不能说明平板已经收到画面,更不能代替实际串流的帧率和延迟测试。
串流和 SSH 走的是相反方向
接下来我想试试,能不能从电脑 SSH 到平板。这里其实有两条方向不同的连接:
| 连接 | 用来做什么 | 这次的结果 |
|---|---|---|
| 平板 Moonlight → 电脑 Sunshine | 查看电脑画面、发送操作输入 | 已配对,主副屏切换、画面与鼠标移动回传已验证 |
| 电脑 SSH → 平板 Termux | 执行终端命令、管理 Termux 环境 | 已实际登录 |
| 电脑 ADB → 平板 | 经 USB 调试授权,协助安装和配置 | 已授权并使用 |
局域网里确实找到了主机名为 vivo-Pad 的设备,也能收到网络响应。但能找到 IP 和能 SSH 登录,是两回事。那时平板还没装 Termux,也没有配置 SSH 服务。
后来我用 USB 连上平板,开启调试。电脑能识别到 Android ADB Interface,安装官方 Android Platform Tools 以后,ADB 设备列表显示为 device,这才确认调试通道已经授权可用。
中间还有一次很普通、但容易误判的失败:安装 Termux 时返回了 INSTALL_FAILED_ABORTED: User rejected permissions。下载完 APK 不等于装好了,USB 调试授权也不等于所有安装确认都会自动通过。处理平板上的安装许可后,重新安装才返回 Success。
先让 SSH 真正连起来
这次安装的是 GitHub 官方渠道的 Termux 0.118.3 ARM64 版本,随后在它的环境里安装 OpenSSH。通过已经授权的 USB 调试通道完成初始配置,把电脑的 SSH 公钥放进平板的 authorized_keys,私钥仍留在电脑上。
SSH 使用 Termux 常见的 8022 端口,开启公钥认证,关闭密码和键盘交互认证。电脑端保存了一个 vivopad 别名,以后连接时不用反复输入地址、用户名和端口:
ssh vivopad
第一次真正的验证走的是 Wi-Fi,而不是 ADB 转发:登录以后读取了用户名、处理器架构和设备型号,返回了 Termux 用户、aarch64 和这台平板的型号 PA2170。随后还核对了主机密钥指纹与 SSH 配置。
文章不放实际内网 IP、设备序列号和密钥内容。内网地址本身也可能随路由器分配而变化;如果以后别名连不上,要先看平板地址是否变了。
SSH 登录后进入 Termux 的应用环境,不会因此获得安卓 root 权限或整个平板屏幕的控制能力。
不想每次手动开 Termux,还得处理后台
能登录以后,我又想省一步:平板不必一直停在 Termux 界面,最好重启之后也能自己把 SSH 开起来。
这件事不能只安装一个开机插件。安卓本身有省电限制,vivo 还提供了额外的后台启动管理。最后做了几层设置:
- 安装与 GitHub 版 Termux 来源匹配的 Termux:Boot
0.8.1,并打开一次,启用它的开机处理。 - 把 Termux 和 Termux:Boot 加入电池优化白名单,允许后台运行。
- 在 vivo 的“自启动”页面,开启 Termux 的“后台启动”,以及 Termux:Boot 的“开机启动、后台启动”。
- 在
~/.termux/boot/下放入启动脚本,获取后台唤醒锁、启动 SSH,并记录执行时间。
脚本整理如下。路径是 Termux 的应用路径,不是电脑上的路径:
#!/data/data/com.termux/files/usr/bin/sh
export PATH=/data/data/com.termux/files/usr/bin:/system/bin
export HOME=/data/data/com.termux/files/home
mkdir -p "$HOME/.termux"
exec >> "$HOME/.termux/ssh-boot.log" 2>&1
date -Iseconds
termux-wake-lock
if ! pgrep -x sshd >/dev/null; then
sshd
fi
termux-wake-lock 的目的,是让后台任务尽量不因设备休眠而停止,并不是让屏幕常亮。系统检查中能看到 Termux 持有的部分唤醒锁。代价也很直接:会增加耗电。
脚本只在启动时检查 SSH 是否运行。如果服务随后崩溃、应用被强行停止或被系统回收,它不会持续监测并自动恢复。
第一次以为重启了,运行时间却对不上
配置完成后,我先退回桌面,又息屏试了一次。SSH 都能连接。
但在一次被当作“重启后测试”的检查里,uptime 返回系统已经运行了 8 小时 54 分钟,启动日志也没有新增。这就不能算重启自启动通过,只能说明当时的后台连接仍然活着。
真正重启以后,又检查了一次。2026 年 9 月 24 日 18:17:32 的连接结果显示:
18:17:32 up 1 min
启动脚本日志也新增了一条:
2026-09-24T18:16:40+08:00
这次没有通过电脑手动启动 SSH,就能再次经 Wi-Fi 登录。系统运行时间、启动脚本的新记录、实际登录结果三项对上,才确认了这一次真实重启后的 SSH 自启动成功。
这次没有验证首次解锁前的连接,也没有覆盖整夜待机或多轮重启。日常先按“重启后解锁一次,再连接”的流程使用。
回到最初的目标,先把画面传过来
后来也回到了最初的目标:安装官方 Moonlight 12.2 免 Root 版,通过 Sunshine 页面输入 PIN 完成配对,进入 Desktop。平板截图实际显示了电脑浏览器中的这篇文章,Sunshine 日志确认建立了 HEVC 硬件编码会话。一次平板横向滑动让电脑鼠标横坐标改变、纵坐标不变,确认输入确实传回了电脑;我也确认了画面和操作正常。
画面正常以后,我又发现一个问题:电脑有两个屏幕,平板却只显示主屏。我的需求其实不复杂,不需要把两块屏幕挤在一起,只要一次看一个、需要时能切过去就行。平板也有实体键盘,正好可以使用 Sunshine 的切屏快捷键。
快捷键收到了,副屏却没正常出图
检查显示输出以后,发现两块屏幕虽然都是 1920 × 1080,却接在不同显卡上:主屏由 NVIDIA RTX 4060 Laptop GPU 驱动,副屏属于 Intel Iris Xe 核显。
在原来的 HEVC / NVIDIA 硬件编码会话里,切屏指令确实触发了,但切到核显屏幕后,日志反复出现:
NvEncOpenEncodeSessionEx() failed: NV_ENC_ERR_NO_ENCODE_DEVICE
切屏指令已触发,问题出现在后续编码。结合显示器所属显卡和错误日志,当前采集、编码路径在跨到核显屏幕时无法继续使用原来的 NVENC 编码器。切回主屏以后,原来的编码又能恢复。这是这台电脑、这套配置下的实际表现,不能由此推断所有双显卡电脑都无法硬件编码切屏。
为了先把两个屏幕都用起来,我选择测试软件编码。保留原配置备份后,Sunshine 改成了下面三项,并重启服务、重新进入 Desktop:
encoder = software
hevc_mode = 1
av1_mode = 1
这里的 1 表示不向客户端提供对应的 HEVC、AV1 支持;最终会话使用 H.264,日志确认编码器为 libx264。这不是让 NVIDIA 硬件编码突然支持了核显屏幕,而是换了一条能兼容这次切屏需求的编码路径。
之后再次从平板发送切屏组合键,副屏显示出了电脑上的 Codex 对话界面;切回主屏,又能看到浏览器里的文章页面。两次都检查了平板截图与编码日志,我随后也确认可以正常使用。
现在在平板的 Moonlight 串流界面里,快捷键是:
| 目标 | 平板实体键盘上的组合键 |
|---|---|
| 主屏 | Ctrl + Alt + Shift + F1 |
| 副屏 | Ctrl + Alt + Shift + F2 |
如果键盘的 F1、F2 默认是亮度或音量键,还需要配合 Fn 或调整功能键模式。这组主副屏对应关系是在当前显示器连接和枚举顺序下验证的,换接口或增减显示器后要重新确认。
软件编码的取舍也要留下来:它使用 CPU,可能比原来的 NVENC 增加 CPU 占用、温度和耗电,也可能影响流畅度。这次验证了两块屏幕都能出图、可以来回切换,没有测量这些性能差异,也没有证明它是所有场景下最合适的方案。
用起来怎么样:调到 2K 后,清晰度也上来了
9 月 25 日补一下实际用下来的感觉:延迟几乎无感,非常流畅。 至少在我这次的使用中,没有明显感觉到操作和画面之间隔着一段等待。
最初清晰度没有同样让我满意,看起来像只有 720p 那样。当时最直观的感受就是:操作跟手,画面清晰度还差一点。
后来我自己调整了 Moonlight 的分辨率,直接开到 2K,画面明显清晰了。在本地网络里,我实际用下来觉得非常流畅,几乎感觉不到延迟,清晰度也满意了。 所以“像 720p”是调整之前的观感,不是最后的使用结果。
这里的“无延迟”是我的主观体感,不是测出了零毫秒;“2K”记录的是我选择的分辨率档位。此前电脑两块屏幕的采集信息是 1920 × 1080,仅凭客户端调到 2K,还不能确认源桌面也变成了原生 2K,是否有缩放需要结合当时的采集、编码和解码信息再核对。
离开同一个 Wi-Fi,用 Tailscale 接着连
本地跑通后,我又想把这套连接带到局域网之外。电脑和平板本来就已经加入同一个 Tailscale 网络,两端也都在线,所以这次没有添加路由器公网端口映射,而是在 Moonlight 里手动添加了电脑的 Tailscale 地址。
这次检查时,平板与电脑的 Wi-Fi 地址已经属于不同网段。添加地址后,Moonlight 能打开 Desktop,平板截图显示出了电脑上的网页;同时,Tailscale 中这台平板处于活动状态,有实际收发流量并建立了直连。结合这些结果,确认了这一次跨网络的 Tailscale 串流能够使用,不只是能 ping 通。
之前的一次 Tailscale 探测约为 37 ms,但这个数字不是端到端画面延迟,也不能保证以后换网络仍然相同。外出使用时,两端的 Tailscale 和电脑上的 Sunshine 都需要运行,电脑也不能进入休眠。
跨网络时还遇到了“与电脑连接过慢,建议降低码率”的提示。检查期间,串流日志出现过约 34 Mbps 的视频码率,随后设置界面显示为 44 Mbps。它们来自不同时间点,不能混成一个固定值,但说明当时尝试的码率不低。高分辨率负责保留像素数量,码率则关系到压缩画质和带宽需求;2K 并不意味着必须使用同一个很高的码率。
我决定自己调整码率,协助过程中尚未确认的滑块修改已取消。这里只记录提示和当时观察到的设置,没有把网络带宽不足、抖动或软件编码负载中的某一项认定为唯一原因。本地 2K 很流畅的体感,也不能直接当成跨网络时同样无感的结论。
快捷键最后还是保留原来的
我一度觉得四键切屏太难按,想改成 Ctrl + 1 和 Ctrl + 2。为此下载并安装了 Key Mapper,但还没创建映射、开启无障碍服务,我就意识到这两个组合键本来是浏览器切换标签页的快捷键。
即使把映射限定在 Moonlight,远程桌面里的浏览器也仍然需要这两个键。省下几个按键,却占掉一个常用操作,并不划算。于是取消修改,卸载了刚装的 Key Mapper,继续使用前面列出的 Ctrl + Alt + Shift + F1/F2。
10 月 2 日:把 iPhone 也接进来
平板能用了以后,我又想在苹果手机上看电脑屏幕。手机已经装好 Tailscale 和 Moonlight,这次直接沿用电脑上的 Sunshine,没有重装服务端。
我先用 USB 把手机接到电脑。Windows 能识别到 Apple iPhone,Sunshine 和 Tailscale 服务也正在运行,Tailscale 中有一台 iOS 设备在线。这些是接入前的检查,还不能当作串流成功。
电脑上已有 pymobiledevice3,手机开发者模式也已开启。旧截图接口启动服务失败后,改用 DVT 截图接口成功。截图里,Moonlight 已经列出电脑,图标带锁,说明还需要配对。随后通过 Sunshine 管理页完成 PIN 配对,再进入 Desktop,手机截图实际显示了电脑桌面。
这里的 USB 用于设备识别和辅助截屏,并不是 Moonlight 的视频传输通道。手机装了 Tailscale、设备在线,也不能单凭这些就判定本次串流一定走了 Tailscale;这轮没有单独核实串流地址和跨网络路径。
能看到画面,触控却一开始不顺手
第一次截图里,电脑桌面上覆盖着虚拟摇杆、A/B/X/Y、L1/R1 等游戏手柄按钮。我主要是操作桌面,于是把 Moonlight 设置改成:
- On-Screen Controls:Off,关闭虚拟手柄。
- Touch Mode:Touchpad,用触控板方式操作鼠标。
后面的截图确认了这两项设置正确,但我当时仍反馈单指无法控制。准备进一步对照手机滑动和电脑光标时,手机停在设置面板,串流已断开,这轮观察没有得到有效的输入测试结果。随后我发现又能操作了,便停止排查。
最终我确认手机触控可用,但恢复原因没有查明。 不能把时间上先后发生的“关闭虚拟手柄”和“恢复操作”直接写成确定的因果关系。日志里还有 ViGEmBus 不可用的警告,它指向虚拟游戏手柄支持,不足以解释鼠标输入失效。
这次新增的结果是 iPhone 配对、接收桌面画面,以及我对触控可用的确认。此前平板的本地 2K 流畅体验不直接套用到手机;iPhone 的实际延迟、画质档位和外网稳定性仍未单独测试。实际截图包含私人桌面内容,不作为公开配图。
留给下次的检查项
这次排查分别留下了安装、登录、自启动和切屏的检查方法。以后某一步出问题,可以先对照对应的服务状态、启动日志或实际画面,缩小范围。
最初想要的“在平板上查看并操作电脑”,现在已经跑通,也补上了主副屏切换。后续要测实际帧率、操作延迟和长时间使用的温度、耗电,再决定是否继续保留软件编码,或者重新评估适合这台混合显卡电脑的硬件编码方案。
如果以后 SSH 连不上,我会先检查平板 IP、Wi-Fi、Termux 是否被强行停止和自启动权限,再看 ~/.termux/ssh-boot.log。相比再装一遍,这些记录更能说明问题发生在哪一步。