.libPaths() ordering and immutable site library for staged package rollout
0 reputation · 22 May 2024, 04:49 UTC
0 reputation · 22 May 2024, 04:49 UTC
Migrating a small R application package without stopping existing sessions requires a clear library path boundary between the current and candidate package trees.
.libPaths() defines an ordered search list; library() loads from the first tree containing the package. A namespace is loaded once per session, so a running process continues to use the code it loaded. Installing into a shared tree risks new sessions seeing a partially installed package if the first entry is mutated in place.
Permission boundaries add uncertainty. Site libraries are often read-only for application users, while R_LIBS_USER can create a personal library that shadows a project or site tree. Startup configuration may be altered by .Rprofile.
What permission boundary ensures application users cannot write to the site library while a new tree remains discoverable? How should library order be enforced so R_LIBS_USER or .Rprofile does not shadow the intended new tree? Is the first .libPaths() entry expected to be immutable during rollout?
1. Permission boundary – The site library must be owned by a privileged group (e.g., root or a dedicated admin group) and have read‑only permissions (typically 0555). Application users run under a non‑privileged account that can read but not write to this tree. This guarantees that, even if R_LIBS_USER or a .Rprofile points to the site library, no write can occur.
2. Enforcing the intended order – Set the environment variable R_LIBS_SITE to the immutable site library path before any R process starts. This establishes the first entry of .libPaths() and is respected by all startup scripts. Then add the candidate tree as the new first entry:
# In a startup wrapper or a minimal .Rprofile placed in the app working directory
Sys.setenv(R_LIBS_SITE = "/opt/r/site") # immutable site library
Sys.setenv(R_LIBS_USER = "/opt/r/candidate") # candidate tree
.libPaths(c(Sys.getenv("R_LIBS_USER"), Sys.getenv("R_LIBS_SITE")))
Because R_LIBS_SITE is consulted before R_LIBS_USER, the candidate tree will always be searched first. A minimal .Rprofile that only sets .libPaths() ensures that no other startup script can reorder the search path.
3. Immutability of the first entry – The first entry (the site library) should be treated as immutable during the rollout. Mutating it in place risks exposing partially installed packages to new sessions. If the site library must be updated, do so in a separate, controlled step *after* the rollout is complete.
ls -ld /opt/r/site
# Expected output: dr-xr-xr-x ... /opt/r/site
cat(.libPaths())
# Expected: first element is /opt/r/candidate, second is /opt/r/site
library(myPackage, character.only = TRUE)
sessionInfo()$otherPkgs
# Confirm the path shown matches /opt/r/candidate
touch /opt/r/site/tmp.txt
# Should return Permission denied.
.libPaths() and optionally delete the directory to avoid ambiguity for future sessions..Rprofile that modifies .libPaths(), it can silently override the intended order. Sanitize or replace that file with the minimal script shown above..libPaths() order. Restart any long‑running workers after updating the environment.library() will fail with “cannot open shared object file” errors.If you have a different user group or a non‑standard site library location, let us know so we can adjust the permission and environment variable recommendations accordingly.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.