做远程开发这几年,我最大的感受就是:配置固定IP和远程连接本身不难,难的是把这两件事串在一起后,各种意想不到的“连锁反应”。比如你费了半天劲把IP固定好了,结果PyCharm连不上;或者PyCharm能连上了,代码同步过来却跑不起来。很多教程只讲单点,不讲联动,看完只能解决一半问题。这篇我把自己踩过的坑和验证过的完整流程整理出来,尽量说人话,你照着做就行。
先交代一下基础环境,方便你对号入座:我的服务器是Ubuntu 20.04 LTS,网卡是常见的ens33类型;本地电脑是Windows 11,IDE用的是PyCharm Professional。不同版本之间有些小差异,我会在关键位置特别标注。另外强调一点:固定IP配置这部分,Ubuntu 17.10之后的版本必须用netplan,如果你在网上搜到一堆改/etc/network/interfaces的老教程,直接关掉,那是上古时期的玩法,用了大概率起不来。
1. 先别急着配IP——搞清楚你到底需要哪种“固定IP”
很多人一上来就打开netplan配置文件开始改,改完发现怎么都上不了网。我强烈建议你先做一件事:打开终端执行ip a,看清楚自己的网络环境。
这里有一个关键概念要区分:你是需要局域网固定IP,还是公网固定IP?
如果是在机房、公司内网、实验室这种环境,你要的是局域网静态IP——也就是IP地址由你在网段内手动指定。操作对象是服务器本身,改的是netplan。
如果服务器托管在云厂商那儿,控制台里一般都有“绑定弹性IP”或“固定公网IP”的入口,那个操作是在云控制面板做的,不需要也不应该在系统里配置公网IP地址。在云服务器里手动写公网IP会导致网络直接瘫痪。
还有一种场景是家庭拨号宽带,想看监控或连NAS,这种通常涉及到NAT和外部访问,和今天聊的局域网站点配置不是一回事,建议先别混在一起。
我们这篇文章主要解决局域网内服务器IP固定的问题。这听起来好像很简单,但实际价值非常大。我在某公司的服务器上跑着一个数据分析任务,每天要手动拉数据。之前用DHCP动态分配,路由器一重启IP就变,我的自动化脚本每天都要改一次地址,烦得要命。固定IP之后,脚本里的连接地址再也没动过。如果你有类似需求,比如SSH远程登录、搭建本地服务、给设备做端口映射,固定IP基本是刚需。
那为什么系统默认不用固定IP?因为DHCP(动态主机配置协议)能自动分配地址,省去手动配置的麻烦。但它的问题是地址可能变动,尤其是短租期的DHCP,或者路由器重启后重新分配。固定IP的本质,就是让你手动指定一个别人不会占用的地址,并告知系统通过哪个网关和DNS访问外部网络。
在动手之前,你还需要搞明白自己的网段信息。用ip route show看一下当前默认路由,输出中类似default via 192.168.1.1 dev ens33的部分,就是你当前网关。ip a里显示的192.168.1.x就是你当前动态地址。你的固定IP必须和它在同一个网段,并且避开路由器DHCP自动分配的地址池,否则会出现IP冲突,导致时断时续。实践中,如果你不确定地址池范围,建议选在网段靠后位置,比如192.168.1.200这样的地址,冲突概率会比较低。
还有一个常见误区需要提醒:固定IP不是只改IP地址就行,子网掩码、网关、DNS必须配套正确。很多人改完IP能ping通局域网,却上不了外网,十有八九是网关写错了,或者DNS没有同步更新。
2. 手写netplan前的三件事:备份、认网卡、查网关与DNS
信息收集清楚了,就可以进入实操阶段了。但在碰配置文件之前,我习惯先做三件准备工作,能帮你省掉后半夜的排障时间。
第一件事:备份现有配置。
sudo cp /etc/netplan/01-netcfg.yaml /etc/netplan/01-netcfg.yaml.bak不同Ubuntu版本里netplan配置文件名可能不一样,常见的有01-netcfg.yaml、00-installer-config.yaml、50-cloud-init.yaml。用ls /etc/netplan/看一下实际有哪些文件,然后逐个备份。这一步看起来多余,但配置出错时能让你一秒回滚。
第二件事:确认网卡名称。
ip a输出的网卡名称,常见的是ens33、ens160、eth0、enp0s3。不同虚拟机或物理机命名规则不同,不要想当然用网上教程里的名字。我见过有人把拓扑图上看到的名字拿来直接写,结果apply完立刻断网。这类可预测命名规则里,en代表以太网,p0代表总线编号,s3代表插槽位置,后边一串具体数字对应不同接口。
第三件事:记录网关和DNS。
ip route show cat /etc/resolv.conf注意:Ubuntu桌面版和服务器版这里会不一样。服务器版常见的是把DNS信息写在netplan里然后由systemd-resolved接管,而/etc/resolv.conf本身往往是个软链接。如果你看到nameserver 127.0.0.53这种地址,别慌,那是本地解析器,真正的上游DNS在netplan或resolved配置里。
弄完这三件事,再打开配置文件去改,我是从“盲改”变成了彻底的“有数改”。顺带插一句:如果你的机器开启了cloud-init(云服务器常见),netplan配置可能由cloud-init动态生成,直接改文件大概率会被覆盖。这时要么在/etc/netplan/下新建一个高优先级的配置文件,要么把DHCP改成静态后用renderer: networkd强制生效。这篇先按普通服务器处理,云服务器的单独讲。
3. netplan配置实操:一个适用于Ubuntu 18.04/20.04/22.04的通用写法
接下来的内容会让你觉得格外简洁,因为netplan本身就是一个以简洁为设计目标的网络配置工具。你只需要看一个核心概念:它用YAML描述网络接口状态,然后通过渲染器(networkd或NetworkManager)把配置交给系统去执行。
3.1 最小可用配置模板
以Ubuntu 20.04服务器版为例,打开/etc/netplan/01-netcfg.yaml,推荐写成这样:
network: version: 2 renderer: networkd ethernets: ens33: dhcp4: no dhcp6: no addresses: - 192.168.1.200/24 routes: - to: default via: 192.168.1.1 nameservers: addresses: [223.5.5.5, 8.8.8.8]字段拆开解释一下:
renderer: networkd:服务器版建议用networkd负责网络管理,稳定且重启不弹图形界面。桌面版才考虑用NetworkManager。dhcp4: no:关闭IPv4的DHCP,固定地址。addresses: - 192.168.1.200/24:注意这里必须写明子网掩码长度,/24代表255.255.255.0。只写IP地址不写掩码,netplan apply会直接报错。routes: - to: default via: 192.168.1.1:default路由就是默认网关。如果你的环境需要多条静态路由,可以在routes下面继续追加。nameservers.addresses:DNS服务器地址。这里我填了国内的223.5.5.5(某公共DNS)和8.8.8.8(另一公共DNS)。你完全可以根据自己环境替换成路由器地址或内网DNS。
如果你用的是桌面版Ubuntu(带图形界面的那种),同样结构可以,但要再加上一行:
network: version: 2 renderer: NetworkManager ethernets: ens33: dhcp4: no addresses: - 192.168.1.200/24 routes: - to: default via: 192.168.1.1 nameservers: addresses: [223.5.5.5, 8.8.8.8]看到区别了吗?只有renderer不一样。这是因为桌面版Ubuntu默认由NetworkManager管理网络,如果你强行用networkd,图形界面的网络设置可能会显示异常,甚至在重启后网络起不来。
3.2 应用配置与正确验证姿势
保存文件后执行:
sudo netplan apply这里有个巨坑:sudo netplan apply不会提示“成功”,而是静默生效。如果配置正确,你就直接断网再联网,好像什么都没发生;如果配置错误(比如网关不可达),等几秒你才会发现网络不通。所以验证时必须分三步:
ip a确认网卡上的地址是否变成了192.168.1.200。ip route show确认默认路由是不是你写完的网关。ping -c 4 223.5.5.5确认能出外网,ping -c 4 baidu.com确认DNS解析正常。
如果第3步外网不通但前两步正常,多半是DNS问题。你可以临时在命令里加@来指定解析服务器测试:
ping -c 4 8.8.8.8 ping -c 4 www.baidu.com前者通后者不通,那就是DNS该换了。另外提醒一点,配置文件修改后最好用sudo netplan try预览,如果配置有问题它会倒计时自动回滚,比直接apply安全。我第一次实操时直接apply,结果忘了写网关,网络直接消失,回滚都找不到入口,最后还是靠备份文件手动恢复的。强烈建议养成try优先的操作习惯。try命令会先测试配置10秒,如果超时未确认就自动回滚,这给你留了充足的试错窗口。
4. PyCharm远程开发的场景与方案选型:不是所有情况都适合连远程
固定IP搞定后,远程连接的环境基础就有了。但要不要用PyCharm连服务器,以及怎么连,这事取决于你的开发场景,选错方案会直接导致你后续开发效率腰斩。
我个人总结了三种最常见的场景,方便你对号入座:
| 场景 | 代码位置 | 推荐方案 | 原因 |
|---|---|---|---|
| 本地有完整项目,服务器只是跑训练/脚本 | 本地 | 传统Deployment + 远程解释器 | 保留IDE全部本地功能,服务器当计算资源 |
| 团队协同,代码主要在服务端仓库 | 服务器 | JetBrains Gateway | 代码、环境都在服务器,本地只当瘦客户端 |
| 偶尔连上去改个配置、跑条命令 | 无所谓 | 直接用PyCharm内置终端SSH | 简单轻量,不涉及解释器配置 |
之所以要先想清楚场景,是因为PyCharm的“远程开发”其实有两条完全不同的路线,我分别讲一下,你就能明白为什么不能盲目跟教程。
4.1 传统方案:Deployment + SSH解释器
这是PyCharm长期以来的经典方案,核心逻辑是:本地文件通过SFTP上传到服务器指定目录,服务器上的Python解释器负责执行,执行结果和输出回传到本地IDE显示。
优点:本地代码树完整保留,补全、跳转、重构这些功能全在本地跑,流畅度很高;断网时本地代码依然可编辑,恢复网络后自动同步。
缺点:必须手动管理文件同步。你改了本地代码,如果不配置自动上传(或忘记按同步按钮),服务器上跑的永远还是旧版本。多人协作时这个模式更容易出问题,两个人改了同一个文件,上传覆盖就是灾难。
4.2 新一代方案:JetBrains Gateway
JetBrains Gateway的思路完全不同:代码、解释器、虚拟环境全部留在服务器上,本地PyCharm退化成纯客户端,负责渲染界面。
优点:彻底告别“文件同步”的概念,你编辑的是服务器上的文件直接落盘;环境一致性极强——队友在服务器上配好依赖,你连上去就是一样的;笔记本磁盘占用几乎可以忽略。
缺点:对网络延迟和稳定性要求高,每次按键和操作都要和服务端通信,如果网速不好,敲代码会有肉眼可见的延迟感。同时,所有依赖和解释器都得在服务器上装好,你在本地再怎么折腾也没用。
4.3 迁移思考:固定IP对两条路线的实际影响
无论走哪条路线,固定IP都解决了同一个致命问题:SSH连接地址不能变。尤其是Teams里跑着长任务或训练的时候,IP一变,整个人都懵了。灵活使用固定IP之后,我在PyCharm里只需要把SSH主机地址写死为192.168.1.200,再也不用每次去路由器后台查地址了。更重要的是,很多连接超时问题,根源就是地址飘了,你却误以为是网络或防火墙问题。
5. 从SSH到解释器:PyCharm连接服务器的完整配置链路
这里我以传统方案(Deployment + SSH解释器)为主线讲解,因为它覆盖了绝大多数人的使用路径,也最适合从零开始理解。每一个环节我都会标注“为什么这样做”,避免你像当年的我一样每一步都踩一遍。
5.1 前置条件:确保SSH服务开启且免密可用
再强调一遍,如果SSH服务没启动,后面所有配置全是白搭。在服务器上执行:
sudo systemctl status ssh如果没启动,直接:
sudo systemctl enable --now ssh很多人会漏掉防火墙规则。如果你在服务器上启用了ufw:
sudo ufw allow OpenSSH sudo ufw status确保22端口是允许状态。我自己调试时经常遇到“连接超时”但不知道到底是防火墙还是IP问题,后来发现用nc -vz 192.168.1.200 22在本地测一下端口是否通,比反复重连高效得多。
强烈建议配置SSH密钥登录,这一步才是“一劳永逸”的关键:
ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/id_ed25519 ssh-copy-id -i ~/.ssh/id_ed25519.pub user@192.168.1.200密钥认证比密码认证安全得多,而且PyCharm连接时不需要弹出密码框。如果你用的是Windows本地机器,ssh-copy-id可能不可用,可以手动把id_ed25519.pub内容追加到服务器的~/.ssh/authorized_keys文件末尾,注意权限:服务器上.ssh目录权限最好是700,authorized_keys文件权限600。权限不对,SSH会直接拒绝密钥登录。
5.2 在PyCharm中配置远程解释器与Deployment
打开PyCharm,进入File -> Settings -> Project: xxx -> Python Interpreter。点击齿轮图标,选择Add... -> SSH Interpreter。这里你就能看到两种选择:New server configuration(新连接)和Existing server configuration(复用已保存连接)。
如果是新连接,填写你的服务器IP、用户名,然后在下一步里选择解释器路径。这里有个容易被忽略的细节:很多人直接在“System Interpreter”里选了/usr/bin/python3,连接是成功了,但pip安装的包都装到了系统环境里。更好的做法是提前在服务器上建好虚拟环境。我在服务器上的组织方式是:
cd /srv/production/my_project python3 -m venv venv source venv/bin/activate pip install -r requirements.txt然后把PyCharm解释器路径填成/srv/production/my_project/venv/bin/python。这样你的项目依赖和系统环境隔离,后续升级系统Python也不会把项目搞挂。
接下来配置Deployment。Tools -> Deployment -> Configuration,点+新建SFTP服务器,填上主机地址、用户名和认证方式。最核心的一道配置是Mapping——Local Path填你本地项目根目录,Deployment Path填服务器上相对于Root Path的目录。我刚接触时总把Deployment Path想当然填成绝对路径,结果上传后文件跑到了一堆不可思议的目录里。正确逻辑是:服务器上的路径由Root Path + Deployment Path拼接而成。比如Root Path是/srv/production/my_project,Deployment Path填/,本地文件就映射到服务器项目根目录下。
配置好后,在Deployment配置界面Options标签页勾选Upload changed files automatically to the default server里的Always,开发时改完代码自动上传。注意:自动上传只对修改过的文件生效,你新建的文件有时不会被自动识别,需要手动右键上传,这是新版PyCharm的一个老毛病。
5.3 路径映射与文件传输的坑
跑开发时,PyCharm会把本地文件传上去执行。但如果代码里有路径信息,你可能需要在运行配置里把工作目录改成服务器上的实际路径。比如训练脚本要读取/srv/data/xxx,你不能指望程序自动把路径换成云端的,得在Run/Debug Configurations -> Working directory里手动设置。
遇到中文文件名或含空格的文件时,SFTP传输偶尔会乱码或失败,快稳准的办法是:在服务器上习惯用全英文命名,路径完整避免特殊字符,能少掉80%的传输类问题。
还要注意文件权限。上传的文件默认不会设置执行权限,如果你有个.sh脚本要跑,先在服务器上chmod +x再执行,避免在PyCharm里报“Permission denied”。
5.4 端口转发:服务器上的服务如何在本地访问
远程开发并不只是跑脚本。很多时候你本地要用localhost:3306连服务器上的MySQL,或者把Flask的8000端口映射过来调试。PyCharm里可以在Tools -> Deployment -> Configuration -> Port Forwarding配置一组SSH隧道。
我常用的配置是:本地端口填3307(避免和本地装的MySQL冲突),目标端口填3306,目标地址填服务器局域网IP或localhost。保存后,你本地连127.0.0.1:3307就能访问服务器上的MySQL。这个功能本质是SSH本地端口转发,不需要在服务器上额外开端口,安全性也更高,因为服务不会被外部直接访问到。
端口转发还有一个更省事的用法:在项目设置里的Build, Execution, Deployment -> Deployment -> SSH Configurations里选中连接,然后Port Forwarding标签页新增规则,你会发现这台服务器上暴露的端口,可以全配成你能用的一整套本地端口。
5.5 JetBrains Gateway模式的配置要点
如果你决定走Gateway路线,需要在本地下载JetBrains Gateway,然后在服务器上装一个“后台IDE”组件。首次连接时Gateway会要求选择IDE版本(比如PyCharm Professional),选好后会自动在服务器上下载安装。
这个模式让我最惊讶的是:配置好之后,本地电脑上几乎不需要安装任何Python环境,连解释器都是服务器上的。如果服务器之前没有图形库或xvfb,部分调试场景可能受限,但普通脚本开发完全没问题。注意网关模式需要服务器能访问JetBrains官网下载组件,如果你的服务器只有内网不能外网,要么离线安装,要么换回传统方案。
6. 验证清单与翻车现场:重启后掉配置、连不上、同步丢失怎么办
所有配置完毕,不代表万事大吉。真正的考验在后面。下面列出我稳过排查的验证步骤,以及几个频发的翻车现场,每个都有对应的解决方案。
6.1 重启后IP是否保持固定的完整验证
sudo reboot重启完登录,执行ip a,看IP是否还是192.168.1.200。如果是,netplan配置生效;如果不是,恭喜你踩到了最经典的坑:配置文件语法没问题,但没被netplan识别。
排查方法:
sudo netplan generate sudo journalctl -u systemd-networkd --no-pager | tail -30前者会检查YAML语法并生成后端配置,后者能让你看到networkd报错日志。最常见的原因有两个:文件权限不正确(netplan要求权限为600),或者文件名没有被系统扫描到(要求以.yaml结尾)。
6.2 PyCharm连接报Connection timed out
这个报错最让人头大。按顺序排查:
- 确认服务器IP是否变了(回到第3章检查
ip a)。 - 确认22端口通不通:
nc -vz 192.168.1.200 22。 - 确认
ssh服务有没有起来:sudo systemctl status ssh。 - 确认防火墙规则:
sudo ufw status。
如果以上全过但PyCharm还是连不上,检查本地SSH密钥权限有没有开。Windows下如果你把私钥放在C:\Users\xxx\.ssh\id_ed25519,权限设置不对会直接拒绝;可以把密钥放到PyCharm的Settings -> Tools -> SSH Configurations里,直接用密码认证绕过密钥,但建议还是把密钥权限理清楚。
6.3 文件同步丢失:远程和本地代码不一致
这个翻车现场的处理我一直觉得是PyCharm的槽点。自动上传只对修改过的文件生效,新文件要手动上传。
一种可靠的应对办法是把Deployment配置里的Root Path与本地项目路径对齐,然后每次启动开发前手动执行一次Tools -> Deployment -> Upload to xxx,之后依赖自动上传。如果你用的是Git仓库,更推荐的方式是:在服务器上直接git pull,把同步交给Git,而不是SFTP。这样本地改代码、提交、推送,服务器上拉取,既避免了文件对比混乱,也天然解决了多人协作覆盖问题。
6.4 远程解释器里import报错:依赖确实装了,但PyCharm看不到
这是新手极其容易忽略的点。你明明在服务器上用pip安装了numpy,PyCharm的远程解释器里却一直飘红。原因多半是PyCharm连接的解释器路径,和你pip安装的虚拟环境不是同一个。
仔细看PyCharm设置里的“Interpreter Path”,如果你填的是/usr/bin/python3(系统解释器),那pip装到什么venv都没用。解决办法就是按第5.2节的方式,在服务器目标虚拟环境建好后,把解释器路径指向venv/bin/python。顺带说一句,如果你用conda环境,路径通常形如/home/user/miniconda3/envs/xxxx/bin/python。
6.5 配置固定IP后宿主机无法访问服务器
这个问题发生在虚拟机/容器场景比较多。你给Ubuntu虚拟机配了192.168.1.200,但宿主机的网卡(比如VMnet8)地址不在192.168.1.x网段内,两个机子之间根本不在一个局域网,自然无法访问。处理办法是:换用桥接模式,或者把虚拟机的IP配置到和宿主机同一网段,并保证网关指向正确。这一步经常被教程忽略,但实际部署时十次里有五次卡在这。
最后:我踩过几次坑之后的一条心得
如果你想把整套链路配置一次搞定,我强烈建议把所有配置项的IP、路径、端口全部记成一份文档,命名固定为server-info.txt放在本地。别嫌麻烦,我每次在“配置固定IP和PyCharm连接”之间往返时,最浪费时间的就是回忆当初填了什么IP、端口和目标路径。这份文档不仅能帮你快速排查,也能在几个月后重装系统时,让你十分钟恢复全部配置。
另外一个小技巧:固定IP的子网和DHCP地址池如果冲突,会出现间歇性断网。解决方式是在路由器端给服务器配置DHCP静态绑定(MAC地址与IP绑定),或者在netplan里选一个足够偏的IP。我个人倾向于前者——利用路由器的静态租约功能,这样如果哪天想换回DHCP,也不会出问题。
这篇内容基于我在Ubuntu 20.04和PyCharm 2023.1版本上的实测经验,配置的思路在其它版本上基本通用。如果遇到版本差异产生的坑,优先看官方文档里关于netplan和remote development的说明,那是最权威的。祝你配置顺利,别再被动态IP折磨了。