Instalações de executáveis binários pré-compilados ou bibliotecas
dinâmicas podem não ter as dependências bem resolvidas e quando
executados ou carregadas, respectivamente, podem retornar o erro
could not load library cannot open shared object file
. Em alguns
casos links simbólicos podem ser uma solução de contorno.
Não vou entrar em detalhes sobre shared library
, LD_LIBRARY_PATH
,
ld.so
e outras coisas, pois alguém com muita propriedade no assunto
já escreveu sobre isto. O que vou explicar aqui é como eu costumo
depurar este erro e uma das soluções de contorno que uso.
NOTA: não me responsabilizo por qualquer coisa estou comentando aqui, vocês conhecem os seus sistemas e os seus ambientes, inspirem-se e usem as informações aqui para o bem. Qualquer mau uso destas informações e dos utilitários sugeridos é por sua conta e risco.
O processo é simples, eu uso os utilitários ldd
ou objdump
, sendo
que este último é mais recomendado, visto que o ldd
executa o
programa passado como argumento, logo pode ser perigoso utilizá-los
com binários não-confiáveis.
Como estudo de caso vou usar um exemplo de uma extensão do PostgreSQL,
que é uma shared library
que depende de bibliotecas do Oracle
instaladas.
Ao criar a extensão no PostgreSQL ele tenta carregar a biblioteca, e logo eu vejo o erro:
guedes=# create extension oracle_fdw ;
ERROR: could not load library "/usr/lib/postgresql/10/lib/oracle_fdw.so": libclntsh.so.18.1: cannot open shared object file: Arquivo ou diretório não encontrado
Todas as dependências estavam instaladas, conforme:
➤ ls -la /usr/lib/oracle/12.2/client64/lib/
total 219708
drwxr-xr-x 2 root root 4096 abr 14 16:23 ./
drwxr-xr-x 4 root root 4096 abr 2 2018 ../
-rw-rwxr-- 1 root root 342 jan 26 2017 glogin.sql*
lrwxrwxrwx 1 root root 21 abr 2 2018 libclntshcore.so -> libclntshcore.so.12.1*
-rw-rwxr-- 1 root root 8033199 jan 26 2017 libclntshcore.so.12.1*
lrwxrwxrwx 1 root root 17 abr 2 2018 libclntsh.so -> libclntsh.so.12.1*
-rw-rwxr-- 1 root root 71638263 jan 26 2017 libclntsh.so.12.1*
-rw-rwxr-- 1 root root 2981501 jan 26 2017 libipc1.so*
-rw-rwxr-- 1 root root 539065 jan 26 2017 libmql1.so*
-rw-rwxr-- 1 root root 6568149 jan 26 2017 libnnz12.so*
lrwxrwxrwx 1 root root 15 abr 2 2018 libocci.so -> libocci.so.12.1*
-rw-rwxr-- 1 root root 2218687 jan 26 2017 libocci.so.12.1*
-rw-rwxr-- 1 root root 124771800 jan 26 2017 libociei.so*
-rw-rwxr-- 1 root root 158543 jan 26 2017 libocijdbc12.so*
-rw-rwxr-- 1 root root 380996 jan 26 2017 libons.so*
-rw-rwxr-- 1 root root 116563 jan 26 2017 liboramysql12.so*
-rw-rwxr-- 1 root root 1641005 jan 26 2017 libsqlplusic.so*
-rw-rwxr-- 1 root root 1559466 jan 26 2017 libsqlplus.so*
-rw-r--r-- 1 root root 3984814 jan 26 2017 ojdbc8.jar
-rw-rwxr-- 1 root root 312974 jan 26 2017 ottclasses.zip*
-rw-r--r-- 1 root root 37494 jan 26 2017 xstreams.jar
Porém a falta era da libclntsh.so.18.1
o que pode ser visto
inspecionando a lib da extensão que eu estou tentando carregar:
➤ ldd /usr/lib/postgresql/10/lib/oracle_fdw.so
linux-vdso.so.1 (0x00007fff8855d000)
libclntsh.so.18.1 => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcc9b58e000)
/lib64/ld-linux-x86-64.so.2 (0x00007fcc9bb50000)
Como eu tenho a libclntsh.so.12.1
, levantei a hipotese de criar um
link simbólico para ver se funcionava:
➤ cd /usr/lib/oracle/12.2/client64/lib/
➤ sudo ln -s libclntsh.so.12.1 libclntsh.so.18.1
Mesmo assim não funcionou:
➤ ldd /usr/lib/postgresql/10/lib/oracle_fdw.so
linux-vdso.so.1 (0x00007fff8855d000)
libclntsh.so.18.1 => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcc9b58e000)
/lib64/ld-linux-x86-64.so.2 (0x00007fcc9bb50000)
Mesmo conferindo o ld.so.conf
pela milésima vez, parecia tudo certo:
➤ cat /etc/ld.so.conf.d/oracle.conf
/usr/lib/oracle/12.2/client64/lib/
Pensei em ver as variáveis de ambiente do usuário em que o Postgres
estava executando e o truque aqui foi pegar o PID
do processo
principal e usar o /proc
para ver se tinha alguma LD_LIBRARY_PATH
específica.
➤ ps -ef | grep postgres
postgres 21571 1 0 abr12 ? 00:00:01 /usr/lib/postgresql/10/bin/postgres -D /var/lib/postgresql/10/pgml -c config_file=/etc/postgresql/10/pgml/postgresql.conf
postgres 21573 21571 0 abr12 ? 00:00:00 postgres: 10/pgml: checkpointer process
postgres 21574 21571 0 abr12 ? 00:00:00 postgres: 10/pgml: writer process
postgres 21575 21571 0 abr12 ? 00:00:00 postgres: 10/pgml: wal writer process
postgres 21576 21571 0 abr12 ? 00:00:00 postgres: 10/pgml: autovacuum launcher process
postgres 21577 21571 0 abr12 ? 00:00:00 postgres: 10/pgml: stats collector process
O número mágico aqui é 21571.
➤ sudo cat /proc/21571/environ | xargs -n 1 -0 echo
PG_OOM_ADJUST_FILE=/proc/self/oom_score_adj
PG_GRANDPARENT_PID=21565
PGLOCALEDIR=/usr/share/locale
PGSYSCONFDIR=/etc/postgresql-common
LANG=pt_BR.UTF-8
PWD=/
PGDATA=/var/lib/postgresql/10/pgml
Nada. Postgres utilizando o padrão. Sendo assim pensei e criar um link
simbólico lá no /usr/lib
:
➤ cd /usr/lib
➤ sudo ln -s /usr/lib/oracle/12.2/client64/lib/libclntsh.so.18.1
E dai sim funcionou:
➤ ldd /usr/lib/postgresql/10/lib/oracle_fdw.so
linux-vdso.so.1 (0x00007ffcb8fdd000)
libclntsh.so.18.1 => /usr/lib/libclntsh.so.18.1 (0x00007f555dbd8000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f555d839000)
libmql1.so => /usr/lib/oracle/12.2/client64/lib/libmql1.so (0x00007f555d5c2000)
libipc1.so => /usr/lib/oracle/12.2/client64/lib/libipc1.so (0x00007f555d18f000)
libnnz12.so => /usr/lib/oracle/12.2/client64/lib/libnnz12.so (0x00007f555ca46000)
libons.so => /usr/lib/oracle/12.2/client64/lib/libons.so (0x00007f555c7f8000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f555c5f4000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f555c2f0000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f555c0d3000)
libnsl.so.1 => /lib/x86_64-linux-gnu/libnsl.so.1 (0x00007f555bebb000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f555bcb3000)
libaio.so.1 => /lib/x86_64-linux-gnu/libaio.so.1 (0x00007f555bab1000)
libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f555b89a000)
/lib64/ld-linux-x86-64.so.2 (0x00007f55618a0000)
libclntshcore.so.12.1 => /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1 (0x00007f555b2cc000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f555b0b5000)
E a extensão criou normalmente:
guedes=# create extension oracle_fdw ;
CREATE EXTENSION
guedes=#
Bom, foi isto. “:)