前言

这学期学的《概率论与数理统计》课有作业需要用到R,加上双十一从腾讯云搞了一台2H4G8M的机器,性能大大提升,因此打算打造一个云服务来运行Python,同时兼顾R。

在安装的过程中碰到了超级多的问题,所以下面介绍一下安装的流程,记录一些很久才解决的问题。

系统信息
OS: Ubuntu 20.04
Python: 3.8.10

方案

目前常用的方式是Anaconda+R(使用apt安装),而Anaconda会安装很多不必要的包,而在服务器(无图形界面)使用apt安装的R中的画图功能需要安装X11的相关环境,还不一定能搞定,所以最终采用的方案如下:

1
2
3
4
5
6
7
8
./
├─pycal Python虚拟环境
├─rsource R安装包的源代码
├─rcal 自定义安装的R
├─project 项目文件夹
│ ├─R R项目
│ └─Python Python项目
└─requirements.txt Python需要的包

安装

Python相关环境

安装虚拟环境

1
2
3
python -m venv pycal
source pycal/bin/activate
pip install -r requirements.txt

Jupyter初步配置

  1. 生成配置文件
1
jupyter lab --generate-config

如果是root用户,可以在后面添加--allow-root,完成后会返回配置文件位置。

ValueError: Can not patch loop of type <class 'NoneType'>
这是由于nest_asyncio的bug导致的,将其版本回退为1.5.1即可解决。[3]

1
2
pip uninstall nest_asyncio
pip install nest_asyncio==1.5.1
  1. 生成密码
1
2
3
4
5
6
7
8
9
(pycal) ~/calhub ❯❯❯ ipython
Python 3.8.10 (default, Sep 28 2021, 16:10:42)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.30.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from notebook.auth import passwd

In [2]: passwd("password", 'sha1')
Out[2]: 'sha1:c3354c486202:4ddc858c5be0eef7b78547c6210c0d65df1023e9'
  1. 修改配置

修改配置文件,路径在2.1中给出,一般为~/.jupyter/jupyter_lab_config.py;在这一步后可以启动jupyter lab,访问http://[ip]:port进行预览。

1
2
3
4
5
c.ServerApp.ip = '0.0.0.0'
c.ServerApp.open_browser = False
c.ServerApp.password = u'sha1:c3354c486202:4ddc858c5be0eef7b78547c6210c0d65df1023e9' # 2.2中得到的加密密码
c.ServerApp.port = 8080 # 自定义端口
c.ServerApp.root_dir = '~/calhub/project' # 自定义工作目录

注意要在服务器的管理面板放行相关端口。

R相关环境

下载

为了避免X11的配置问题,采用编译安装R的方式。从CRAN下载源代码(推荐清华镜像源),将其解压:

1
2
3
wget https://mirrors.tuna.tsinghua.edu.cn/CRAN/src/base/R-4/R-4.1.2.tar.gz
tar -zxvf R-4.1.2.tar.gz
mv R-4.1.2 rsource && cd rsource

安装前配置

有问题,多看手册:R Installation and Administration

在安装之前,我们需要先通过rsource目录下的configure文件生成安装的配置文件,在安装中我们需要指定Cairo代替X11环境(--with-x=no--with-cairo),同时指定相应的图片格式(如--with-libpng代表png格式),还可以指定R的安装位置(--prefix=your path)。运行[1]

1
./configure --prefix=~/calhub/rcal --with-libpng --with-jpeglib --with-libtiff --with-x=no --with-cairo

在这一步骤前,请先确认服务器上安装有以下包:libcairo2-devlibjpeg-devlibtiff-devlibpng-dev

configure: error: No Fortran compiler found
直接安装Fortran的编译器即可,如sudo apt install gfortran

configure: error: –with-readline=yes (default) and headers/libs are not available
安装readlinesudo apt install libreadline6-dev

configure: WARNING: you cannot build info or HTML versions of the R manuals
这个问题是无法获取R手册的html版本,通过sudo apt install texinfo解决。

安装

1
2
3
make
make check
make install

安装后配置

  1. 确认正常

进入R环境(可以将~/calhub/rcal/bin加入环境变量),查看cairo是否启用,各类图片是否支持。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(pycal) ~/calhub ❯❯❯ ./rcal/bin/R
R version 4.1.2 (2021-11-01) -- "Bird Hippie"
...
Type 'q()' to quit R.

> capabilities()
jpeg png tiff tcltk X11 aqua
TRUE TRUE TRUE FALSE FALSE FALSE
http/ftp sockets libxml fifo cledit iconv
TRUE TRUE TRUE TRUE TRUE TRUE
NLS Rprof profmem cairo ICU long.double
TRUE TRUE FALSE TRUE TRUE TRUE
libcurl
TRUE
  1. 配置~/.Rprofile

.Rprofile文件是R的开始配置文件(Startup Configuration),一般情况下在用户目录下建立该文件即可,也可以在工作目录或者R的安装目录编写[2]。通过该文件,我们指定图片默认使用cairo,安装默认使用清华镜像源。

1
2
3
4
5
## Set default 'type' for png() calls - useful when X11 device is not available!
## NOTE: Needs 'cairo' capability
options(bitmapType='cairo')
options("repos" = c(CRAN="https://mirrors.tuna.tsinghua.edu.cn/CRAN/"))
cat("\nWelcome at", date(), "\n")
  1. 安装Cairo

安装Cairo,并查看是否支持各类图片格式。(未尝试过不安装是否可以)

1
2
3
4
5
6
> install.packages("Cairo")
...
> library("Cairo")
> Cairo.capabilities()
png jpeg tiff pdf svg ps x11 win raster
TRUE TRUE TRUE TRUE TRUE TRUE TRUE FALSE TRUE

ERROR: configuration failed for package ''Cairo'
服务器没有安装cairo的包,通过sudo apt install libcairo2-dev解决。

fatal error: X11/Intrinsic.h: No such file or directory
这个包是在编译安装cairo过程中需要用到的,通过sudo apt install libxt-dev解决。[4]

Jupyter配置

添加R kernel

  1. 安装依赖包
1
> install.packages(c('repr', 'IRdisplay', 'evaluate', 'crayon', 'pbdZMQ', 'devtools', 'uuid', 'digest'))

installation of package 'devtools'/'gert'/'phangorn' had non-zero exit status
通过单独安装某个包(例如install.packages("devtools"))的方式,可以获取报错,发现都是因为git2导致的,通过sudo apt install libgit2-dev解决。[5]

  1. 安装kernel
1
> devtools::install_github('IRkernel/IRkernel')

这一步对网络的要求比较高,可以设置代理进行。

Error in loadNamespace(i, c(lib.loc, .libPaths()), versionCheck = vI[[i]]) : 载入了名字空间'rlang' 0.2.2,但需要的是>= 0.3.0
先卸载rlang包,再重新安装:

1
2
3
4
> remove.packages(c('rlang'), lib=file.path('包所在位置')) 
# 或
> remove.packages('rlang')
> install.packages('rlang')
  1. 添加kernel
1
2
3
4
# 给自己安装
> IRkernel::installspec()
# 给系统安装
> IRkernel::installspec(user = FALSE)

输出会给出kernel路径,如Installed kernelspec ir in ~/.local/share/jupyter/kernels/ir

Nginx配置

在完成上述步骤后,可以通过http://ip:port的方式进行访问,如果需要绑定域名,我们还需要对Nginx进行配置,主要是实现WebSocker转发。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
location /
{
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;

# 持久化连接相关配置实现wss转发
proxy_connect_timeout 30s;
proxy_read_timeout 86400s;
proxy_send_timeout 30s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;

add_header X-Cache $upstream_cache_status;

#Set Nginx Cache
add_header Cache-Control no-cache;

}

服务与插件

服务设置

为了使Jupyter在后台长期运行,可以选择使用nohup,或者使用类似于tmux的应用,也可以选择创建系统服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
## /usr/lib/systemd/system/jupyter.service
[Unit]
Description=Jupyter Lab

[Service]
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/calhub
ExecStart=/home/ubuntu/calhub/pycal/bin/jupyter lab

Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

随后运行sudo systemctl daemon-reload重载以下,后面就可以通过以下命令控制Jupyter:

1
2
3
4
sudo systemctl start jupyter    # 启动
sudo systemctl enable jupyter # 设置开机自启
sudo systemctl status jupyter # 查看状态
sudo journalctl -u jupyter # 查看日志

插件安装

Jupyter Lab拥有众多的插件,在左侧的Extension Manager中可以对插件进行管理。目前安装了两个较为需要的插件。

lsp

Coding assistance for JupyterLab (code navigation + hover suggestions + linters + autocompletion + rename) using Language Server Protocol

  1. 首先安装插件本体:
1
pip install 'jupyterlab>=3.0.0,<4.0.0a0' jupyterlab-lsp
  1. 根据需要安装LSP language server,例如我需要Python以及R语言:
1
2
pip install 'python-lsp-server[all]'
R -e 'install.packages("languageserver")'
  1. 重启Jupyter Lab服务

system-monitor

  1. 安装插件本体:
1
pip install jupyterlab-system-monitor
  1. 修改Jupyter配置~/.jupyter/jupyter_lab_config.py
1
2
3
4
5
6
# memory
c.ResourceUseDisplay.mem_limit = <size_in_GB> *1024*1024*1024

# cpu
c.ResourceUseDisplay.track_cpu_percent = True
c.ResourceUseDisplay.cpu_limit = <number_of_cpus>
  1. 修改插件配置:在Settings中选择Advanced Settings Editor,找到System Monitor,在右侧写入自己的配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
// CPU Settings
// Settings for the CPU indicator
"cpu": {
"label": "CPU Usage: "
},

// Memory Settings
// Settings for the memory indicator
"memory": {
"label": "Memory Usage: "
},

// Refresh Rate (ms)
// Refresh Rate to sync metrics data
"refreshRate": 1000
}

附录

演示


requirements内容

1
2
3
4
5
6
7
numpy
pandas
matplotlib
tables
astropy
handcalcs
jupyterlab

保存文件失败

  1. 防火墙设置

宝塔的专业版防火墙和免费Nginx防火墙都有POST最大参数限制,查看错误日志(如/www/wwwlogs/free_waf_log/)发现有参数值长度超过20w已被系统拦截的字样,则说明防火墙出现问题,修改/www/server/free_waf/init.lua中的200000为更大的数字即可。

  1. websocket问题

可参考官方推荐配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

server {
listen 80;
server_name jupyter.somewhere.cool;

location / {
proxy_pass http://localhost:9999;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
  1. 权限问题

请确认运行jupyter lab的用户拥有.ipynb文件的读写权限。

参考资料

  1. 【上云第1期】访问云上的 jupyter 环境(保姆级搭建教程)
  2. Linux环境下R语言安装笔记
  3. jupyter中加入R语言kernel操作指南

  1. Compile R with Cairo support without X11 ↩︎

  2. startup: Friendly R Startup Configuration ↩︎

  3. Can not launch notebook after nest_asyncio upgraded to 1.5.2 ↩︎

  4. 【解决】fatal error: X11/XXXX.h: No such file or directory ↩︎

  5. Ubuntu, how to deal the error “<stdin>:1:10: fatal error: git2.h: No such file or directory”? ↩︎