【远程开发】穿越跳板机和CLion远程开发——全面配置流程


tips:本文讲了两种穿越跳板机的方案(推荐ProxyJump方案),和两种代码映射的方案。实际任选一对搭配即可。

穿越跳板机

远程开发有时是在集群中进行,而集群中的机器位于内网环境。为了安全地访问这些内部服务器,通常会设置一个跳板机,这是在网络中的安全性边界处设置的关键访问点,用以增强整体安全性。

“穿越跳板机"就是从外部机器连接到内部服务器(以下简称"目标机"或"远程机”)的过程。

一种简单的做法是:用户先通过ssh连接到跳板机,然后再通过跳板机ssh连接到目标机。然而,这种方式在实际操作时会让人感到繁琐,因此可以通过shell工具提供的"Expect登录脚本"功能来自动化地实现,Xshell、Tabby等shell工具都有这个功能。但是我们的远程开发工具(如jetbrains IDE、vscode)并不支持,可能它也不适用于远程开发,因此要寻找更有效的解决方案。

一般所说的"穿越跳板机"指的是更加高级且无感知的方案,通过隧道技术(Tunnel)来实现,通常有两种做法:

  • ProxyJump(跳板代理):这是ssh工具本身提供的功能,可以通过ssh命令实现,但通常在ssh配置文件(通常为~/.ssh/config)中配置会更为方便。它通过指定一个中间服务器(跳板机),从而通过该服务器访问目标机器。
    使用ProxyCommand(代理命令)也能达到相同的目的。ProxyCommand是ProxyJump的超集,能够设置更复杂/灵活的代理。但仅对于实现跳板代理来说,ProxyJump是更加简单的方式。
  • 建立Tunneling(隧道转发):使用专门的隧道工具。隧道工具可以用于各种网络服务,而不仅仅是SSH。它可以用于创建安全的通信通道,如VPN、端口转发等。然而本文我们搭建的只是 SSH Tunnel,它只能用于SSH,与跳板代理在本质上有相似之处。

下面对这两种方案分别进行详细的介绍。

配置 ProxyJump 方案

跳板代理可以使用命令来指定:

  • ProxyJump的命令格式是:ssh -J <user@jump-host> <user@target-host>
  • ProxyCommand设置跳板代理的命令格式是:ssh -o "ProxyCommand=ssh -W %h:%p <user@jump-host>" <user@target-host>

但每次输入这么长的命令会很繁琐,而且JetbrainsIDE的SSH配置界面并不支持添加命令选项,因此我们采用配置文件的方式来实现。

  • 用户级的配置文件:~/.ssh/config
  • 全局配置文件:在windows上是%PROGRAMDATA%\ssh\ssh_config,在macos/linux上是/etc/ssh/ssh_config
  • 具体的配置格式参见ssh_config文件帮助手册

一般格式:

# 使用Host关键字创建块结构
# 别名通常是一个便于记忆的名字,配置完成后可以直接通过`ssh 别名`建立连接。
Host <别名>
    # 要登录的真实主机名,也就是平时我们使用ssh后面跟的地址名称,通常是ip地址。
	HostName <host>
    # 端口号,默认22
	Port <端口号>
	# 指定登录的用户名
	User <用户名>
    # 指定私钥文件。默认是~/.ssh/id_rsa或~/.ssh/id_dsa等文件,如果没有合适的密钥则会自动切换到密码身份验证方式。
    # 在windows上,如果用的是Cygwin的ssh,则可以配置成windows用户目录,否则ssh默认是在cygwin的用户目录中找密钥文件。
	IdentifyFile <私钥文件>

穿越跳板机的具体配置如下所示:

# 全局配置
Host *
    # 指定 SSH 客户端接受的远程主机(服务器)提供的主机密钥算法,添加对ssh-rsa的支持。(作为客户端时才有用)
    # 【为什么要配置HostKeyAlgorithms +ssh-rsa】
    # openssh8.8以上的版本认为ssh-rsa加密方式不安全, 因此默认不允许这种密钥用于登陆。
    # 如果使用ssh-rsa密钥会报错:Unable to negotiate with UNKNOWN port 65535: no matching host key type found. Their offer: ssh-rsa,ssh-dss.
    # 这个错误表明远程 SSH 服务器提供的主机密钥类型(Host Key Type)不被你的 SSH 客户端支持。
    # 具体来说,错误中提到服务器提供的两种主机密钥类型为 ssh-rsa 和 ssh-dss,而你的 SSH 客户端没有匹配的支持这两种类型的密钥。
    # Q: 我用的是密码登录,和这个有关系吗?
    # A: 虽然密码登录通常不涉及主机密钥验证(因为这主要用于密钥登录),但在连接时服务器仍然会提供主机密钥,
    #    并且客户端会尝试验证。如果服务器的主机密钥算法不在客户端支持的列表中,就会出现这个错误。
    HostKeyAlgorithms +ssh-rsa
    # 指定 SSH 服务器接受的用户公钥算法。(作为服务器时才有用,放在这里是为了提醒自己)
    PubkeyAcceptedKeyTypes +ssh-rsa
    # 指定密钥文件
    # IdentityFile <密钥文件>

# 跳板机配置
Host jump-host
    HostName <跳板机ip>
    User <跳板机用户名>
    Port <跳板机ssh端口>

# 远程机配置
Host remote-host
    HostName <远程机ip>
    User <远程机用户名>
    Port <远程机ssh端口>
    # 指定跳板代理。多个代理可以用逗号分隔,并且将按顺序访问。
    # ProxyJump jump-host
    # 也可以使用ProxyCommand来配置跳板代理。ProxyJump和ProxyCommand只需要配置一个。
    # 需要注意的是,JetBrainsIDE目前还不支持Windows上的ProxyJump。
    # 也就是说如果使用ProxyJump,你可以通过`ssh remote-host`连接到远程机,但在JetbrainsIDE中会连接失败。
    # 详见jetbrains issues:https://youtrack.jetbrains.com/issue/IDEA-214679/ProxyJump-not-supported
    ProxyCommand ssh -W %h:%p jump-host

如果想要使用密钥连接,则把公钥配置到跳板机和远程机各一份即可。

配置好之后,我们可以直接执行ssh <别名>代替ssh <user>@<ip>建立与服务器的连接

正常来说也可以照旧用ip进行连接,但这里碰到的一个坑是:配置了ProxyJump之后,不能再通过ip访问,必须使用Host别名。当然,如果直接把Host别名配置为ip就可以了。

测试:可以通过ssh命令测试跳板代理是否成功:

> ssh <ssh配置文件中的Host别名>
# 如
> ssh remote-host

输入密码(或使用配置好的ssh密钥)即可成功连接到远程机。


Cygwin上的配置

特别说明一下Cygwin上的配置。如果用的是Cygwin安装的ssh,则应该编辑cygwin目录下的ssh配置文件(如用户级配置文件是cygwin64安装目录/home/<user>/.ssh/config),而不是windows的。

由于我们可能即会用到windows自带的ssh,也可能会用到cygwin安装的ssh,因此两处的配置文件可能会写的十分相似。
一个令人愉悦的配置方式是,可以使用Include指令来使一个配置文件包含另一个配置文件。因此我们可以这样编写cygwin上的config:

# Include 包含其它配置文件。这里包含windows用户目录的ssh配置文件,就免得在两处编写同样的配置。
Include /cygdrive/c/Users/wushu/.ssh/config

# 全局配置
Host *
    # 指定的密钥文件。如果不设置,则默认是~/.ssh/id_rsa或~/.ssh/id_dsa等文件,如果没有合适的密钥则会自动切换到密码身份验证方式。
    # 当前用的是Cygwin的ssh,默认会在"cygwin安装目录/home/<user>/.ssh/"中找密钥。这里指定使用windows用户目录中的密钥。
    IdentityFile /cygdrive/c/Users/wushu/.ssh/id_rsa

特别注意:前面配置文件中的HostKeyAlgorithms +ssh-rsa一定要有,或者写在这个文件里。在撰写本文时,新安装的win11自带的ssh版本是8.6,如果仅仅是这样的话不加并没有关系;但Cygwin安装的ssh版本是9.3,不加一定会报错


建立 SSH Tunneling 方案

我们可以借助MobaXterm工具建立SSH Tunneling(SSH隧道)。
然后只需要ssh连接到本地的tunneling端口,就可以无感地将连接转发到远程机。

具体的配置如下:

  1. 打开MobaXterm,选择tunneling
    在这里插入图片描述

  2. 创建 SSH tunnel
    在这里插入图片描述

  3. 配置并保存
    在这里插入图片描述

  4. 点击启动。(还可以点选自动启动和自动重连)
    在这里插入图片描述

    第一次启动时,会提示信任身份,并要求输入跳板机的ssh密码(如果没有配置密钥)。

测试:启动后,可以通过ssh命令测试隧道转发是否成功:

> ssh <远程机用户名>@<本机ip> -p <本机tunnel端口>
# 如
> ssh user@127.0.0.1 -p 12345

此命令将直接连接到远程机,如果没有配置密钥,则会显示输入user@127.0.0.1的密码,实际上就是远程机的ssh密码

> ssh user@127.0.0.1 -p 12345
user@127.0.0.1's password: #输入远程机的密码
Last login: Tue Dec 12 16:42:38 2023 from xxx
Welcome to tlinux 1.2 64bit
Version 1.2 20130106 

代码映射

目前远程代码映射主要有两种方案:

  • 目录映射(传统):用ftp/sftp、webdav等方式建立目录映射,自动或手动地同步改动的文件。
  • 远程服务器(现代):jetbrains 的 gateway 和 vscode 的 remote-ssh 插件 都是这种方式。(其实严格来说这种不算是代码映射,而是远程控制)
    • remote-ssh 会在远程机安装一个vscode-server,本机的remote-ssh插件和远程机的vscode-server建立连接实现远程开发。
    • jetbrains gateway 会在远程机安装一个对应的IDE后台程序,并在本地启动一个瘦客户端(Jetbrains Client),瘦客户端和远程机的IDE后台程序建立连接实现远程开发。gateway既可作为一个独立的启动器安装,也默认捆绑在jetbrains的IDE中。

两种方案的优缺点分析:

  • 远程服务器方案
    • 优点:是彻底的远程环境。本地运行瘦客户端可以减少本机的内存占用。
    • 缺点:网络不好可能会出现卡顿,断网时无法进行编码。
  • 目录映射方案
    • 优点:在本地拥有代码文件,因此可以使用本地应用来访问代码,如使用git图形化工具来管理代码,使用notepad++查看文件的空白符。
    • 缺点:因为有本机和远程两份代码文件,因此可能存在比较麻烦的同步问题:大工程同步要很久,可能需要设置很多排除目录以降低同步时间;配置也比较麻烦;远程Debug时速度比较慢。
  • 二者各有优劣,我们可以按需选择。

CLion支持这两种方案(见CLion远程开发官方文档),下面进行详细的介绍。

目录映射方案

1. 配置SSH连接
在这里插入图片描述

上图示的Host和端口填写的是 ssh tunnel 方案的。如果你用的是ProxyJump方案则要填写远程机的Host(ssh配置文件中的Host别名)和端口。
在这里插入图片描述

2.1 配置sftp - 连接,使用刚刚配置好的ssh。“设为默认"的目的是用于在第3步"开启自动同步”(自动同步使用默认的Deployment)。Root path通常设置为远程机上的项目根目录
在这里插入图片描述

2.2 配置sftp - 目录映射
如果刚刚把Root path设置为远程机上的项目根目录,那么这里的"Deployment path"可以直接写"/"。
但如果项目很大,只想映射其中几个目录,可以通过点击Add New Mapping添加多个映射来实现。
在这里插入图片描述

2.3 配置sftp - 排除目录,按需配置即可。
在这里插入图片描述

3. 设置自动同步策略。按需选择。始终自动同步可能会导致IDE卡顿;按下Ctrl+S时同步是一个不错的选择。也可以不自动同步,而是完全手动上传和下载。
在这里插入图片描述

手动上传/下载/同步(查看差异):右击文件视图的文件或目录名,选择Deployment,可以对该文件或目录进行上传/下载/同步。
在这里插入图片描述


配置Rsync加速

在配置SFTP的时候,有一个Rsync选项。使用Rsync可以显著提高同步的速度。

摘自官方文档-windows客户端细节:对于 Windows 上的文件同步,默认情况下,CLion 依靠自己的远程主机访问(Remote Host Access),并使用 tar 工具在主机端进行压缩。这种机制比 macOS 和 Linux 上使用 Rsync 工具同步的速度慢。您可以在部署设置中选择 "使用 Rsync 进行下载/上传/同步 "复选框,在 Windows 上启用 Rsync 同步。
在这里插入图片描述

勾选它,然后配置Rsync

MacOS和Linux自带Rsync,所以几乎不需要再设置什么。前往Rsync的设置界面,点击Test Connection显示"successful"表示成功检测到工具,然后手动上传一个文件测试,一般都会成功上传。

Windows并不自带Rsync,根据CLion的提示,windows上推荐使用cygwin安装rsync和openssh,它们会被安装到cygwin的bin目录下。(首先要下载cygwin,然后用cygwin安装openssh和rsync。此文有讲解rsync的安装,用同样的方式再安装OpenSSH即可)

前往Rsync的设置界面,配置rsync和ssh的全路径,点击Test Connection显示"successful",然后手动上传一个文件来测试,如果成功那么恭喜你。但也可能会报错Unknown message with code "Rsync failed with exit code: 12"
在这里插入图片描述

Rsync options:--no-perms选项用来告诉rsync不要传输任何(文件或目录的)权限信息,否则由于windows和linux的文件权限管理方式不同,上传到linux的文件的权限会发生改变。如果远程目录也由git管理,则可以用git status、git diff <file>清晰的看到文件权限发生了变化。

如果报错,可能是因为安装的ssh版本高于8.8。解决方法是编辑 cygwin64\home\wushu\.ssh\config 文件(如果没有则手动创建),添加以下内容:

Host *
	# openssh8.8以上的版本认为ssh-rsa加密方式不安全, 因此默认不允许这种密钥用于登陆。
	# 此行作用是让客户端添加对ssh-rsa的支持。
	# Q: 我用的是密码登录,和这个有关系吗?
	# A: 虽然密码登录通常不涉及主机密钥验证(因为这主要用于密钥登录),但在连接时服务器仍然会提供主机密钥,并且客户端会尝试验证。如果服务器的主机密钥算法不在客户端支持的列表中,就会出现这个错误。
    HostKeyAlgorithms +ssh-rsa

然后再尝试上传/下载,应该就成功了。(本文在前面讲ProxyJump方案的时候,其实就已经在配置文件中添加了这条配置,目的就是应对这个问题)
如果还是失败,那么继续往下看,下面将讲解用于排查真正错误原因的方法。

——————
如何才能排查到真正的错误原因?

很多错误CLion都只会报Unknown message with code "Rsync failed with exit code: 12",通过这个根本无法得知具体是为何失败。因此我们需要手动测试rsync,看到底是哪里出了问题。

进行手动测试前必须要知道的一些事情:(否则这会成为大坑)

  • 我们必须保证自己使用的是用Cygwin安装的openssh和rsync。虽然windows本身也会提供一个ssh,但实际看来并不能用它,我尝试过直接在google上搜索openssh和rsync下载并安装,但实际测试始终不能成功,找不到具体的原因(心态崩)。
    具体测试时出现过的情况我记录在非Cygwin安装的openssh和rsync测试情况记录
  • Cygwin是什么?
    • Cygwin是一个在Windows上提供模拟Unix/Linux环境的开源软件(就像wsl)。因此它能够安装原生的linux工具,例如我们前面刚安装的openssh和rsync。
    • Cygwin在windows中模拟了Linux文件系统的结构,根目录与Cygwin的安装目录映射。
    • Cygwin提供一个终端工具Cygwin64 Terminal,在这里可以看到完整的linux目录。
    • Cygwin安装的工具只依赖于Cygwin环境,这包括一些环境变量、配置文件等,而不是依赖于Windows。例如,我们安装的ssh并不会读取C:\Users\<username>\.ssh\中的密钥和配置,而是读取cygwin64(安装目录)\home\<username>\.ssh\,因为cygwin64\home\<username>才是cygwin/ssh的用户目录。即便我们不在Cygwin64 Terminal中而是在cmd、powershell等外部终端中使用这些工具也是如此(看来是Cygwin为这些工具做了一些封装)。
  • 早期版本的CLion:启用rsync后,SSH将不能使用"密码"的身份验证方式(会失败),只能使用密钥方式验证。参见相关的Issues:Download from SFTP server using rsync fails with rsync exit code 12 on Windows。目前应该已经解决了,我测试用密码方式验证身份没有问题。

我们可以直接在Cygwin64 Terminal中测试。或者将cygwin64/bin/配置到Windows环境变量,这样就可以用windows上的终端(如cmd、powershell)来测试。就像刚刚说的一样,无论哪种方式,ssh使用的都是Cygwin提供的环境。

配置windows环境变量时注意:一定要配置到Path变量的最前面,目的是覆盖windows提供的ssh。配置好后重新打开cmd输入ssh -V,如果显示OpenSSH_for_Windows_xxx(Windows自带的ssh)则说明没有配置成功。

接下来我们尝试将一个text.cpp同步到远程机。在当前目录下创建一个text.cpp,然后输入以下命令:

# `v`越多日志越详细
$ rsync -avvv -e "ssh -p 12121" ./test.cpp user@127.0.0.1:~/test.cpp # 填写你的远程机用户名和地址(这里是本机tunnel的地址)
opening connection using: ssh -p 12121 -l user 127.0.0.1 rsync --server -vvvlogDtpre.iLsfxCIvu . "~/test.cpp"  (11 args)
Unable to negotiate with 127.0.0.1 port 12121: no matching host key type found. Their offer: ssh-rsa,ssh-dss
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(231) [sender=3.2.7]
[sender] _exit_cleanup(code=12, file=io.c, line=231): about to call exit(12)

可以看到,导致连接失败的错误原因是no matching host key type found. Their offer: ssh-rsa,ssh-dss

这是由于openssh8.8以上的版本认为ssh-rsa加密方式不安全,因此默认不允许这种密钥用于登陆。通过ssh -V看到我的openssh版本是9.3

有同学可能会有疑问:为什么我在CLion的Tools -> SSH Configurations里点击Test Connection显示的是连接成功,这里怎么却失败了呢?

  • 这是因为SSH Configurations里的Test Connection使用的是在环境变量PATH中找到的ssh,默认也就是Windows带的ssh,它的版本低于8.8(我的是8.6),所以直接就能连接成功。
  • 而当我们启用rsync后,rsync用的是我们在Tools -> Rsync界面中配置的ssh,也就是Cygwin的ssh,版本是高于8.8的,因此连接失败,才出现了退出码12的错误。
  • 既然这样,我们自然还会这么想:如果把rsync用的ssh配置成windows自带的ssh不就行了吗?这个问题其实还可以再进一步想:系统明明有ssh,为什么rsync还要我们配置ssh,并且建议都用Cygwin安装的。说实话我也不太清楚,CLion的官方文档中也并没有写。
    猜想的原因可能是:Cygwin安装的ssh和windows的ssh实现并不一样。尽管都是openssh,但Cygwin的ssh应该是linux上的实现,而Windows的ssh则是Windows上的实现。而cygwin安装的rsync的实现也应该是Linux上的实现。rsync的过程需要用到ssh,只有二者都是linux实现,才完全兼容,才能一起正常运行。

因此解决方法就是添加ssh -o HostKeyAlgorithms=+ssh-rsa选项,即:

> rsync -avvv -e "ssh -p 12121 -o HostKeyAlgorithms=ssh-rsa" ./test.cpp user@127.0.0.1:~/test.cpp # 填写你的远程机用户名和地址(这里是本机tunnel的地址)

但每次都输入选项会很麻烦,并且CLion也不支持添加选项。所以最终的方法就是前面说的,编辑 cygwin64/home/<user>/.ssh/config 文件(如果没有则手动创建),添加以下内容。ssh会自动读取此配置。

Host *
	# openssh8.8以上的版本认为ssh-rsa加密方式不安全, 因此默认不允许这种密钥用于登陆。
	# 此行作用是让客户端添加对ssh-rsa的支持。
	# Q: 我用的是密码登录,和这个有关系吗?
	# A: 虽然密码登录通常不涉及主机密钥验证(因为这主要用于密钥登录),但在连接时服务器仍然会提供主机密钥,并且客户端会尝试验证。如果服务器的主机密钥算法不在客户端支持的列表中,就会出现这个错误。
    HostKeyAlgorithms +ssh-rsa

然后再执行此命令,应该就可以把test.cpp上传到远程机。如果失败,也会显示具体的错误,那么继续排查即可,只要知道具体的原因,就比较好处理了。

本节到这就可以结束了。

————

非Cygwin安装的openssh和rsync测试情况记录

记录一下测试情况,报的错都比较难排查。其中Connection reset by peer是socket底层的错误,几乎无法排查。

我尝试理解这些错误:rsync需要和ssh配合工作,以及和远程的rsync/ssh进行通信。所以当涉及到不同平台实现的ssh和rsync配合以及通信时,出现不兼容是能够理解的。因此必须使用Cygwin安装的rsync和ssh(这应该都是基于linux实现的),才能和远程linux主机建立正确的关通信。

① 使用 Windows的openssh8.6 和 Cygwin的rsync3.2.7。这是我在手动测试时遇到的第一个问题,因为当时还不了解Cygwin,所以没有将cygwin64\bin配置在环境变量PATH的最前面,导致ssh命令调用的是windows本机的ssh。

> rsync -avvv -e "ssh -p 12121" ./test.cpp user@127.0.0.1:~/test.cpp
opening connection using: ssh -p 12121 -l user 127.0.0.1 rsync --server -vvvlogDtpre.iLsfxCIvu . "~/test.cpp"  (11 args)
rsync: connection unexpectedly closed (0 bytes received so far) [receiver]
rsync error: error in rsync protocol data stream (code 12) at io.c(600) [receiver=3.0.6]
_exit_cleanup(code=12, file=io.c, line=600): about to call exit(12)
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(231) [sender=3.2.7]
[sender] _exit_cleanup(code=12, file=io.c, line=231): about to call exit(12)

这个错误显示了本机和远程机的rsync版本号,因此起初我误以为是版本不兼容。花了老半天时间尝试将服务器的版本更新到与本机一致。非常麻烦,结果最后因为又编译rsync还需要gcc5.x以上(而我的是gcc4.8),我无法把gcc版本升级到5.x以上(怕公司的项目不兼容),就放弃了。

也顺便记录一下rsync的安装:下载对应版本的rsync,然后进行编译安装。(见rsync安装文档)
rsync依赖很多库,因此安装过程可能会比较麻烦。比如autoconf版本低,需要python3但centos6的yum没有python3。

  • centos6安装python3参考此文,但这个文章也是几年前的了,遇到问题请随机应变。安装python3后,再安装pip,然后pip install commonmark
  • 依赖安装完毕后,再回到rsync的解压目录下执行./configure,应该就不报错了。然后再执行makemake install

② 使用 Windows的openssh8.6 和 Google上找的rsync3.0.4;或者使用Cygwin的ssh9.3和Google上找的rsync3.0.4:

> rsync -avvv -e "ssh -p 12121" ./test.cpp user@127.0.0.1:~/test.cpp
opening connection using: ssh -p 12121 -l user 127.0.0.1 rsync --server -vvvlogDtpre.iLs . "~/test.cpp"
Unable to negotiate with 127.0.0.1 port 12121: no matching host key type found. Their offer: ssh-rsa,ssh-dss
rsync: read error: Connection reset by peer (104) # 这是socket抛出的错误
rsync error: error in rsync protocol data stream (code 12) at io.c(791) [sender=3.0.4]
_exit_cleanup(code=12, file=io.c, line=791): about to call exit(12)

③ 使用 Google上找的ssh7.3 和 Google上找的rsync3.0.4:

> rsync -avvv -e "ssh -p 12121" ./test.cpp user@127.0.0.1:~/test.cpp
opening connection using: ssh -p 12121 -l user 127.0.0.1 rsync --server -vvvlogDtpre.iLs . "~/test.cpp"
dup() in/out/err failed
rsync: read error: Connection reset by peer (104)
rsync error: error in rsync protocol data stream (code 12) at io.c(791) [sender=3.0.4]
_exit_cleanup(code=12, file=io.c, line=791): about to call exit(12)

远程服务器方案 (jetbrains gateway)

参见CLion官方文档:使用gateway进行远程控制

这种方案配置起来最简单。

本章开头提到:gateway 会在远程机安装一个对应的IDE后台程序,并在本地启动一个瘦客户端(Jetbrains Client),瘦客户端和远程机的IDE后台建立连接实现远程开发。gateway既可作为一个独立的启动器安装,也默认捆绑在jetbrains的IDE中。

我们只需要打开Gateway,或者打开CLion的欢迎界面,又或点击CLion菜单栏 -> File -> Remote Development...
选到Remote Development -> New Connection,然后配置SSH连接。
在这里插入图片描述
接着选择要安装的IDE后台程序,以及项目目录。gateway就会自动将IDE后台程序安装到远程机,然后打开项目。
在这里插入图片描述

gateway需要和远程服务器建立端口转发。如果提示The SSH port forwarding check failed,可能是因为远程机器禁止了端口转发。编辑/etc/ssh/sshd_config,将AllowTcpForwarding no改为AllowTcpForwarding yes。然后重启sshd服务再次尝试即可。

欢迎界面-Remote Development / SSH中会显示远程项目列表,此后可以通过这里打开项目。


远程Debug

参考CLion官方文档:远程Debug

CLion提供了两种远程Debug的方案:“远程Debug” 和 “远程GDB服务器”。此二者的区别在官方文档解释的很清楚,主要的限制或特点是:

  • “远程GDB服务器”:必须是CMake构建的项目,且Debug服务器只能使用gdb-server。

    什么是"debug服务器":gdb其实是CS架构的,远程debug需要在远程机器上运行debug-server,再通过本机的debug-client与之连接来实现。

  • “远程Debug”:适用于任何的构建方式,且Debug服务器可以用gdb-server,也可以用lldb-server。

由于我目前的项目并不是CMake构建的,所以这里选择选用更为通用的"远程Debug"方案。

步骤如下

① 远程机器安装gdb-server,并启动。
(暂时不清楚远程机器上的gdb-server和gdb的版本要不要保持一致或相近,如果碰到问题可以往这方面考虑。我这里安装的gdb-server凑巧和gdb的版本一样,都是7.2-50.el6)

# 安装
yum install gdb-gdbserver 

# 启动
gdbserver <监听的host>:<监听的port> <executable> # 启动gdbserver,并运行指定的可执行文件
gdbserver <监听的host>:<监听的port> --attach <PID> # 启动gdbserver,并attach到指定PID的进程
# 例。启动gdbserver,并attach到29834进程。监听1234端口,host省略表示允许来自所有host的连接。
gdbserver :1234 --attach 29834

建议在CLion的Terminal中建立ssh连接、启动gdbserver,all in IDE。

② 先在远程机器上测试一下。 在远程机器上另开一个shell,使用gdb连接到gdbserver,看能否成功。

> gdb <executable> # 此命令启动gdb并加载符号文件
# 在gdb命令行输入此命令,连接到gdbserver
# 格式:target remote <host>:<port>
(gdb) target remote 127.0.0.1:1234

③ 本地机器创建ssh端口转发。(非必须)

由于我的远程机只开放了ssh端口,没有开放其它端口,因此不能直接连接到gdbserver监听的端口。好在ssh提供了端口转发的功能,利用ssh端口就可以间接访问到远程机器上的其它端口。(这里只介绍利用ssh命令和config配置文件进行端口转发的具体操作,用MobaXterm的同学可以自行搜索"MobaXterm如何设置端口转发"。)

方法一:通过ssh命令进行端口转发:

# 建立ssh连接并配置端口转发。将本地1234端口映射到remote-host的1234端口
ssh -L 1234:localhost:1234 <remote-user>@<remote-host> -p <ssh-port>
# 如。这里的remote-host是前面在.ssh/config中配置的远程机host别名
ssh -L 1234:localhost:1234 remote-host # 此命令执行完后,会建立ssh连接和端口转发

方法二:在~/.ssh/config中添加端口转发的配置(如下),然后再执行:ssh remote-host

Host remote-host
	# (前面的配置这里就不写了)
    # 端口转发,本地1234端口映射到remote-host的1234端口
    # 注意,ssh端口转发只有在建立连接后才生效
    LocalForward 1234 localhost:1234

注意:SSH端口转发依赖于SSH连接,也就是说端口转发需要建立SSH连接后才生效,SSH连接断开后立即失效。因此在进行远程debug的过程中要保持ssh处于连接状态(建议在CLion的Terminal中建立连接,all in IDE)。

④ 测试端口转发是否生效

# (需要下载tcping工具,这个工具下载很简单,不用担心麻烦)
tcping 127.0.0.1 1234

此时要观察第③步中建立了ssh连接的窗口

  • 如果提示channel 3: open failed: administratively prohibited: open failed 则说明端口转发未生效,原因可能是远程机器禁止了端口转发。编辑/etc/ssh/sshd_config,将AllowTcpForwarding no改为AllowTcpForwarding yes。然后重启sshd服务再次尝试即可。
  • 如果提示channel 3: open failed: connect failed: Connection refused,大概是因为远程机上没有程序在监听这个端口,别忘了我们在第①步已经启动gdbserver监听了,可能刚刚被你不小心关掉了。

⑤ 配置 CLion 的 Remote Debug configuration

参考官方文档:The Remote Debug configuration

在这里插入图片描述

  • Symbol file:"远程Debug"方案要把符号文件(symbol file)放到本地,目的是让gdb客户端加载到调试信息。通常可执行文件本身就可以很好地用作符号文件,因此直接把远程机器上编译好的可执行文件下载到本机即可(可以利用前面的映射功能同步此文件)。

    低级错误提醒:编译时要使用-g选项才能为可执行文件加入调试信息。这个选项是我们平时调试时必须要加的。

  • Path mappings:配置本地的源码路径和远程机器的源码路径的映射。这样在debug时,程序才能在IDE设置的本地文件断点处停止。

  • Sysroot:动态库的本地根路径。根据官方文档的说法,大多数最新版本的GDB都可以自动下载动态库文件,因此不需要指定此字段。但如果不指定,每次启动Debug都会花费比较明显的时间重新自动下载,因此建议手动下载并指定这个路径

    • 自动下载库文件:稍后启动debug时,在"GDB"选项卡中可以看到自动下载的过程。
      在这里插入图片描述
    • 手动下载库文件:在GDB命令行中(在远程机器的GDB命令行或者上图的GDB选项卡)执行info sharedlibrary ,可以看到需要哪些动态库。将这些库拷贝到Sysroot路径下,注意目录结构要保持一致:绝对路径相对于Sysroot目录,相对路径相对于本地项目路径(准确说是相对于在GDB选项卡中执行pwd得到的路径)。
      在这里插入图片描述

原神(bushi) Debug !启动!😁
在这里插入图片描述
现在就可以像在本地运行一样检查代码。例如,像平时一样单步执行和检查变量。

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值