问题遭遇
今天升级了Linux系统的一堆底层运行时库,结果发现R包RProtoBuf
加载失败了,报出如下错误:
1
2
3
4
|
> library(RProtoBuf)
Error: package or namespace load failed for ‘RProtoBuf’ in dyn.load(file, DLLpath = DLLpath, ...):
unable to load shared object '/home/yanll/R/x86_64-pc-linux-gnu-library/3.6/RProtoBuf/libs/RProtoBuf.so':
libprotobuf.so.19: cannot open shared object file: No such file or directory
|
过去遇到这种问题时,我通常的解决方法,就是重新安装相应的R包,就可解决问题:
1
|
> install.package("RProtoBuf")
|
不过,有时候涉及很多包都受到影响,就需要逐个重新编译。但因为不知道到底有多少包需要重新安装,于是整个过程可能就需要手工进行多次尝试才能完全解决。
这个问题,并不能通过如下方式解决:
1
|
> BiocManager::install()
|
因为该命令只能根据R包之间的版本关系来进行更新,而并不能检查到“unable to load shared object”的错误。
问题解决
为此,我尝试了如下的bash命令,用来列举到底有哪些动态库(*.so
文件)出现了依赖问题,预期通过重新安装它们所属的R包即可:
1
2
3
4
5
6
7
8
9
10
11
12
|
$ Rscript -e 'cat(.libPaths(), sep = "\n")' \
| while read d; do \
( \
cd $d; \
find -type f -name '*.so' -executable \
| while read f; do \
if [ "$(ldd $f | grep "not found" | wc -l)" -gt 0 ]; then \
echo "$d/$f"; \
fi; \
done \
) \
done
|
如下命令,则将这些输出.so
文件所属包名(上级目录名)取出,用awk
构造了R语言的安装命令,提交给Rscript
进行安装:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
$ Rscript -e 'cat(.libPaths(), sep = "\n")' \
| while read d; do \
( \
cd $d; \
find -type f -name '*.so' -executable \
| while read f; do \
if [ "$(ldd $f | grep "not found" | wc -l)" -gt 0 ]; then \
echo $f; \
fi; \
done \
) \
done \
| cut -d/ -f2 \
| awk '{print"install.packages(\""$0"\")"}' \
| Rscript /dev/stdin
|
最终,问题得以解决。