Projector基本介绍
用JetBrains或者Android Studio开发项目有时候会有一个需求,就是本地的笔记本性能比较弱,或是有便携需求,或是系统不兼容(比如本地习惯用Mac,但是开发必须用Linux编译),或者单纯就是类似WSL的场景但是Linux里没有好用的图形界面,这个时候就希望能在远程机器上编译代码,而在本地机器上开发调试。
这个需求如果是VSCode,只需要装WSL、Remote等插件就能轻松搞定。VSCode的原理是在远程设备上运行了一个VSCode Server,这个Server负责做代码解析等操作,然后通过ssh把解析好的内容传输到本地,对带宽占用是很小的,稳定性非常好。
而同样的需求到了JetBrains上情况不太一样。在JetBrains Gateway推出之前,JetBrains的原理不太一样,整个IDE要跑在远程设备上,本机要想访问,要么直接走VNC一类方式直接把图像全部传过来,但是占用带宽大,要么用Projector,把IDE要显示的GUI元素信息传递到本机,然后在网页里面把GUI绘制出来。
Gateway是付费软件,而且好像不支持Android Studio,所以已经停止维护的Projector也还能凑合用(但是不支持最新版本Android Studio,我自己还在用的Android Studio 2021.2.1 Patch 1是没问题的)。这篇文章就是简单介绍Projector配置的一些问题。
Projector安装
Projector的配置基本可以参考这篇文章,但是还有一些坑需要填。
GitHub - joaquim-verges/ProjectorAndroidStudio: Guide to setup JetBrains Projector and access Android Studio from any device
Ubuntu中的安装
1 | $ sudo apt update |
下载好Android Studio Linux包,例如放在 ~/apps/android-studio
目录。运行 projector config add
输入AS的路径,就会马上生成一个Config。但是默认的Config是有一些问题的,需要做一下修改。
1 | # 查看config |
运行下面的命令,在远程启动projector
1 | projector run Android_Studio |
然后在本机浏览器输入网址 https://<REMOTE_IP>:9999
即可访问,例如 https://192.168.5.110:9999/
。 当然前提是本机可以访问这个地址,我用的是家里的局域网,也没有防火墙,所以直接就能访问。
HTTPS和PWA
但是有个很烦的问题来了,每次都会提示https的签名不对,每次都要在浏览器里点continue确认继续访问。
而如果你想长期使用Projector,每次在浏览器里打开,和众多标签混在一起也很烦。于是你想借助Chrome / Edge的创建App的功能,给这个网址生成一个单独的App(我们称之为PWA),有自己独立的窗口和图标,这样就会方便很多。但是,当https证书有问题的时候,PWA就会自动跑到浏览器里打开网页,这让我很不爽。一开始觉得是不是有Bug,好在我就是做Edge浏览器的,在同事群里试着问了一下,结果真就有人指出来了具体代码。看了下发现这个是Chromium有意设计的,不是Bug而是By Design,这里的考虑是PWA比一般的网页有更大的权限,如果有SSL错误就不安全,所以直接转到浏览器打开了。这里把代码也贴出来,注释写的挺明白的。
ssl_error_controller_client.cc - Chromium Code Search
安装自定义证书
由于以上两个原因,就必须想办法解决projector https证书的问题。网上找了半天,相关的资料太少了,结果最后发现挺简单的,projector本身的命令行就能搞定,运行下面命令生成一个证书(Certificate)给Android Studio。
1 | Y9000P ➜ ~ projector install-certificate |
然后在远程可以看到Certificate在这里:
1 | Y9000P ➜ ~ cd ~/.projector/ssl |
直接在本机运行scp把Certificate复制到本机:
1 | ➜ ~ scp [email protected]:/home/jzj/.projector/ssl/ca.crt ./ |
Mac上直接双击,默认会用Keychain安装到系统。然后打开Keychain Access,找到这个证书,右击菜单选Get Info,然后在Trust里选择Always Trust就可以了。重新启动Projector,重新启动浏览器访问,就发现证书已经没问题了。
最终的效果就是我可以安装一个PWA在里面跑Projector。
如果嫌每次手工启动Projector需要同时操作Server和本机太麻烦,还可以写个function搞定,保存到 .bashrc
,以后直接运行 startProjector
即可启动或重启Projector。
1 |
|
自动切换host
在这之后我又有了一个新的需求,我有多个运行Projector的远程主机,例如在家和在公司用的主机IP是不一样的,但是配置都是一样的,现在想随时切换不同的主机。
最简单直接的办法,是在shell脚本里传不同的HOST参数。但是这样会有个问题,PWA里的URL是固定的,我需要给每个HOST都装一个对应的PWA,不够方便。
能不能在本机 /etc/hosts
直接定义一个host来映射到不同的主机?这样我所有的操作都可以用这个host来操作,包括ssh,projector,adb等等。
这么做是可行的,下面的脚本可以用ping自动检测多个主机,按优先级能连上哪个就用哪个,然后设置到host中,之后就可以用 https://develop:9999 访问Projector了。
备注:部分代码是ChatGPT写的,Mac已经测试通过,没有在Linux上测试。
1 | setMachineAuto() { |
生成和安装Self-Signed Certificate
这么做又会遇到新的问题,浏览器再次报Certificate错误。
借助ChatGPT查了一番发现了问题所在,原来Certificate里是指定了域名的,而develop这个域名不在Projector自动生成的cert里,所以浏览器报错了。Cert里的这个东西叫做SAN(Subject Alternative Name)。
Projector命令行自动生成Certificate还是不太可控的,于是尝试自己直接生成Certificate。这种Certificate也叫Self-Signed Certificate,因为是自己生成的证书,而不是第三方颁发的证书。
先定义一个openssl.cnf
配置文件。注意:在最后面的alt_names
里,可以添加所有你想用来访问的host和IP,其中IP不支持通配符,DNS支持通配符但是不建议直接写个 *
,可能会导致浏览器判断出错。
1 | [req] |
然后运行脚本生成Certificate,要用到前面的配置文件。其实配置文件里的参数也可以直接命令行传,但是写配置文件会更方便一点。
1 | openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 3650 -nodes -config openssl.cnf -extensions v3_req |
注意:一定要在后面指定参数-extensions v3_req
,如果不指定,这个alt_names
就不会生成到Certificate里,而且你在生成的时候看不到任何报错,最后在浏览器里会报下面的错误。这个问题害我找了挺久才发现,ChatGPT有时候挺坑的……
1 | Subject Alternative Name Missing The certificate for this site does not contain a Subject Alternative Name extension containing a domain name or IP address. |
运行完就会生成证书cert.pem
和 私钥key.pem
,运行下面的命令可以查看cert的信息:
1 | openssl x509 -in cert.pem -noout -text |
如果cert没问题,应该可以看到SAN如下:
1 | X509v3 extensions: |
实际在浏览器中,也可以看到一个网站的证书详情,点击URL左边的锁,点Connection is secure
,再点里面的证书图标就可以了,知道了这个可以更方便的排查问题。比如Google的证书:
运行下面的命令把生成的Certificate安装到Projector中:
1 | projector install-certificate --certificate cert.pem --key key.pem |
然后把 cert.pem
下载到本机,我用的还是Mac,和前面一样用KeyChain App添加到系统,设置成信任就可以了。在系统KeyChain里,同样可以看到一个Cert的详细信息,包括前面我们生成时设置的SAN。
最后的效果就是,每次我的网络环境发生变化,就运行一下setMachineAuto
,会自动根据我的网络找到最合适的机器,设置到系统host里。然后我所有的操作都直接用develop这个host访问就可以了,https不会报Certificate错误了,PWA也是没有问题的。