在调试宇树G1人形机器人的时候,最让我庆幸的一件事,就是它出厂就带了完整的SSH服务。你不需要额外装软件、不需要接显示器、不需要抱着键盘蹲在机器人旁边操作——只要你的电脑和G1在同一网络里,一条ssh unitree@<ip>命令就能进入机器人的终端,像操作本地Linux一样跑命令、改配置、拉日志、部署算法。整个工作流一下子就顺了。
这篇内容我打算完整梳理一下我是怎么用SSH连接宇树G1的,覆盖从最基础的网络准备、用户名密码登录,到SSH密钥免密、VSCode远程开发、后台跑训练脚本、以及踩过的各种连接坑。不管你是刚拿到G1想先登录看看,还是已经上手、想把SSH玩出效率,这篇文章应该都能给你一些参考。
1. 连接前必看:为什么SSH是调试宇树G1的第一选择
1.1 人形机器人调试场景的核心痛点
宇树G1作为一个具备全身自由度的人形机器人,本体上搭载了多个计算单元——负责运动控制的实时控制器,和负责感知、决策的工控机/高性能计算模块。日常开发中,你要做的事情通常包括:修改运动参数、部署视觉模型、采集运行日志、更新固件、调试ROS/ROS 2节点等等。
以前有人习惯用“显示器+键盘+鼠标”直接怼在机器人上操作,但G1这种人形机器人的本体结构紧凑,接口位置很别扭,你总不能每次调试都趴在地上或者把机器人搬到工位上。更麻烦的是,运动中的调试场景——机器人正在测试走路、抓取、遥操作,你还想同步看它的终端输出、改参数,物理接触几乎不可能。
SSH解决的就是这个刚需:通过网络远程进入G1的系统,在完全不触碰机器人的情况下完成几乎所有系统级操作。
1.2 SSH连接的本质:一条加密的远程shell通道
SSH全称Secure Shell(安全外壳协议),它做的事情本质上就是:在你自己的电脑上开一个终端,通过加密通道连接到远程主机上,远程主机的shell(命令行解释器)接收你的输入并返回输出。
这个“加密”很关键。G1的调试网络里可能有多个设备,如果使用Telnet那种明文协议,密码和命令流都会被嗅探到。SSH默认加密通信内容,用户名、密码、命令、输出数据都是密文传输。在调试机器人这种涉及内部代码和配置文件的场景下,安全等级完全不是一个量级。
1.3 和串口/USB连接的方案对比
有人会问:那我用USB数据线直连G1的工控机行不行?行,但有明显劣势。
| 连接方式 | 优点 | 缺点 |
|---|---|---|
| SSH网络连接 | 无线/有线灵活,多终端可同时访问,支持远程开发、文件传输、端口转发 | 需要网络环境配置正确 |
| USB转串口/ADB | 不依赖网络,链路简单 | 不能远距离操作,调试运动状态时不方便,线缆限制机械臂活动 |
| 物理显示器+键鼠 | 直观 | 需要找HDMI接口、键盘鼠标,机器人本体附近操作极度不方便 |
实测下来,SSH是唯一能兼顾“运动调试”“远程开发”“多人协作”的方案。
2. 硬件与环境准备:做对这几步,连接才能顺
2.1 网络环境与IP地址的基本规划
连接SSH的第一件事,是确保你的电脑和G1在同一个局域网内。
宇树G1通常支持有线网口和Wi-Fi两种网络接入方式。建议的第一选择是有线连接,稳定、延迟低、不会意外断连。用网线把G1接到你的路由器LAN口,然后把你的电脑也接到同一个路由器(Wi-Fi即可)。
如果你的环境里没有路由器,也可以直接用一根网线把电脑和G1的网口直连,手动配置静态IP实现连接。这种方式适合现场没有网络设备的场景。
拿到IP的方式有几种:
- 在G1开机后,如果外接有屏幕,直接在系统里查看;
- 通过宇树官方提供的调试软件查看设备列表;
- 如果路由器后台能看DHCP客户端列表,也可以根据MAC地址分辨G1的IP。
提示:我个人习惯在路由器里给G1做静态IP绑定,或者直接在机器人系统里配置固定IP,这样SSH命令、SCP脚本、VSCode配置里的IP就永远不会变,省去了每次开机查IP的麻烦。
2.2 G1侧SSH服务状态确认
宇树G1出厂系统一般默认启用了SSH服务。如果你连不上,第一件事不是怀疑密码,而是确认服务有没有在运行。
判断方法:在机器人侧(如果有条件接屏幕)执行:
systemctl status ssh sudo systemctl status sshd如果显示active (running)就说明服务正常。如果没启用,执行:
sudo systemctl enable ssh sudo systemctl start sshUbuntu 20.04/22.04系统下的OpenSSH服务名一般是ssh,老版本可能叫sshd,两个命令都试一下。
另外,检查一下防火墙。如果G1上启用了ufw,默认会挡住外部SSH连接:
sudo ufw status如果状态是active,需要放行22端口:
sudo ufw allow 22/tcp或者干脆开发调试阶段直接sudo ufw disable(仅限纯内网调试环境,谨慎使用)。
2.3 电脑侧SSH工具的准备:命令行就够,但好工具更省心
Windows、macOS、Ubuntu三大平台现在基本都自带SSH客户端。
- Windows 10 1809以上版本,系统自带OpenSSH,直接在PowerShell或CMD里输
ssh就能用; - macOS和Linux天生自带;
- 如果你用的是Windows但想用更顺手的工具,可以试试Bitvise SSH Client。这玩意儿是个老牌工具,包含SFTP文件管理界面,图形化操作,不需要记命令行参数,对新手极其友好。它其实也自带SSH Server组件(Bitvise SSH Server),但在G1上我们不需要装服务端,只需要用到它的客户端功能。
我自己平时的情况是:简单登录用系统终端,传文件用SCP命令,做远程开发用VSCode的Remote-SSH插件。图形化客户端在给同事演示或者偶尔需要拖拽传文件的时候会开一下。
3. 首次连接全流程:从开机到成功登录
3.1 需要准备的信息
连接之前,把下面几个信息准备好:
- G1的IP地址,例如
192.168.1.100 - SSH用户名:宇树G1的官方账号体系一般基于Ubuntu用户,常见的默认用户名是
unitree(也可能因版本差异不同,以机器出厂标签或官方文档为准) - 密码:默认密码一般在出厂资料中标注,初次登录后强烈建议改掉
3.2 直连场景下的网络配置方法
如果说现场真的没有路由器,只有一根网线。那你需要手动设置电脑的有线网卡IP为同一网段,比如G1静态IP是192.168.123.15,那电脑端可以设置成192.168.123.100,子网掩码255.255.255.0,网关不用管。
Windows上操作路径:设置 -> 网络和Internet -> 以太网 -> 更改适配器选项 -> 右键属性 -> IPv4协议 -> 手动填写IP。
Linux桌面版可以在“设置 -> 网络 -> 有线连接 -> IPv4”里切到“手动”模式填写。
macOS在“系统设置 -> 网络 -> 以太网 -> 详细信息 -> TCP/IP”里修改。
设置完后用ping测试:
ping 192.168.123.15能通就说明链路OK,然后就能SSH了。
3.3 局域网连接场景下的标准流程
有路由器的场景更简单,开机等G1连上网络,查询到IP后,直接打开终端。
Linux/macOS终端、Windows PowerShell/CMD:
ssh unitree@192.168.1.100第一次连接会出现指纹确认提示:
The authenticity of host '192.168.1.100 (192.168.1.100)' can't be established. ED25519 key fingerprint is SHA256:xxx... Are you sure you want to continue connecting (yes/no/[fingerprint])?这个提示是在确认远端主机的身份指纹,选择yes并回车。随后系统会要求输入密码,输密码时屏幕不会显示任何字符,这是正常现象,不要以为是卡住了。
输入正确密码后,你会看到类似下面的信息:
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.15.0-91-generic x86_64) ... unitree@G1:~$看到unitree@G1:~$就说明已经进入了G1系统的shell,你现在可以执行任何你有权限的命令了。比如查看系统信息:
uname -a lsb_release -a3.4 登录后第一时间要做的事
成功登录后,不要急着跑业务代码,先把两件事做了:
第一件事,修改默认密码:
passwd系统会先让你输入当前密码,再设置新密码。改一个只有你知道的密码,避免调试现场有人用默认密码登进去乱搞。
第二件事,更新系统软件源并安装常用调试工具(可选,但强烈推荐):
sudo apt update sudo apt install -y net-tools htop tmux treehtop用于查看进程资源占用,tmux是终端复用器(后面细讲它的作用),net-tools提供ifconfig命令方便查看网络状态。
注意:G1的系统环境可能有专门的实时内核和专用驱动,不要轻易执行
apt upgrade升级内核,万一和驱动不兼容,机器人运动控制会出问题。开发调试跑用户态程序问题不大,涉及内核级的升级务必谨慎。
4. 进阶用法:从“能连上”到“高效干活”
4.1 SSH密钥免密登录:摆脱每次输密码的麻烦
如果你一天要SSH登进登出十几次,每次输入密码确实烦人。更关键的是,在自动化脚本里没法交互输入密码。解决办法是配置SSH密钥认证。
密钥认证原理:生成一对密钥(公钥+私钥),把公钥放到G1的~/.ssh/authorized_keys文件中,私钥留在本地。连接时服务器会验证你的私钥签名,验证通过就放行,不再询问密码。
在本地电脑生成密钥:
ssh-keygen -t ed25519 -C "your_email_or_comment"一路回车即可,默认生成的密钥文件在~/.ssh/id_ed25519和~/.ssh/id_ed25519.pub。如果你有特殊安全需求,可以设置passphrase(私钥密码),不过日常开发建议留空。
然后把公钥复制到G1上:
ssh-copy-id unitree@192.168.1.100这个命令会要求你输一次密码,之后它会自动把公钥追加到G1的authorized_keys文件里,并设置好权限。
如果你没有ssh-copy-id命令(比如Windows老版本),可以手动操作:
cat ~/.ssh/id_ed25519.pub | ssh unitree@192.168.1.100 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"完成之后,再执行ssh unitree@192.168.1.100应该就直接进去了,不需要输密码。
这里有两个容易踩的坑:
.ssh目录权限必须是700,authorized_keys文件权限必须是600,权限太松会导致ssh服务端拒绝使用这个密钥文件;- 如果你改了G1上的用户目录,或者从备份恢复过home目录,需要重新检查属主是否还是unitree用户。
4.2 SSH配置文件:多台机器人一键直连
如果你手上有不止一台宇树G1(或者还有Go2、其他Linux开发板),建议在本地~/.ssh/config里配置主机别名,省去每次敲完整用户名和IP。
在~/.ssh/config里添加:
Host g1-1 HostName 192.168.1.100 User unitree IdentityFile ~/.ssh/id_ed25519 Host g1-2 HostName 192.168.1.101 User unitree IdentityFile ~/.ssh/id_ed25519配置好以后,连接就变成了:
ssh g1-1不用记忆IP地址,不需要手动指定用户名和密钥文件,干净利落。
还可以给scp、rsync等命令使用同样的别名:
scp ./test.py g1-1:/home/unitree/dev/这在实际使用中能省下大量重复输入的时间。
4.3 SSH端口转发:远程访问机器人的图形化/服务接口
很多场景下你不仅要命令行,还想访问G1上运行的服务端口,比如ROS的可视化工具、Jupyter Notebook、Web端调试界面等。这时SSH端口转发(隧道)就派上用场了。
本地端口转发的基本格式:
ssh -L 本地端口:目标地址:目标端口 用户名@主机IP例如G1上运行了一个Web服务监听在8888端口,你想在本地浏览器访问:
ssh -L 8888:localhost:8888 unitree@192.168.1.100然后本地浏览器打开http://localhost:8888,就能访问到G1的Web服务了。数据全程通过SSH加密隧道传输。
反向转发的场景也常见:G1上需要访问你电脑上的某个端口服务,用-R参数:
ssh -R 9000:localhost:9000 unitree@192.168.1.100这样G1上访问localhost:9000就会转发到你电脑的9000端口。
提醒:SSH端口转发是非常强大的工具,但也意味着如果密码/密钥泄露,攻击者可能通过隧道访问你的内网资源。密钥文件务必保管好,G1的root权限不要随意开放给不信任的人。
4.4 SSH连接保活与断线重连
SSH默认会话在长时间无操作后会超时断开,尤其在网络质量不稳的调试现场。两个解决办法:
方法一,本地侧配置心跳:
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 unitree@192.168.1.100意思是每60秒发一个心跳包,连续3次无响应才断开。
方法二,在G1的服务端配置/etc/ssh/sshd_config:
ClientAliveInterval 60 ClientAliveCountMax 3改完重启ssh服务。
如果你希望在网络闪断后自动重连,Linux/Mac下可以直接用autossh:
autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" unitree@192.168.1.100断线后它会自动重新建立连接。Windows下则可以写一个简单的PowerShell循环脚本实现重连。
5. 远程开发与多任务运行:SSH连接的高级打开方式
5.1 VSCode + Remote-SSH:把G1变成你的远程开发环境
日常开发中,直接在G1上用Vim改代码非常痛苦,尤其是Python工程的补全、调试、代码跳转。我的推荐方案是VSCode + Remote-SSH插件,这个组合可以让你在本地使用完整的IDE界面,但所有代码都实时同步在远端G1上运行。
流程很简单:
- 本地安装VSCode;
- 安装扩展“Remote - SSH”;
- 按F1,输入
Remote-SSH: Connect to Host...,选择或输入目标主机(比如unitree@192.168.1.100); - 连接成功后,VSCode会新开一个远程窗口,左侧文件列表显示的是G1上的目录。
这样就拥有了完整的远程开发体验:代码自动补全、调试器、终端面板直接指向G1,完全可以替代在本机开发再拷贝到机器人的低效流程。
这里有一个很常见的报错,就是这篇文章标题热词里提到的:“此扩展在此工作区中被禁用,因为其被定义为在远程扩展主机中运行”。出现这个提示说明你试图在远程窗口中安装或使用那些只能在本地UI运行的扩展,比如部分主题、自定义键位映射插件。解决办法很简单——扩展分两种:一种是远程端扩展(Remote),真正在服务器上执行,需要安装在SSH目标上;另一种是UI端扩展,只能在本地窗口用。你只需要在扩展页面看它的分类,把属于远端类别的扩展在远程窗口里安装即可。一般你需要的Python、Pylance、ROS扩展都可以直接在远程端装。
5.2 tmux终端复用:防止断线导致任务中断
SSH连接如果断开,正在前台运行的进程通常会收到挂断信号(SIGHUP)而终止。这对机器人调试来说非常恼火——可能你的训练脚本跑了一半,Wi-Fi抖了一下,连接断了,任务就废了。
解决办法是用tmux。在G1上启动一个tmux会话:
tmux new -s train_session然后在这个会话里跑你的训练任务。如果SSH断了,重连后执行:
tmux attach -t train_session所有输出和任务状态还在,仿佛什么都没发生过。
tmux还有很多高效用法:
Ctrl+b c创建新窗口;Ctrl+b n切换下一个窗口;Ctrl+b d脱离当前会话(任务继续后台运行);- 在同一个窗口里分屏:
Ctrl+b %左右分屏,Ctrl+b "上下分屏。
我个人习惯是在G1上常驻一个名为dev的tmux会话,里面开一个窗口跑roscore/ros2 daemon,一个窗口跑状态监控,一个窗口留作临时命令。这样每次SSH上去,一分钟就能恢复到干活的完整布局。
5.3 通过SSH在后台安全运行长时间任务
如果你不想用tmux,也可以用nohup直接把命令放后台:
nohup python3 train.py > train.log 2>&1 &这条命令把标准输出和错误输出都重定向到train.log,配合&让进程在后台运行。SSH断开也不影响它继续跑。
需要查看进度就:
tail -f train.log通过退出命令返回值判断任务是否正常结束:
echo $?不过用nohup管理多个任务会变得混乱,推荐还是tmux作为主力方案。
5.4 用SCP/rsync高效传输文件到G1
日常往G1上传代码、模型权重,最常用的是scp命令:
scp -r ./my_robot_app unitree@192.168.1.100:/home/unitree/dev/从G1下载文件:
scp -r unitree@192.168.1.100:/home/unitree/dev/logs ./如果只需要传增量文件,用rsync更高效:
rsync -avz --progress ./src/ unitree@192.168.1.100:/home/unitree/dev/src/rsync会对比文件差异只传输改动部分,实测传大文件夹要比scp快很多,而且支持断点续传。
如果室内网络环境不稳定,我在传大文件时还会加上-e "ssh -o ServerAliveInterval=60"参数,减少长传输超时断连的概率。
6. 高频故障排查:连不上的时候,按这个顺序查
6.1 常见报错与对应解决方案
我把实际使用中见过的高频问题整理成了表格,方便对照排查:
| 报错/现象 | 大概率原因 | 处理方案 |
|---|---|---|
Connection timed out | IP错误、网络不通、防火墙拦截 | 先ping目标IP,再检查网线/Wi-Fi连接 |
Connection refused | SSH服务未运行或端口错误 | 确认sshd服务状态,检查端口是否为22 |
Permission denied (publickey,password) | 密码错误或密钥认证失败 | 确认用户名和密码,检查authorized_keys内容 |
Host key verification failed | 远端系统重装/密钥变更 | 运行ssh-keygen -R IP地址清除旧的host key记录 |
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! | G1系统被重置或IP被复用 | 同上,清除后重连 |
| SSH连接建立后频繁掉线 | 网络不稳定或空闲超时 | 配置ServerAliveInterval心跳参数 |
bash: command not found | 环境变量或shell配置异常 | 检查.bashrc是否被改动 |
Windows下ssh不是内部或外部命令 | OpenSSH客户端未安装 | 设置-系统-可选功能-添加OpenSSH客户端 |
6.2 终极调试命令:ssh -vvv
当所有常规手段都无效时,用ssh -vvv来调试连接过程。这个命令会输出SSH握手全过程的调试信息,把连接失败的具体阶段暴露出来。
ssh -vvv unitree@192.168.1.100输出会告诉你:
- 客户端加载了哪个config文件;
- 尝试连接哪个IP和端口;
- 是否建立了TCP连接;
- 密钥协商到哪一步失败了;
- 是公钥认证被拒还是密码认证被拒。
有一次我排查一个连接问题,发现卡在banner exchange阶段,后来查出来是G1上装了Banner、内容里有特殊字符导致客户端处理异常。这种问题不看详细日志基本定位不到。
6.3 常见问题:Ubuntu系统SSH无法连接
看热词里出现了“ubuntu ssh无法连接”,这个在宇树G1上也可能遇到。Ubuntu默认不装openssh-server,虽然G1出厂预装了,但如果有人重置过系统或者换过镜像,就可能出现这个问题。
排查步骤:
dpkg -l | grep openssh-server检查是否安装;- 如果未安装,
sudo apt install openssh-server; - 安装后
sudo systemctl enable --now ssh; sudo systemctl status ssh确认状态。
还有一个小坑:G1如果是通过Wi-Fi连接路由器的,部分路由器AP隔离功能会禁止无线设备之间的通信,导致SSH连不上,但ping也可能通或不通。解决方法是关闭路由器的AP/客户端隔离,或者改用有线连接。
6.4 网络环境排查的完整命令顺序
当你SSH不上G1时,可以按这个顺序执行排查命令:
# 第一步:确认物理链路连通 ping 192.168.1.100 # 第二步:确认端口开放 nc -vz 192.168.1.100 22 # 第三步:尝试SSH连接并指定超时时间 ssh -o ConnectTimeout=5 unitree@192.168.1.100 # 第四步:查看详细握手过程 ssh -vvv unitree@192.168.1.100nc -vz如果显示Connection succeeded,说明网络通、SSH端口可达,问题大概率出在认证或者客户端配置上;如果显示Connection refused,说明G1上SSH服务可能没起,或者防火墙把22端口拦了。
6.5 远程执行命令返回码与日志排查技巧
有些时候SSH命令能执行,但脚本运行结果不对。建议养成的习惯是:把远程命令输出捕获下来仔细看,而不是只看“报没报错”。
ssh g1-1 "python3 /home/unitree/dev/run_test.py; echo EXIT_CODE=$?"这样就可以在本地看到脚本退出码,以及完整的远程输出。如果脚本卡住,再用ps aux配合htop看是CPU跑满还是IO阻塞。
用systemd运行的机器人自启动服务,排查日志用:
journalctl -u my-service -f如果是Docker容器里的模块:
docker logs -f <container_name>这些远程日志排查能力,是SSH连接价值的重要组成部分。
7. 连接稳定性与安全加固:让SSH连接真正“靠得住”
7.1 四个提高连接稳定性的习惯
调试机器人时,SSH掉线带来的损失远不只是重新登录那几秒钟——它可能打断正在进行的实时数据采集、遥操作控制或模型训练。我总结了几条提高稳定性的实操习惯:
第一,网络端优先有线。Wi-Fi受干扰波动大,特别是在机器人运动时,电机带来的电磁干扰不可忽视。只要现场条件允许,G1的网口务必插上有线。
第二,G1的SSH服务端开启心跳保活参数。修改/etc/ssh/sshd_config:
ClientAliveInterval 30 ClientAliveCountMax 6每30秒检测一次,允许连续6次无响应才断开,相当于容忍180秒的网络波动。
第三,本地使用autossh自动重连,或者用tmux保存任务状态。网络恢复后一键回到之前的会话。
第四,定期检查G1的磁盘空间。df -h如果根分区写满,SSH服务可能无法正常写入日志、用户无法创建临时文件,表现就是连接成功但执行命令卡死。这种问题很隐蔽,我已经踩过两次了。
7.2 G1上的SSH安全加固要点
G1一般部署在受控的调试环境,但如果你的实验室允许网线直连且不少人共用网络,建议做几个基础加固:
- 修改默认账号密码,这个前面说了;
- 禁止root用户直接SSH登录,在
/etc/ssh/sshd_config里设置PermitRootLogin no; - 如果指定机器才允许登录,可以在
/etc/ssh/sshd_config里设AllowUsers unitree,再结合密钥认证; - 更改SSH端口不是必须的,但在公网环境(如果G1暴露到公网)可以有效减少扫描攻击。改端口后连接命令要加
-p参数。
我个人的做法是:内网调试保持默认22端口和密码+密钥混合认证,凡是涉及跨网络或者访客接入的场景,临时改为仅密钥认证,并且每次调试完检查一下/var/log/auth.log有没有异常登录记录。
7.3 从G1反向SSH到你电脑的场景
最后一个偏门但好用的技巧,是从G1主动反向连接到你电脑。有些时候,G1处于一个你无法直达的隔离网段,反而G1能主动访问你的电脑。这时可以反向建立隧道:
在G1上执行:
ssh -R 2222:localhost:22 your_username@<你电脑的IP>这样在你电脑上执行:
ssh -p 2222 unitree@localhost就能反向进入G1。这个技巧在G1的Wi-Fi配置出错、或无线路由器不可达时几乎是救命稻草——你只需要能物理接触到G1的网口和键鼠就能救回来。
我个人在实际调试中最深的体会是:SSH连接不是“能进终端”就结束的事情,它真正决定你开发效率的是后续一连串习惯的建立。密钥免密配好、tmux会话常驻、VSCode远程开发用顺手、端口转发知道怎么用,调试G1的效率才能说有本质提升。尤其是拿到G1的第一天,不要急着跑demo,先把SSH这一套环境打磨好,后面所有工作都会顺畅很多。最后再分享一个小技巧:把常用的SSH命令和文件同步脚本写成一个Makefile放在本地项目根目录,比如make conn、make sync、make logs,这样团队里任何人拿到项目都能一键连接G1,不会有“怎么连机器人”这种入门问题卡住人。