CodLe

Keep calm and make sure the growth is my own business.

如何利用实验室服务器进行远程开发

Codle / Jul 24, 2024


对于计算机研究生而言,一般在实验室都有配备的 GPU 服务器用于深度学习之类的开发(作者现在都才只有台 1070 的旧机子,哭泣 有了一块 RTX 2080 了!)。在很多情况下都有远程开发的需求,比如:晚上在寝室想改一下代码继续跑实验、周末在寝室摸鱼不想去实验室、实验室公用一台电脑当面不好操作等。

本文将详细讲解我采用的一些远程开发方法,其中需要用到的工具有:

内网穿透神器 frp

所谓内网穿透,就是将内网的主机映射到公网中,使得我们可以在任何地方都访问到该主机,一种简单的方法就是使用花生壳等软件实现,虽然操作简单,但是有着流量限制且该公司网页也让人感觉不太靠谱。所以还是自己来做比较好。

本文主要采用了 frp 开源软件来完成内网穿透的功能。frp 软件需要我们在公网服务器和本地服务器各开一个程序,公网服务器使用 frps 程序,本地服务器使用 frpc 程序。大致的结构为:

frp

用户访问公网服务 ip,frps 程序判断监视服务器端口,发现有用户的访问,将数据包发送给指定的端口服务程序。该端口由本地服务器的 frpc 与之通信,故数据包会发送到本地服务器上,这样就实现了在任意地点访问实验室服务器。

下载地址:https://github.com/fatedier/frp/releases 查看下载最新版本的程序,由于仍在开发阶段,故软件的架构可能会发生变更,请确保使用同一个版本的 frps 和 frpc 程序,不要混用。

官方中文文档:README_zh.md 提供了大量的示例以及非常丰富的功能。

SSH 穿透与 vscode 远程开发

SSH 穿透

公网服务器(阿里云等):将 frps 和 frps.ini 传到服务器上,修改 frps.ini 文件,这里使用了最简化的配置:

# frps.ini
[common]
bind_port = 7000

这里表示服务端监听端口为 7000,在服务端启动 frps 程序:

./frps -c ./frps.ini

本地服务器(带有GPU的机器):修改内网服务器 frpc.ini 文件,假设 frps 所在服务器的公网 IP 为 x.x.x.x;

# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000

[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000

common 里面需要填入服务端的 ip 地址与监听端口号,与 frps.ini 中的对应。ssh 配置内填写本地 ssh 地址与端口,并指明远程访问的端口。

接着在本地服务器运行:

./frpc -c frpc.ini

运行后,我们在其他的电脑即可使用:

ssh -oPort=6000 username@x.x.x.x

访问到实验室内网的服务器,username 为内网服务器用户名。

Tips

无论是在哪个服务器运行 frp 程序,他都是关掉 ssh 或者关掉终端就会停止,建议做成守护进程,以下是一些推荐的方法,按照简单到复杂排列:

  1. supervisor
  2. systemctl
  3. screen
  4. ...

supervisor 比较简单,写好脚本每次开机都会自启动。

结合 VS Code 远程开发

通过 SSH 穿透,那么我们就可以在本地很轻松的连接到了服务器,那么一些基本的 bash 指令就可以使用了,但是如何进行在线代码编辑呢,这里就要结合 VS Code 来使用了。VS Code 在最新的版本中提供了一系列 remote dev 插件,也就是远程开发插件,这一系列插件提供了 wsl、docker、ssh 等跨环境通信服务。我们这里主要使用了 ssh 功能。

密钥登陆 SSH

在结合 vscode 之前,我们需要给设置登陆 ssh 方式为免密码输入密钥登陆,因为 vscode 不支持使用密码的方式进行登陆。这一步骤可以参考微软官方的文档:https://code.visualstudio.com/docs/remote/ssh 也可以参考接下来我写的内容:

Note:确保你的电脑支持使用 ssh 相关指令,Windows 10 之后的版本都是支持的

首先,在计划连接的主机上(内网服务器)配置基于密钥的身份验证,方法是将本地公共 SSH 密钥添加到主机上的~/.ssh/authorized_keys

这一步骤的详细过程为:

  1. 检查本地计算机上是否已有 SSH 密钥。该公钥通常位于 macOS/Linux 上的 ~/.ssh/id_rsa.pub 或 Windows 上的 %USERPROFILE%\.ssh\id_rsa.pub 中。如果没有密钥,请在当前电脑(想要远程开发的主机)的终端/命令提示符下运行以下命令以生成 SSH 密钥对:
ssh-keygen -t rsa -b 4096
  1. 将本地公钥(id_rsa.pub文件)的内容添加到 SSH 主机上相应的 authorized_keys 文件中。

在macOS/Linux上,在本地终端中运行以下命令,根据需要替换用户名和主机名。

ssh-copy-id your-user-name-on-host@host-fqdn-or-ip-goes-here

在 Windows 上,在本地命令提示符中运行以下命令,并根据需要替换 REMOTEHOST 的值。

$REMOTEHOST="your-user-name-on-host@host-fqdn-or-ip-goes-here"

scp "$env:USERPROFILE\.ssh\id_rsa.pub" "${REMOTEHOST}:~/tmp.pub"
ssh "$REMOTEHOST" "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat ~/tmp.pub >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys && rm -f ~/tmp.pub"

Note:因为不是采用的 22 端口,因此在 scp 和 ssh 指令后面都需要在加上 -oPort=6000 指定端口号。

Remote SSH 插件

打开 vscode,在插件处搜索 remote ssh,安装结果的第一个插件。

vscode-install-ssh-remote

安装完成后左侧工具栏会出现一个新加的图标,点击后,选择 connection 的 Configure 选择本地的设置文件。选择第一个文件即可。

vscode-ssh-step

该文件是一个空白文件,按照以下格式写如配置文件:

Host ComputerName
    User username
    HostName x.x.x.x
    Port 6000

hostname 输入公网 ip,host 处的 ComputerName 可以替换成任意名称(注意不要写括号和中文字符)。

vscode-finish-remote

点击左下角,或者 TARGETS(SSH) 里面的对应主机即可连接到远程服务器,拥有等同于本地开发的体验。

Web 映射与公网访问

对于使用 Python 进行数据挖掘与数据分析的人员而言,Jupyter Notebook 是一个非常棒的工具,它可以在本地开启一个 Web 服务器供我们在本地网页进行编写程序。那么我们可不可以将该服务映射到公网使得在任意地点进行开发呢,答案当然也是可以的。这一功能也采用 frp 软件来进行实现。

frp 配置

对于公网服务器而言我们不需要什么额外的配置了,而对于本地的服务器,我们需要对 frpc.ini 增加配置。

[common]
server_addr = x.x.x.x
server_port = 7000

[web]
type = http
local_port = 8888
custom_domains = user_domain.com

新加了一个 web 配置,type 为通信类型,可选 http 或者 https,local_port 为本地的 web 程序端口,8888 是 jupyter 默认的端口,custom_domains 为公网域名,没有这一行则使用 ip 访问。

jupyter 公网配置

接下来我们需要对 jupyter 的一些设置进行修改,因为默认的 jupyter 只能在本地访问。这一部分的配置与网上的大部分教程类似,主要分为三步:

  1. 生成配置文件
  2. 生成密码
  3. 修改配置文件

生成配置文件相对比较简单,在终端输入以下命令,生成的配置文件会被保存到 ~/.jupyter/jupyter_notebook_config.py

jupyter notebook --generate-config

接着是生成密码,从 jupyter notebook 5.0 版本开始,提供了一个命令来设置密码:jupyter notebook password,生成的密码存储在 jupyter_notebook_config.json

最后是修改配置文件,使用编辑器打开配置文件,主要修改以下几行

c.NotebookApp.ip='*'
c.NotebookApp.open_browser = False

此时在终端启动 jupyter notebook 指令,我们就可以在公网进行访问 jupyter 网页了。

更多的需要做的

既然将服务器暴露在了公网,那么安全也是非常重要的一个要做,因此如果希望后续继续进行探索和研究,可以从以下几个方面: