skip to Main Content

I’m currently working on building a distroless R image (though I’m not versed in R)

I’m currently pulling deb packages from https://cloud.r-project.org/bin/linux/debian/buster-cran35/ for amd64 architecture.

I’m able to run R interactively from the image created, however, some of the core libraries are not loaded correctly, and the information on the failure cause in the terminal are scarce.

Below is the output of running the following command: R --verbose

'verbose' and 'quietly' are both true; being verbose then ..
now dyn.load("/usr/lib/R/library/methods/libs/methods.so") ...

R version 3.6.2 (2019-12-12) -- "Dark and Stormy Night"
Copyright (C) 2019 The R Foundation for Statistical Computing
Platform: x86_64-pc-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.

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.

'verbose' and 'quietly' are both true; being verbose then ..
'verbose' and 'quietly' are both true; being verbose then ..
now dyn.load("/usr/lib/R/library/utils/libs/utils.so") ...
Garbage collection 1 = 0+0+1 (level 2) ...
12.0 Mbytes of cons cells used (35%)
3.1 Mbytes of vectors used (5%)
Error: package or namespace load failed for 'utils':
 .onLoad failed in loadNamespace() for 'utils', details:
  call: system(paste(which, shQuote(names[i])), intern = TRUE, ignore.stderr = TRUE)
  error: error in running command
'verbose' and 'quietly' are both true; being verbose then ..
now dyn.load("/usr/lib/R/library/grDevices/libs/grDevices.so") ...
'verbose' and 'quietly' are both true; being verbose then ..
now dyn.load("/usr/lib/R/library/graphics/libs/graphics.so") ...
'verbose' and 'quietly' are both true; being verbose then ..
shared object ''utils.so'' already loaded
Error: package or namespace load failed for 'stats':
 .onLoad failed in loadNamespace() for 'utils', details:
  call: system(paste(which, shQuote(names[i])), intern = TRUE, ignore.stderr = TRUE)
  error: error in running command

All dependent libraries for utils.so are found by the ldd command.

Output for the command for ldd utils.so linkage:

/ # ldd /usr/lib/R/library/utils/libs/utils.so
    linux-vdso.so.1 (0x00007ffe772f9000)
    libR.so => /usr/lib/libR.so (0x00007f127acdf000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f127ab1e000)
    libblas.so.3 => /usr/lib/x86_64-linux-gnu/libblas.so.3 (0x00007f127aac3000)
    libgfortran.so.5 => /usr/lib/x86_64-linux-gnu/libgfortran.so.5 (0x00007f127a855000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f127a6d2000)
    libquadmath.so.0 => /usr/lib/x86_64-linux-gnu/libquadmath.so.0 (0x00007f127a690000)
    libreadline.so.7 => /lib/x86_64-linux-gnu/libreadline.so.7 (0x00007f127a441000)
    libpcre2-8.so.0 => /usr/lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007f127a3bc000)
    libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f127a348000)
    liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f127a320000)
    libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0 (0x00007f127a30d000)
    libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f127a0ef000)
    librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f127a0e3000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f127a0de000)
    libicuuc.so.63 => /usr/lib/x86_64-linux-gnu/libicuuc.so.63 (0x00007f1279f0f000)
    libicui18n.so.63 => /usr/lib/x86_64-linux-gnu/libicui18n.so.63 (0x00007f1279c34000)
    libgomp.so.1 => /usr/lib/x86_64-linux-gnu/libgomp.so.1 (0x00007f1279c03000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f1279be2000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f127b17f000)
    libopenblas.so.0 => /usr/lib/x86_64-linux-gnu/libopenblas.so.0 (0x00007f12779fc000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f12779e2000)
    libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f12779b4000)
    libicudata.so.63 => /usr/lib/x86_64-linux-gnu/libicudata.so.63 (0x00007f1275fc4000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f1275e40000)

What may I be missing here?

And what does "utils.so" already loadedmay indicate?

2

Answers


  1. You’re missing "which" I think.

    In this code chunk system(paste(which, shQuote(names[i])), intern = TRUE, ignore.stderr = TRUE), which is an object from Sys.which and its value is the string "/usr/bin/which".

    You should try installing which.

    Login or Signup to reply.
  2. UGH! I finally figured out how to work around this stupid problem!
    And GEE, thanks AWS Lambda team for not including the unix (GNU) primitive "/usr/bin/which" tool in your basic "Amazon linux 2" runtime – ARGH!

    So, besides figuring out how to include a version of ‘which’, the problem actually runs a bit deeper! You actually have to rebuild R with where the ‘which’ binary is located! This is because R uses system() and wants the full path to the ‘which’ command.

    In normal scenarios, ./configure figures out where ‘which’ is located and then embeds that path wherever ‘@WHICH@’ is located within the build system (turns out that’s src/library/base/R/unix/system.unix.R). Under EC2’s basic Amazon Linux 2 AMI, this happens to be where most unix systems would expect it: /usr/bin/which.

    However, being that AWS Lambda’s "Amazon linux 2" runtime is pre-built and doesn’t include ‘which’ – you can’t just go and install ‘which’ into /usr/bin. You have to layer it in somewhere under /opt, like perhaps in bin/ which puts it under /opt/bin; or where I’ve actually put it which is along with R in R/bin. Did I mention: ARGH?

    So, here’s what you have to do to get this to work:

    1. Copy /usr/bin/which to /opt/R/bin/which (assuming your going to layer it in with R). Basicaly, cp /usr/bin/which /opt/R/bin. Note, you really need to do this step first (well, right after you’ve untarred your R source and moved/renamed it to /opt/R).
    2. Now you run ./configure, however, with the modification of first defining an environment variable for WHICH to configure. Eg:
    WHICH=/opt/R/bin/which ./configure --prefix=/opt/R/ --exec-prefix=/opt/R/ --with-libpth-prefix=/opt/ --without-recommended-packages --without-x
    

    This overrides configure from searching for ‘which’ and defining ‘which’ as wherever it was found on the build system.

    1. After you’ve made sure you’ve put ‘which’ in the directory you told ./configure about, then run make. Because you told configure a different location, it needs to exist during the build because the ‘which’ it knows about is also actually used during the build. If it’s not found during build, then you’ll have other weird issues when you go to run R.

    2. Add any missing system libraries into /opt/R/lib. Eg, For AWS Lambda ‘Amazon linux 2’ runtime, you will need to add: libgfortran.so.4, libquadmath.so.0, libpcre2-8.so.0, libgomp.so.1

    3. Add in some basic "required" packages for running a reasonable bootstrap:

    ./bin/Rscript -e 'chooseCRANmirror(graphics=FALSE, ind=34); install.packages(c("jsonlite","httr","logging"))'
    
    1. Package your whole kit-n-kaboodle up and install as the first layer:
    (cd /opt; zip -qr ~/R-runtime.zip R/bin/ R/lib/ R/etc R/library/ R/modules/)
    

    Voilà! You should now have a R layer that will actually function!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search