环境搭建
352.1.2 环境搭建
#include <stdio.h> // 引入标准输入输出头文件,以便调用 printf 函数
int main() // 定义程序入口函数;这里原样保留视频中的空参数列表写法
{ // main 函数体开始
printf("Hello ssh\r\n"); // 向终端输出文本,再依次输出回车符和换行符
return 0; // 返回 0,表示程序正常结束
} // main 函数体结束
本节在 Windows 主机上使用 VS Code 和 MobaXterm,通过 SSH 连接 Ubuntu 虚拟机,并在虚拟机中安装本地 C 程序所需的基本构建工具。上面的 main.c 是视频实际展示的全部源码;本节只创建并查看了文件,尚未演示 GCC 编译命令。
源码中的 \r 是回车符,\n 是换行符。在 Linux 终端中通常只写 \n 即可,但这里按照视频原样保留 \r\n。另外,视频使用了 int main();在 C 语言中,如果要明确表示“不接收参数”,更严谨的声明是 int main(void),但不能因此改写课堂源码。
一、开发环境搭建
本节环境中各组件的职责如下:
| 所在位置 | 组件 | 职责 |
|---|---|---|
| Windows 主机 | VS Code | 显示编辑界面,通过 Remote - SSH 操作远端文件 |
| Windows 主机 | MobaXterm | 提供 SSH 客户端和终端,用于先独立验证 SSH 连接 |
| Ubuntu 虚拟机 | OpenSSH Server | 监听 SSH 连接并完成身份验证,服务进程通常为 sshd |
| Ubuntu 虚拟机 | VS Code Server | 由 Remote - SSH 建立连接时部署,使命令和远端扩展在虚拟机中运行 |
| Ubuntu 虚拟机 | GCC、make 等 | 编译和构建 Linux 程序 |
数据流可以概括为:Windows 上输入代码,Remote - SSH 把编辑操作送到 Ubuntu;源文件保存在 Ubuntu 文件系统中,GCC 也在 Ubuntu 中运行。
1.1 环境搭建
课程沿用前一阶段安装的 Ubuntu 虚拟机。开始前应确认:
- 虚拟机能够正常启动和登录;
- Ubuntu 能访问软件源;
- Windows 与 Ubuntu 之间网络可达;
- 当前用户拥有
sudo权限; - 已记录 Ubuntu 版本、虚拟机 IP 地址和登录用户名。
视频中的 Ubuntu 地址 192.168.8.151 和用户名 argon 仅是当时演示环境的示例,不能照抄为自己机器的地址和账号。使用 DHCP 时,虚拟机重启或网络变化后 IP 地址还可能改变。
1.1.1 虚拟机配置
视频要求在 VMware 的虚拟机设置中,把网络适配器设为“桥接模式”。桥接确实适合本节演示:虚拟机像局域网中的独立设备一样获得地址,Windows 主机和同一局域网中的其他设备可以直接访问它。
但“必须桥接,否则无法 SSH 或联网”并不准确。常见模式的差别是:
| 模式 | 网络关系 | 能否访问外网 | 适用场景与注意事项 |
|---|---|---|---|
| 桥接(Bridged) | 虚拟机直接接入物理局域网,通常从局域网 DHCP 获取地址 | 通常可以 | 便于局域网设备直接访问虚拟机,但 SSH 端口也可能暴露给同一局域网 |
| NAT | 虚拟机通过宿主机共享对外连接,并位于 VMware 私有网络 | 通常可以 | 一般也能满足宿主机连接虚拟机以及虚拟机下载软件,隔离性通常更好 |
| 仅主机(Host-only) | 只建立宿主机与虚拟机之间的私有网络 | 默认通常不可以 | 适合纯本机实验;若要下载软件,需要另配路由或第二块网卡 |
因此应按目标选择模式。若桥接在校园网、公司网或启用了无线客户端隔离的网络中无法获得地址,可改用 NAT,而不是认定 SSH 本身有问题。
1.1.2 安装 VS Code 插件
- 从 VS Code 官方网站 下载并安装 Windows 版本;已经安装则无需重复操作。
- 在扩展视图中搜索并安装 Microsoft 发布的 Remote - SSH 扩展。
- Windows 本地还需要兼容 OpenSSH 的 SSH 客户端。视频使用 MobaXterm;现代 Windows 自带的 OpenSSH Client 也可以完成基本连接。
Remote - SSH 扩展不是 GCC 编译器。它负责建立远程工作区,并在远端运行终端、命令和适合远程运行的扩展。后续若安装 C/C++ 语言扩展,应留意 VS Code 显示的“本地安装”和“在 SSH 主机上安装”并非同一环境。
1.1.3 配置网络
视频使用以下命令查看 Ubuntu 虚拟机的网络接口:
ifconfig
ifconfig 来自较旧的 net-tools 工具包,并非所有新系统都默认安装。更推荐使用 iproute2 提供的命令:
ip -br address
找到状态为 UP 的实际网卡,并记录其 IPv4 地址。不要把回环接口 lo 的 127.0.0.1 当成虚拟机在网络中的地址;127.0.0.1 始终指向执行命令的本机。
排查连接时应逐层确认:
- Ubuntu 是否获得了预期网段的地址;
- Windows 是否能到达该地址;
- Ubuntu 的 SSH 服务是否正在运行;
- TCP 22 端口是否被虚拟机防火墙或外部网络策略拦截。
Windows PowerShell 可用下列命令测试 SSH 端口,而不仅是依赖 ping:
Test-NetConnection <虚拟机IP> -Port 22
1.1.4 SSH 安装
视频依次执行了 apt update、apt upgrade 和 apt install ssh。其中:
apt update只刷新软件包索引,不会升级已安装的软件;apt upgrade才会升级当前系统中的软件包,它可能耗时较长,并非只为安装 SSH 所必需;- Ubuntu 中的
ssh是同时依赖客户端和服务端的元包。若目标只是让虚拟机接受远程连接,官方文档使用更明确的openssh-server。
推荐安装流程如下:
sudo apt update
sudo apt install openssh-server
sudo systemctl enable --now ssh
sudo systemctl status ssh
命令含义:
sudo:以管理员权限执行后面的命令;输入密码时终端不显示字符属于正常现象;apt install openssh-server:安装 OpenSSH 服务端及其依赖;systemctl enable ssh:设置以后开机自动启用该服务,它本身不保证立即启动服务;--now:让enable在设置开机启用的同时立即启动服务;systemctl status ssh:查看当前状态,应关注Active: active (running),而不只是界面颜色。
如果严格复现视频,也可以执行:
sudo apt install ssh
sudo systemctl enable ssh
sudo systemctl status ssh
但如果 status 显示服务未运行,还要执行 sudo systemctl start ssh。查看状态进入分页器时通常按 q 退出;Ctrl+C 是中断当前前台命令,不是分页器最规范的退出键。
1.1.5 配置防火墙
原笔记中的“搜索 mobile 或猫吧”是语音识别错误;视频是在浏览器中搜索 MobaXterm。防火墙配置则是在 Ubuntu 终端中通过 UFW 完成,与安装 MobaXterm 是两件事。
若准备启用 UFW,应先允许 SSH,再启用防火墙,以免把自己的远程连接挡在外面:
sudo ufw allow ssh
sudo ufw enable
sudo ufw status verbose
ssh 是 /etc/services 中定义的服务名,默认对应 TCP 22 端口;也可以写成 sudo ufw allow 22/tcp。如果以后修改了 SSH 监听端口,必须先放行新端口,再重启服务并关闭旧规则。
UFW 默认可能处于未启用状态。对仅在本机隔离网络中实验的虚拟机,是否启用应结合网络模式和安全需求决定;它不是 SSH 协议能够工作的绝对前提。
1.1.6 通过 SSH 连接到 Ubuntu
MobaXterm Home Edition 可免费用于本节练习,但它是按 Mobatek 最终用户许可协议发布的 freeware,不是完整开源软件;Professional Edition 为收费版本。
在 MobaXterm 本地终端或 Windows 终端中输入:
ssh <Ubuntu用户名>@<虚拟机IP地址>
视频中的实际形式为:
ssh argon@192.168.8.151
第一次连接会显示远端主机密钥指纹。它用于确认正在连接的确是目标虚拟机,不应在不核对的情况下机械地点击同意。可先在虚拟机控制台查看 ED25519 主机密钥指纹:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
确认指纹一致后接受,客户端会把主机身份写入 known_hosts。随后输入的是 Ubuntu 登录密码,终端不回显密码字符。
视频在 Ubuntu 桌面创建了 hello ssh 文件夹,再从远程终端进入桌面并用 ls 查看:
cd Desktop
ls
这只能证明当前登录账号看到了同一用户目录。不同语言的 Ubuntu 桌面目录名称可能不是 Desktop,可以用 xdg-user-dir DESKTOP 查询实际路径。目录名含空格时,应使用引号或转义,例如:
cd "$(xdg-user-dir DESKTOP)/hello ssh"
1.1.7 VS Code 配置
- 在 VS Code 中打开“远程资源管理器”,选择 SSH 目标并单击“添加新 SSH 主机”;
- 输入与终端测试相同的命令,如
ssh argon@192.168.8.151;用户名与@之间不能随意添加空格; - 选择要写入的本地 SSH 配置文件;
- 从目标列表发起连接,必要时选择远端平台为 Linux,并完成登录;
- 连接成功后选择“打开文件夹”,打开远端用户目录中的
hello ssh文件夹; - 在该远端目录中创建
main.c,输入本笔记顶部的视频原样源码。
连接成功后,VS Code 会打开远程窗口,并在 Ubuntu 端部署 VS Code Server。此时:
- 资源管理器中看到的是 Ubuntu 文件系统,不是 Windows 本地目录;
- 新建终端默认运行在 Ubuntu 虚拟机中;
- 在 VS Code 中保存
main.c,Ubuntu 桌面立即看到变化,是因为两边查看的是同一个远端文件,不是后台做了一次文件同步; - VS Code 不会因为连接成功就自动拥有 GCC,编译器仍须安装在 Ubuntu 中。
视频所谓“进入根目录”不够准确:刚连接时 VS Code 只是打开一个远程窗口;之后由用户选择具体文件夹。Linux 根目录是 /,普通用户的家目录通常是 /home/<用户名>,二者不能混称。
1.1.8 安装 build-essential
转录中的 “Build Assistant” 是识别错误,正确包名是 build-essential。它是一个很小的元包,通过依赖关系安装 Ubuntu/Debian 本机软件构建所需的一组基础包,主要包括:
gcc:GNU C 编译器;g++:GNU C++ 编译器;make:根据 Makefile 规则组织构建;libc6-dev(或对应的libc-dev):C 库开发头文件和链接文件;dpkg-dev:Debian 软件包构建相关工具。
因此,“包含 GNU C 库、Makefile 脚本组件和 dpkg 打包解包工具”不够准确:它安装的是开发依赖和 make 工具;Makefile 是项目编写的构建规则文件;dpkg-dev 也不等同于基础的 dpkg 包管理程序。build-essential 还不包含所有开发工具,例如 GDB、CMake 和 ARM 交叉编译器仍需按需要另行安装。
视频执行的安装命令是:
sudo apt install build-essential
推荐这样验证安装结果:
gcc --version
g++ --version
make --version
视频先单独输入 gcc,出现 gcc: fatal error: no input files。这说明 shell 已找到并运行 GCC,只是没有提供输入文件;它是预期错误,不是最清晰的版本检查方式。视频随后执行的正确写法是 gcc -v,注意选项前需要空格和连字符,不能写成原笔记中的 gcc-v。
视频环境显示的是 Ubuntu 20.04 系列中的 GCC 9.4.0;学习者实际安装到的版本由 Ubuntu 发行版和软件源决定,不必强求完全相同。
1.2 内容回顾
本节完整流程是:
- 检查 Ubuntu 虚拟机网络,并记录真实 IP 地址;
- 在 Ubuntu 安装并启动 OpenSSH Server,按需配置 UFW;
- 在 Windows 使用 MobaXterm 或 OpenSSH 客户端验证
ssh 用户名@IP; - 在 VS Code 安装 Remote - SSH,连接并打开 Ubuntu 中的工作目录;
- 按视频原样创建
main.c,确认 Windows 界面操作的是远端文件; - 在 Ubuntu 安装
build-essential,并检查 GCC、G++ 与 make 是否可用。
本节应形成三个关键认识:VS Code 是编辑器而不是编译器;SSH 是加密远程连接机制而不是文件同步工具;build-essential 提供本机构建基础环境,但不等于完整的嵌入式交叉开发工具链。
常见故障可按下表定位:
| 现象 | 优先检查 |
|---|---|
Connection timed out | IP 是否正确、虚拟机网络是否可达、22 端口及防火墙/网络策略 |
Connection refused | ssh 服务是否安装并处于 active (running),监听端口是否正确 |
Permission denied | 用户名、密码或密钥是否正确,目标账号是否允许登录 |
| VS Code 能连接但扩展不可用 | 扩展是否安装在远端 SSH 主机侧,远端是否能下载 VS Code Server 依赖 |
gcc: command not found | build-essential 是否安装成功,APT 是否报错,PATH 是否异常 |