痛点

今天在网上看到一个 R 编程语言的扩展包,解决了长期以来困扰我的一个难题:如果在本地终端编辑运行位于远程服务器上的 R 命令脚本,并在需要的时候,能够把远程的画图同步输出到本地,使得在本地也可以浏览画图效果。针对这个问题,其实我们可以有以下至少三种解决方案:

  1. Install RStudio Server on the remote server and use that from a web browser on your local machine. Graphics output is shown in the IDE.
  2. Use X11 forwarding (ssh -X|Y). Graphics output is sent back to your machine.
  3. Use VNC with a linux desktop environment like KDE or GNOME.

当然,第一种使用 Rstudio 其实是非常好的方案,运行在网页打开,整个界面其实就是本地化的 IDE,这也是我们团队目前使用的方案。但是,对于我这样使用惯了终端命令行的开发人员,更倾向于在 Sublime 编辑脚本,然后通过 SublimeREPL 把命令发送到远程服务器的解释器进行运行。长期以来,我一直在苦苦寻找这样的方案。

今天隆重介绍这个优秀的扩展包:rmote

解决

ssh 登录服务器

rmote 默认开启 4321 的服务端口,可以通过 rmote::start_rmote() 进行设置。这个命令是把远程消息同步映射到本地浏览器端

ssh -L 4321:localhost:4321 fl@192.168.1.166

启动 R 服务

通过以上命令我们就登录了远程服务器,接下来是启动 R 进程开始运行

R                                                                                                                                                                     [14:44:16]

R version 3.5.1 (2018-07-02) -- "Feather Spray"
Copyright (C) 2018 The R Foundation for Statistical Computing
Platform: x86_64-redhat-linux-gnu (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

  Natural language support but running in an English locale

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.


Attaching package: ‘emayili’

The following object is masked from ‘package:base’:

    body

> 

## 可以设置不同的端口
rmote::start_rmote()

?start_rmote
start_rmote               package:rmote                R Documentation

Initialize a remote servr

Description:

     Initialize a remote servr

Usage:

     start_rmote(server_dir = file.path(tempdir(), "rmote_server"), port = 4321,
       daemon = TRUE, help = TRUE, graphics = TRUE, basegraphics = TRUE,
       htmlwidgets = TRUE, hostname = TRUE, history = TRUE)

Arguments:

server_dir: directory to launch servr from

    port: port to run servr on

  daemon: logical - should the server be started as a daemon?

    help: (logical) send results of `?` to servr

graphics: (logical) send traditional lattice / ggplot2 plots to servr

basegraphics: (logical) send base graphics to servr

htmlwidgets: (logical) send htmlwidgets to servr

hostname: (logical) try to get hostname and use it in viewer page title

 history: (logical) should history thumbnails be created and shown in
          the viewer?

运行命令

输入命令运行

?plot

library(ggplot2)
qplot(mpg, wt, data=mtcars, colour=cyl)

本地浏览器查看

这样,我们可以在浏览器打开 http://localhost:4321 即可查看图片。

Sublime 集成快捷键

// 使用 Rmote 功能,实现远程服务器图片在本地浏览
  { "keys": ["f8"],
    "caption": "SublimeREPL: Rmote166",
    "command":"repl_open","args":
    {
        "type": "subprocess",
        "external_id": "r",
        "additional_scopes": ["tex.latex.knitr"],
        "encoding": 
        {
            "windows": "$win_cmd_encoding",
            "linux": "utf8",
            "osx": "utf8"
        },
        "soft_quit": "\nquit(save=\"no\")\n",
        "cmd": {"linux": 
                    [
                        "ssh",
                        "-L", "4321:localhost:4321", "fl@192.168.1.166", "-p22",
                        "R","--interactive", "--no-readline"
                    ]
                },
        "cwd": "$file_path",
        "extend_env": 
        {
            "osx": {"PATH": "{PATH}:/usr/local/bin"},
            "linux": {"PATH": "{PATH}:/usr/local/bin"},
            "windows": {}
        },
        "cmd_postfix": "\n",
        "suppress_echo": 
        {
            "osx": true,
            "linux": true,
            "windows": false
        },
        "syntax": "Packages/R/R Console.tmLanguage"
    }
  },
Rmote+Chrome

Rmote+Chrome

问题

提示:

- not sending to rmote because another graphics device has been opened...
- sending to the open graphics device instead...
- to send to rmote, close all active graphics devices using graphics.off()

说明已经有图片打开,需要关闭后即可

graphics.off()