드라이버나 라이브러리를 새로 깔았는데 실행 파일이 error while loading shared libraries: libXXX.so.1: cannot open shared object file 로 죽는다. 파일은 디스크에 분명히 있는데 실행기가 못 찾는다. nvidia-smi 나 cx_Oracle 처럼 공유 라이브러리에 의존하는 도구에서 자주 만난다.
동적 링커 ld.so 는 다음 순서로 찾는다.
먼저 실행 파일에 박힌 DT_RPATH · DT_RUNPATH 를 본다. 다음으로 환경변수 LD_LIBRARY_PATH 를 본다. 그다음 /etc/ld.so.cache 를 본다. 마지막으로 /lib64 · /usr/lib64 같은 기본 경로를 본다.
ldconfig 는 세 번째 단계의 캐시를 다시 만드는 명령이다. 새 경로를 등록하고 캐시를 갱신하면 모든 프로세스가 별도 환경변수 없이 그 라이브러리를 찾는다. PATH 를 고치는 것과는 다른 이야기인데, PATH 는 실행 파일 위치이고 이쪽은 라이브러리 위치다.
경로를 파일 하나로 등록한 뒤 캐시를 다시 만든다.
echo '/usr/local/nvidia/lib64' | sudo tee /etc/ld.so.conf.d/nvidia.conf
sudo ldconfig
/etc/ld.so.conf 는 보통 include ld.so.conf.d/*.conf 한 줄만 들고 있으므로, 직접 고치지 말고 ld.so.conf.d/ 에 파일을 하나 더 두는 것이 관리하기 좋다.
ldconfig 는 등록된 디렉터리를 훑어 libfoo.so.1 같은 SONAME 심볼릭 링크까지 다시 만들어 준다. 링크를 손으로 걸 필요가 없는 이유가 이것이다.
캐시에 들어갔는지 본다.
ldconfig -p | grep -i libcuda
ldconfig -p | wc -l
실행 파일이 실제로 무엇을 찾고 있는지 본다. not found 로 나오는 항목이 문제다.
ldd /usr/local/nvidia/bin/nvidia-smi
어느 경로를 뒤졌는지까지 보려면 링커의 디버그 출력을 켠다.
LD_DEBUG=libs nvidia-smi 2>&1 | head -40
건드리지 않고 갱신 결과만 미리 보려면 -v 와 -N·-X 조합을 쓴다.
sudo ldconfig -v -N -X | head
급할 때는 환경변수로 넘길 수 있다.
export LD_LIBRARY_PATH=/usr/local/nvidia/lib64:$LD_LIBRARY_PATH
다만 이 방법은 그 셸에서만 유효하고, systemd 서비스나 cron 처럼 다른 환경에서 도는 프로세스에는 적용되지 않는다. 또 전역으로 걸어 두면 다른 프로그램이 의도치 않은 버전을 물어 오는 사고가 난다. 운영 환경에서는 ld.so.conf.d 등록이 맞다.
서비스 하나에만 주고 싶으면 유닛 파일에 넣는다.
[Service]
Environment=LD_LIBRARY_PATH=/usr/local/nvidia/lib64
ldconfig 는 캐시만 만들 뿐 라이브러리를 설치하지 않는다. 파일이 없으면 아무리 돌려도 달라지지 않는다.
컨테이너 안에서는 이미지 빌드 단계에서 돌려야 한다. 실행 중에 돌린 결과는 그 컨테이너가 사라지면 함께 사라진다.
같은 이름의 라이브러리가 여러 경로에 있으면 ld.so.conf.d 의 파일 이름 순서가 우선순위를 가른다. 버전 충돌이 의심되면 ldconfig -p 로 어느 경로가 잡혔는지 먼저 확인한다.
NFS 등 느린 파일시스템을 등록하면 ldconfig 가 오래 걸리고 부팅이 느려진다.
nvidia-smi 가 보여 주는 값의 의미.