远程工作流

远程工作的需求无非两个:

  1. 远程执行命令。
  2. 在远程与本地之间进行文件的双向传输。

所有的远程工作流都需要考虑如何提高这两个操作的效率。

1. 一般远程工作流

对于一般的远程机器,我们可以通过 ssh 进行连接和操作,并使用 scp 命令或 SFTP 客户端实现双向文件交换:

1
2
3
4
5
6
7
8
# 登录开发机
ssh dest_host

# 上传文件
scp path/to/local_file dest_host:path/to/remote_file

# 下载文件
scp dest_host:path/to/remote_file path/to/local_file

有很多可视化的 SFTP 工具能够代替 scp 命令完成文件双向传输,非常方便,例如 WinSCP、Xmanager 等。

主流的文本编辑器也都提供了对 SFTP 的插件支持,例如:

可以很方便地上传、下载、删除、编辑远程文件。

2. 中继机下的远程工作流

考虑到安全原因,公司常常会对远程开发机的入口做限制,想要连接开发机必须以一个中继机器作为中介。这时候我们需要两次 ssh 连接:首先连接到中继机,然后从中继机连接到开发机。

1
2
3
4
5
6
# 登录到中继机
ssh relay_host

# 现在我们已经在中继机上…
# 登录开发机
ssh dest_host

中继机的存在除了造成登录更复杂之外,也使得文件传输更难实现,因为绝大多数 SFTP 工具都没有中继功能,在这种情况下无法使用。

按照传统的方案,我们需要两次 scp 命令来完成一次文件上传操作:首先从本地上传到中继机,然后从中继机上传到开发机。但是这种方式显然太复杂了,而且大部分中继机对安全的要求非常苛刻,只允许使用 ssh 命令,导致 scp 方式失效。

此时我们有以下三种方案来实现文件传输功能:

2.1 SSH 隧道

为了避免重复性的中继命令,我们可以借助 ssh 提供的“隧道”功能。该功能可以透过任意数量的中继机,在本地机器与目标机器之间建立一条“隧道”。因此,文件的上传、下载依然可以通过本地机器上的一条命令完成。

同时,SSH 隧道有一个巨大的好处:所有的 SFTP 工具依然可用,因为隧道对外部是透明的。

关于隧道功能,可以查看 ssh 帮助手册中的 -ProxyJump-ProxyCommand-R-L 等参数的用法。

不过使用该方案有两个前提:

  1. ssh 版本必须足够新,以支持隧道功能(OpenSSH 7.3 +)。
  2. 中继机必须允许 TCP 转发。

但不幸的是,很多中继机对安全的要求非常苛刻,不允许 TCP 转发。在这种情况下,该方案无法工作。

2.2 szrz 工具

szrz 是一个轻量、便捷的解决方案,其内部采用的 ZModem 协议非常底层,对中继机是透明的。因此 szrz 是中继机环境下文件传输问题的天然解决方案。

szrz 容易使用,配置完成后,在开发机的控制台中使用 sz 命令下载文件,rz 命令上传文件,同样可以透过任意数量的中继机。

但 szrz 有两个严重弊端:

  1. 不支持大文件传输(超过 30MB 的文件就会把控制台卡死)。
  2. 丧失了 SSH 协议的一切好处,比如安全性、丰富的 SFTP 工具等。

2.3 不使用 SSH,而是借助 FTP、HTTP 等其他协议

既然 SSH 协议被中继机限制了,那我们不如另立门户,借助 FTP、HTTP 等其他协议来实现文件传输。考虑到 FTP 天然适合静态文件服务,比 HTTP 高效很多,所以我们一般选择搭建 FTP 服务。

FTP、HTTP 服务器是非常成熟、稳定的技术,基本上随意挑选一款工具都可以满足我们的需求。我们以 pyftpdlib 为例:

  • 在开发机上安装 FTP 工具:
1
pip install pyftpdlib
  • 启动 FTP 服务
1
python -m pyftpdlib # and many other options ...

我们实际在用的启动命令:

1
2
# 考虑安全因素,可设置用户名和密码
python -m pyftpdlib --directory /home/work/ --port 8888 -r 8000-9000 --user username --password ****** --write

FTP 服务非常稳定,极少出错,因此你可以把上述命令放到后台执行,并且丢弃其日志:

1
nohup python -m pyftpdlib ...blahblah... >/dev/null 2>&1 &

开发机配置完成之后,我们就可以在本地进行文件上传、下载操作了:

1
2
3
4
5
# 下载文件
curl ftp://dest_host:8888/tmp/test.tar.gz -o test.tar.gz -u username:******

# 上传文件
curl -T test.tar.gz ftp://dest_host:8888/tmp/test.tar.gz -u username:******

FTP 解决方案的优势如下:

  1. 支持大文件,并且传输速度是三种方案中最快的。
  2. 天然支持可视化,可直接把 ftp 地址输入浏览器查看、下载文件。
  3. 安全性:比 SSH 稍弱,但考虑到开发机仅公司内网可见,因此并不需要过度担忧。
  4. FTP 与 SFTP 一样,有着丰富的第三方工具可用。

3. 终极远程工作流:实现远程实时编辑

文件的上传下载其实是个低频需求,远程实时编辑开发机上的文件才是真正的痛点,这样就实现了远程工作空间(remote workspace)。在这个需求上,SSH 隧道和 FTP 解决方案更能充分提现其优越性。

目前主流的文本编辑器都支持 SFTP、FTP 等插件,比如:

这些插件可以在本地目录和远程 SFTP/FTP 目录之间建立映射,从而实现远程实时编辑开发机上的代码(以下图片引自 Sublime Text SFTP):

Mapping a Folder to a Remote

当然,你也可以不做实时映射,而是使用手动方式同步本地和远程的代码:

Editor Menu

在这种工作流下,编辑远程机器上的代码与编辑本地代码没有任何差别。

相比如下两种工作流:

  • 本地编辑代码->上传到开发机->发现问题->重复以上三步(或使用 vim 做简单修改)
  • 登录开发机->使用 vim 编辑代码(这种方式的弊端是不够工程化,大代码量难以管控)

remote workspace 工作流有着可视化编辑器的加成,在实践中可以大大提高开发效率。