R Advent Calendar 2021 の7日目の記事です。
Rのパッケージをインストールできないのは、 /tmp にマウントした tmpfs が noexec なのが原因だった、という話です。エラーメッセージからは原因が分かりにくいので、状況を再現しました。
実行環境
Dockerイメージを、以下の Dockerfile ファイルから作成します。あえて rocker/tidyverse を使っていません。本文書の実行環境は、 Windows 10 + WSL2 + R 3.6.3 です。
FROM ubuntu:focal
ENV TZ=Asia/Tokyo
RUN apt-get update && apt-get install -y tzdata
RUN apt-get install -y r-base
RUN apt-get install -y wget gdebi-core
RUN wget https://download2.rstudio.org/server/bionic/amd64/rstudio-server-2021.09.1-372-amd64.deb
RUN gdebi --non-interactive rstudio-server-2021.09.1-372-amd64.deb
RUN apt-get install -y libssl-dev libcurl4-openssl-dev libxml2-dev
RUN R -e 'install.packages("remotes")'
RUN Rscript -e 'remotes::install_version("devtools")'
RUN adduser --disabled-password --gecos "" rstudio
RUN echo "rstudio:rstudio" | chpasswd
CMD rstudio-server start && tail -f < /dev/null
docker-compose.yml を以下のように書きます。最初は /tmp の tmpfs を exec にしておきます。
version: '3'
services:
installation_failed:
build: .
image: installation_failed
ports:
- 8787:8787
tmpfs:
- /tmp:exec
volumes:
- .:/home/rstudio/work
この Docker イメージをビルドして起動すると(必要なら sudo をつけてください)、 http://example.com:8787/ の RStudio Server にログインできます。ホスト名は localhost などに適宜読み替えてください。先の Dockerfile に書いた通り、ユーザとパスワードは rstudio です。
docker-compose -f docker-compose.yml build
docker-compose -f docker-compose.yml up -d
tmpfs が exec のとき
data.table パッケージをインストールしましょう。 HTTP proxy などに止められなければ、無事インストールできるはずです。
install.packages("data.table")
library(data.table)
pkgbuild を使って、パッケージをビルドできるかどうか調べます。ビルドできますね。
pkgbuild::check_build_tools(debug = TRUE)
## Your system is ready to build packages!
pkgbuild::check_compiler(debug = TRUE)
## Trying to compile a simple C file
## Running /usr/lib/R/bin/R CMD SHLIB foo.c
## gcc -std=gnu99 -I"/usr/share/R/include" -DNDEBUG -fpic -g -O2 -fdebug-prefix-map=/build/r-base-jbaK_j/r-base-3.6.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c foo.c -o foo.o
## gcc -std=gnu99 -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o foo.so foo.o -L/usr/lib/R/lib -lR
## [1] TRUE
tmpfs が noexec のとき
先ほどの docker-compose.yml の、 /tmp:exec を /tmp:noexec に変えます。これを docker-compose-noexec.yml として保存して、
version: '3'
services:
installation_failed:
build: .
image: installation_failed
ports:
- 8787:8787
tmpfs:
- /tmp:noexec
volumes:
- .:/home/rstudio/work
先ほどと同じ Docker イメージを docker-compose-noexec.yml で起動します(必要なら sudo をつけて実行してください)。
docker-compose -f docker-compose.yml down
docker-compose -f docker-compose-noexec.yml up -d
pkgbuild を使って、パッケージをビルドできるかどうか調べます。ビルドツールはありますが、コンパイルはできないようです。
pkgbuild::check_build_tools(debug = TRUE)
## Your system is ready to build packages!
pkgbuild::check_compiler(debug = TRUE)
## Trying to compile a simple C file
## Running /usr/lib/R/bin/R CMD SHLIB foo.c
## gcc -std=gnu99 -I"/usr/share/R/include" -DNDEBUG -fpic -g -O2 -fdebug-prefix-map=/build/r-base-jbaK_j/r-base-3.6.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c foo.c -o foo.o
## gcc -std=gnu99 -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o foo.so foo.o -L/usr/lib/R/lib -lR
## Error: Failed to compile C code
data.table パッケージをインストールしましょう。 configure が実行可能でない、と言われてインストールに失敗します。
install.packages("data.table")
## Installing package into '/home/rstudio/R/x86_64-pc-linux-gnu-library/3.6'
## (as 'lib' is unspecified)
## trying URL 'https://cloud.r-project.org/src/contrib/data.table_1.14.2.tar.gz'
## Content type 'application/x-gzip' length 5301817 bytes (5.1 MB)
## ==================================================
## downloaded 5.1 MB
##
## * installing *source* package 'data.table' ...
## ** package 'data.table' successfully unpacked and MD5 sums checked
## ** using staged installation
## ERROR: 'configure' exists but is not executable -- see the 'R Installation and Administration Manual'
## * removing '/home/rstudio/R/x86_64-pc-linux-gnu-library/3.6/data.table'
## Warning in install.packages :
## installation of package 'data.table' had non-zero exit status
##
## The downloaded source packages are in
## '/tmp/RtmpatoM4r/downloaded_packages'
エラーメッセージから /tmp で data.table パッケージをビルドしようとして失敗したことが分かります。しかしこのエラーメッセージだと、原因が分かりにくいですね。実際にこのようなやり取りが GitHub の Issues でありました。
/tmp が noexec かどうかは、 findmnt コマンドで確認できます。
findmnt /tmp
## TARGET SOURCE FSTYPE OPTIONS
## /tmp tmpfs tmpfs rw,nosuid,nodev,noexec,relatime
自作したRパッケージをインストールする
自作したRパッケージが依存する、外部のRパッケージは、 DESCRIPTION ファイルの Imports: に書きます。ここに data.table があると、やはりパッケージのビルドでエラーになります。
tmpfs が exec のとき
-
install.packages("data.table")
で data.table をインストールします - RStudio の Build タブを開きます
- Check を押してパッケージを検査すると、最後まで実行されて結果が出ます
- Install and Restart を押してインストールする処理も上手くいきます
tmpfs が noexec のとき
-
install.packages("data.table")
は失敗するので、結果を無視します - RStudio の Build タブを開きます
- RStudio の Build タブを開き、 Check を押してパッケージを検査すると、以下のメッセージが出ます
==> devtools::check(document = FALSE)
-- Building ------------------------------- installationfailedsample --
Setting env vars:
* CFLAGS : -Wall -pedantic
* CXXFLAGS : -Wall -pedantic
* CXX11FLAGS: -Wall -pedantic
-----------------------------------------------------------------------
v checking for file '/home/rstudio/work/sample/DESCRIPTION' ...
- preparing 'installationfailedsample':
v checking DESCRIPTION meta-information ... OK
- checking for LF line-endings in source and make files and shell scripts
- checking for empty or unneeded directories
- building 'installationfailedsample_0.1.0.tar.gz'
-- Checking ------------------------------- installationfailedsample --
Setting env vars:
* _R_CHECK_CRAN_INCOMING_REMOTE_: FALSE
* _R_CHECK_CRAN_INCOMING_ : FALSE
* _R_CHECK_FORCE_SUGGESTS_ : FALSE
* NOT_CRAN : true
Error: Could not find tools necessary to compile a package
Call `pkgbuild::check_build_tools(debug = TRUE)` to diagnose the problem.
Execution halted
Exited with status 1.
"Could not find tools necessary to compile a package" というエラーメッセージから、 tmpfs が原因であることを突き止めるのは大変です。gcc と g++ はインストールされているので、 pkgbuild::check_build_tools(debug = TRUE)
は正常終了します。そういう理由からこの記事を書きました。
サンプルコード
コード一式を GitHub に置きました。お役に立てれば幸いです。