fail to access ~¶
Info
The post can date back to May 12, 2021
Z 在群里问道,他在服务器上提交 job 时,之前安装好的包不能使用。显然,很可能因为 .libPaths() 没有包含 $HOME 下的用户安装路径,但是他在登录结点上在 R 中运行 .libPaths(),一切正常。那么问题或许出在工作结点上,事实表明在该工作结点上采用以下任一种方式都能解决问题
- 在 R 中运行
.libPaths("/lustre/users/sXXXXXXXXX/R/x86_64-pc-linux-gnu-library/4.0") - 或者
export R_LIBS_USER=/lustre/users/sXXXXXXXXX/R/x86_64-pc-linux-gnu-library/4.0
Note
此处也看到一个类似的问题,但是原因不一样,在 R_LIBS_USER ignored by R 问题中,原因是 $HOME 不能正常展开。
但是此时并不是很理解,因为按理说不同结点都是共享的。后来研究了下 R 的启动机制,
On Unix versions of R there is also a file
R_HOME/etc/Renvironwhich is read very early in the start-up processing. It contains environment variables set by R in the configure process. Values in that file can be overridden in site or user environment files: do not changeR_HOME/etc/Renvironitself. Note that this is distinct fromR_HOME/etc/Renviron.site.
才知道 R_LIBS_USER 是定义在 Renviron 中,
R_LIBS_USER=${R_LIBS_USER-'~/R/x86_64-pc-linux-gnu-library/4.0'}
其中 ${A-B} 的语法是如果 A 没有设置,则令 B 为 A,注意其与 ${A:-B} 的区别。
这也难怪为什么直接在命令行中输入 echo $R_LIBS_USER 结果为空。
SSH 到该工作结点,发现其 prompt 并没有正确加载,直接出现 bash-4.2$,而一般会是 [sXXXXX@chpc-sandbox ~]$。
Note
其实 source .bashrc 后能显示 ~,但访问 ~ 仍然失败。另见 Terminal, Prompt changed to “-Bash-4.2” and colors lost
这样一个直接后果就是无法解析用户目录 ~,这大概也是为什么 R_LIBS_USER 在这个结点没有正常加载,因为上述系统配置文件 /opt/share/R/4.0.3/lib64/R/etc/Renviron 中使用了 ~,于是需要用不带 ~ 的全路径。不过 ~ 其实只是指向 /user/sXXXXX,发现这个文件夹没有正常被连接,所以要使用 /lustre/user/sXXXX. 或者说是没有挂载,因为在其它结点上有以下三条挂载记录,
$ df -h
storage03:/chpc-userhome 50T 4.4T 46T 9% /storage03/chpc-userhome
storage03:/chpc-optshare 10T 713G 9.4T 7% /storage03/chpc-optshare
storage01:/chpc-users 15T 6.2T 8.9T 42% /storage01/users
而该结点上没有。
为了验证上述想法,也手动进行 export R_LIBS_USER= 及 .libPaths(),
> .libPaths("/lustre/users/sXXXXXXXXX/R/x86_64-pc-linux-gnu-library/4.0")
> .libPaths()
[1] "/lustre/users/sXXXXXXXXX/R/x86_64-pc-linux-gnu-library/4.0"
[2] "/lustre/opt_share/R/4.0.3/lib64/R/library"
$ export R_LIBS_USER=/lustre/users/sXXXXXXXXX/R/x86_64-pc-linux-gnu-library/4.0
$ R
> .libPaths()
[1] "/lustre/users/sXXXXXXXXX/R/x86_64-pc-linux-gnu-library/4.0"
[2] "/lustre/opt_share/R/4.0.3/lib64/R/library"
> .libPaths("/users/sXXXXXXXXX/R/x86_64-pc-linux-gnu-library/4.0/")
> .libPaths()
[1] "/lustre/opt_share/R/4.0.3/lib64/R/library"
$ export R_LIBS_USER=~/R/x86_64-pc-linux-gnu-library/4.0
$ R
> .libPaths()
[1] "/lustre/opt_share/R/4.0.3/lib64/R/library"
可见涉及 ~ 和 /users/sXXXX 的均有问题。
虽然问题已经得以解决,但是很好奇为什么访问 ~ 失败。因为根据我的理解,/users/sXXXX (~)、/lustre/users/sXXXX 中间应该是通过类似 soft links 形式连接的(即便可能不是,因为确实直接 ls 也没返回指向结果)。
后来咨询管理员才明白,他们正在将迁移用户文件夹,

其中黄色方块表明迁移的目标硬盘,称为 storage,而未框出来的地方则表明当前所在硬盘 lustre.
但是因为并非所有用户都已迁移完成,所以需要对这两类用户访问 ~ 的行为做不同的处理,

- 如果用户 A 已经迁移,则其
~直接指向/storage01/users/A - 如果用户 B 未迁移,则其
~通过/storage01/users/B(此时该路径只相当于 soft link) 指向/lustre/users/B
所以无论迁移与否,访问 ~ 都需要通过上图的黄色方框。那么倘若 storage 本身挂载失败,则 ~ 解析失败,而未迁移用户正因为还未迁移,所以仍能绕过 ~ 而直接访问 /lustre/users/sXXXX。