我从源代码编译了 R,但没有找到证书
I compiled R from source and it doesn't find certificates
我正在多个虚拟桌面上部署多个 R 版本。我从 Ubuntu 18.04.3 LTS
上的源代码构建了 3.6.3
和 4.1.2
R。其中 None 在 /etc/R
中找到系统范围的 Rprofile.site
文件或在 /usr/share/ca-certificates
中找到系统证书。但是安装了APT的R(3.4.4
)就没有这样的问题。我使用了 Ansible,但为了这个问题,我使用 shell 脚本为一台主机复制了部署。
#!/bin/bash
set -euo pipefail
# install build dependecies
(command -v apt && apt-get build-dep r-base) || (command -v dnf && dnf builddep R)
version='4.1.2'
major_version=$(echo "$version" | cut -c 1)
wget "https://cran.rstudio.com/src/base/R-$major_version/R-$version.tar.gz"
tar -xzf R-$version.tar.gz
cd R-$version
./configure \
--prefix=/opt/R/$version \
--sysconfdir=/etc/R \
--enable-R-shlib \
--with-pcre1 \
--with-blas \
--with-lapack
make -j 8
make install
注意:它应该 运行 在大多数 Linux 带有 APT 或 RPM 包管理器的发行版上。增加make
的-j
参数,如果你有足够的核心,但没有时间。
所以我将安装前缀定义为 /opt/R/$version
,但我希望它从 /etc/R
(定义为 --sysconfdir=/etc/R
)读取配置文件。但是,当我打开 R 交互式 shell (/opt/R/4.1.2/bin/R
) 尝试安装包时:
install.packages("remotes")
然后会提示我选择一个R包镜像,但是已经定义在/etc/R/Rprofile.site
:
local({
r <- getOption("repos")
r["CRAN"] <- "https://cloud.r-project.org"
options(repos = r)
})
我可以通过使用 R_PROFILE
环境变量定义它来强制 R shell 找到 Rprofile.site
文件。
export R_PROFILE=/etc/R/Rprofile.site
/opt/R/4.1.2/bin/R
然后在 R shell 中再次调用 install.packages("remotes")
。现在不会出现镜像选择提示,而是报如下错误:
Warning: unable to access index for repository https://cloud.r-project.org/src/contrib:
cannot open URL 'https://cloud.r-project.org/src/contrib/PACKAGES'
Warning message:
package ‘remotes’ is not available for this version of R
A version of this package for your version of R might be available elsewhere,
see the ideas at
https://cran.r-project.org/doc/manuals/r-patched/R-admin.html#Installing-packages
所以它无法访问存储库索引(真正的问题),然后得出结论,“remotes”包不适用于我的 R 版本。这是 BS,因为它一开始无法读取索引。所以我在同一个 R shell.
中尝试了一个简单的 HTTP 调用
curlGetHeaders("https://example.com")
并收到此错误:
Error in curlGetHeaders("https://example.com") : libcurl error code 77:
unable to access SSL/TLS CA certificates
因此无法在 /usr/share/ca-certificates
中找到 CA 证书。
由于APT安装的R有none个这样的问题。编译后的 R 不会搜索正确的位置。即使我省略 --sysconfdir=/etc/R
构建选项并复制或符号链接前缀下的 /etc/R
目录,它也会位于 /opt/R/4.1.2/etc
。它仍然找不到它的配置文件。
更大的问题是我什至不知道如何指定/usr/share
所以它可能会找到证书。 rsharedir
构建选项(makefile 中也缺少 --
)将不起作用,因为它应该指向 /usr/share/R/
而不是 /usr/share
,无论如何这都是一个不好的做法。
我也用 3.6.3
R 版本尝试了所有这些并得到了相同的结果。
问题:如何使编译后的 R 安装找到系统范围或任何配置文件和证书。
更新 1
我 运行 Ubuntu 服务器上的构建脚本,我不使用相同的 Ansible 代码进行管理。在他们两个上,R 成功地找到了证书。所以问题不在于构建脚本,而在于系统状态。
更新 2
我创建了一个安装包的简单 R 脚本 (install-r-package.R
):
install.packages("renv", repos="https://cran.wu.ac.at/")
然后我用 Rscript
执行它并跟踪它们在正确和错误的主机上打开了哪个文件:
strace -o strace.log -e trace=open,openat,close,read,write,connect,accept ./Rscript install-r-package.R
事实证明,在有问题的系统上,R 甚至没有尝试打开证书文件。
正确系统上的相关跟踪片段:
connect(5, {sa_family=AF_INET, sin_port=htons(443), sin_addr=inet_addr("137.208.57.37")}, 16) = -1 EINPROGRESS (Operation now in progress)
openat(AT_FDCWD, "/etc/ssl/certs/ca-certificates.crt", O_RDONLY) = 6
read(6, "-----BEGIN CERTIFICATE-----\nMIIH"..., 200704) = 200704
read(6, "--\n", 4096) = 3
read(6, "", 4096) = 0
close(6) = 0
在有问题的系统上:
connect(5, {sa_family=AF_INET, sin_port=htons(443), sin_addr=inet_addr("137.208.57.37")}, 16) = -1 EINPROGRESS (Operation now in progress)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/nss/libsoftokn3.so", O_RDONLY|O_CLOEXEC) = 6
read(6, "7ELF[=20=][=20=][=20=][=20=][=20=][=20=][=20=][=20=][=20=][=20=]>[=20=][=20=][=20=][=20=]0A[=20=][=20=][=20=][=20=][=20=][=20=]"..., 832) = 832
close(6) = 0
在这两种情况下,R 都会连接到镜像 (137.208.57.37
),然后在正确的系统上读取 ca-certificates.crt
证书文件和许多其他 .crt 文件。然而错误的系统完全跳过了这一步。
终于找到了解决办法:
因为两个系统都有arch和OS。我在它们之间交叉复制了 R 编译安装。在有问题的系统上编译但在正确系统上编译的 R 运行 在调用 install.packages("renv", repos="https://cran.wu.ac.at/")
后发出以下警告
Warning: unable to access index for repository https://cran.wu.ac.at/src/contrib:
internet routines cannot be loaded
Warning messages:
1: In download.file(url, destfile = f, quiet = TRUE) :
unable to load shared object '/opt/R/4.1.2/lib/R/modules//internet.so':
libcurl-nss.so.4: cannot open shared object file: No such file or directory
2: package ‘remotes’ is not available for this version of R
A version of this package for your version of R might be available elsewhere,
see the ideas at
https://cran.r-project.org/doc/manuals/r-patched/R-admin.html#Installing-packages
如果我反其道而行之,安装就会成功。
libcurl-nss.so.4: cannot open shared object file: No such file or directory
行给了我不同的 libcurl4 风格被用作构建依赖项的线索。我检查了系统上安装了哪些开发依赖项,libcurl4-nss-dev 7.58.0-2ubuntu3
安装在有问题的系统上,libcurl4-gnutls-dev 7.58.0-2ubuntu3.16
安装在正确的系统上。
所以我从有问题的系统中清除了 libcurl4-gnutls-dev
:
apt purge libcurl4-nss-dev -y
并安装了 libcurl4-gnutls-dev:
aptitude install libcurl4-gnutls-dev
我使用了 aptitude,因为我必须降级 libcurl3-gnutls 7.58.0-2ubuntu3.16 (now) -> 7.58.0-2ubuntu3 (bionic)
,它是 libcurl4-gnutls-dev
的依赖项,然后我 运行 在 R- 4.1.2 源码目录。最后,我重新运行问题中的构建脚本,得到了一个运行良好的 R,它可以读取证书,因此可以使用包镜像访问 HTTPS。
我正在多个虚拟桌面上部署多个 R 版本。我从 Ubuntu 18.04.3 LTS
上的源代码构建了 3.6.3
和 4.1.2
R。其中 None 在 /etc/R
中找到系统范围的 Rprofile.site
文件或在 /usr/share/ca-certificates
中找到系统证书。但是安装了APT的R(3.4.4
)就没有这样的问题。我使用了 Ansible,但为了这个问题,我使用 shell 脚本为一台主机复制了部署。
#!/bin/bash
set -euo pipefail
# install build dependecies
(command -v apt && apt-get build-dep r-base) || (command -v dnf && dnf builddep R)
version='4.1.2'
major_version=$(echo "$version" | cut -c 1)
wget "https://cran.rstudio.com/src/base/R-$major_version/R-$version.tar.gz"
tar -xzf R-$version.tar.gz
cd R-$version
./configure \
--prefix=/opt/R/$version \
--sysconfdir=/etc/R \
--enable-R-shlib \
--with-pcre1 \
--with-blas \
--with-lapack
make -j 8
make install
注意:它应该 运行 在大多数 Linux 带有 APT 或 RPM 包管理器的发行版上。增加make
的-j
参数,如果你有足够的核心,但没有时间。
所以我将安装前缀定义为 /opt/R/$version
,但我希望它从 /etc/R
(定义为 --sysconfdir=/etc/R
)读取配置文件。但是,当我打开 R 交互式 shell (/opt/R/4.1.2/bin/R
) 尝试安装包时:
install.packages("remotes")
然后会提示我选择一个R包镜像,但是已经定义在/etc/R/Rprofile.site
:
local({
r <- getOption("repos")
r["CRAN"] <- "https://cloud.r-project.org"
options(repos = r)
})
我可以通过使用 R_PROFILE
环境变量定义它来强制 R shell 找到 Rprofile.site
文件。
export R_PROFILE=/etc/R/Rprofile.site
/opt/R/4.1.2/bin/R
然后在 R shell 中再次调用 install.packages("remotes")
。现在不会出现镜像选择提示,而是报如下错误:
Warning: unable to access index for repository https://cloud.r-project.org/src/contrib:
cannot open URL 'https://cloud.r-project.org/src/contrib/PACKAGES'
Warning message:
package ‘remotes’ is not available for this version of R
A version of this package for your version of R might be available elsewhere,
see the ideas at
https://cran.r-project.org/doc/manuals/r-patched/R-admin.html#Installing-packages
所以它无法访问存储库索引(真正的问题),然后得出结论,“remotes”包不适用于我的 R 版本。这是 BS,因为它一开始无法读取索引。所以我在同一个 R shell.
中尝试了一个简单的 HTTP 调用curlGetHeaders("https://example.com")
并收到此错误:
Error in curlGetHeaders("https://example.com") : libcurl error code 77:
unable to access SSL/TLS CA certificates
因此无法在 /usr/share/ca-certificates
中找到 CA 证书。
由于APT安装的R有none个这样的问题。编译后的 R 不会搜索正确的位置。即使我省略 --sysconfdir=/etc/R
构建选项并复制或符号链接前缀下的 /etc/R
目录,它也会位于 /opt/R/4.1.2/etc
。它仍然找不到它的配置文件。
更大的问题是我什至不知道如何指定/usr/share
所以它可能会找到证书。 rsharedir
构建选项(makefile 中也缺少 --
)将不起作用,因为它应该指向 /usr/share/R/
而不是 /usr/share
,无论如何这都是一个不好的做法。
我也用 3.6.3
R 版本尝试了所有这些并得到了相同的结果。
问题:如何使编译后的 R 安装找到系统范围或任何配置文件和证书。
更新 1
我 运行 Ubuntu 服务器上的构建脚本,我不使用相同的 Ansible 代码进行管理。在他们两个上,R 成功地找到了证书。所以问题不在于构建脚本,而在于系统状态。
更新 2
我创建了一个安装包的简单 R 脚本 (install-r-package.R
):
install.packages("renv", repos="https://cran.wu.ac.at/")
然后我用 Rscript
执行它并跟踪它们在正确和错误的主机上打开了哪个文件:
strace -o strace.log -e trace=open,openat,close,read,write,connect,accept ./Rscript install-r-package.R
事实证明,在有问题的系统上,R 甚至没有尝试打开证书文件。
正确系统上的相关跟踪片段:
connect(5, {sa_family=AF_INET, sin_port=htons(443), sin_addr=inet_addr("137.208.57.37")}, 16) = -1 EINPROGRESS (Operation now in progress)
openat(AT_FDCWD, "/etc/ssl/certs/ca-certificates.crt", O_RDONLY) = 6
read(6, "-----BEGIN CERTIFICATE-----\nMIIH"..., 200704) = 200704
read(6, "--\n", 4096) = 3
read(6, "", 4096) = 0
close(6) = 0
在有问题的系统上:
connect(5, {sa_family=AF_INET, sin_port=htons(443), sin_addr=inet_addr("137.208.57.37")}, 16) = -1 EINPROGRESS (Operation now in progress)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/nss/libsoftokn3.so", O_RDONLY|O_CLOEXEC) = 6
read(6, "7ELF[=20=][=20=][=20=][=20=][=20=][=20=][=20=][=20=][=20=][=20=]>[=20=][=20=][=20=][=20=]0A[=20=][=20=][=20=][=20=][=20=][=20=]"..., 832) = 832
close(6) = 0
在这两种情况下,R 都会连接到镜像 (137.208.57.37
),然后在正确的系统上读取 ca-certificates.crt
证书文件和许多其他 .crt 文件。然而错误的系统完全跳过了这一步。
终于找到了解决办法:
因为两个系统都有arch和OS。我在它们之间交叉复制了 R 编译安装。在有问题的系统上编译但在正确系统上编译的 R 运行 在调用 install.packages("renv", repos="https://cran.wu.ac.at/")
Warning: unable to access index for repository https://cran.wu.ac.at/src/contrib:
internet routines cannot be loaded
Warning messages:
1: In download.file(url, destfile = f, quiet = TRUE) :
unable to load shared object '/opt/R/4.1.2/lib/R/modules//internet.so':
libcurl-nss.so.4: cannot open shared object file: No such file or directory
2: package ‘remotes’ is not available for this version of R
A version of this package for your version of R might be available elsewhere,
see the ideas at
https://cran.r-project.org/doc/manuals/r-patched/R-admin.html#Installing-packages
如果我反其道而行之,安装就会成功。
libcurl-nss.so.4: cannot open shared object file: No such file or directory
行给了我不同的 libcurl4 风格被用作构建依赖项的线索。我检查了系统上安装了哪些开发依赖项,libcurl4-nss-dev 7.58.0-2ubuntu3
安装在有问题的系统上,libcurl4-gnutls-dev 7.58.0-2ubuntu3.16
安装在正确的系统上。
所以我从有问题的系统中清除了 libcurl4-gnutls-dev
:
apt purge libcurl4-nss-dev -y
并安装了 libcurl4-gnutls-dev:
aptitude install libcurl4-gnutls-dev
我使用了 aptitude,因为我必须降级 libcurl3-gnutls 7.58.0-2ubuntu3.16 (now) -> 7.58.0-2ubuntu3 (bionic)
,它是 libcurl4-gnutls-dev
的依赖项,然后我 运行 在 R- 4.1.2 源码目录。最后,我重新运行问题中的构建脚本,得到了一个运行良好的 R,它可以读取证书,因此可以使用包镜像访问 HTTPS。