예제 lshw
프로그램으로 다음이 ldd
제공됩니다.
$ ldd /usr/sbin/lshw
linux-vdso.so.1 => (0x00007fff8bdaf000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x000000360e400000)
libsqlite3.so.0 => /lib64/libsqlite3.so.0 (0x0000003631600000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x000000360ec00000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x000000360d800000)
libc.so.6 => /lib64/libc.so.6 (0x000000360c000000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x000000360cc00000)
libdl.so.2 => /lib64/libdl.so.2 (0x000000360c800000)
libm.so.6 => /lib64/libm.so.6 (0x000000360c400000)
/lib64/ld-linux-x86-64.so.2 (0x000000360bc00000)
공유 라이브러리의 절대 위치를 찾고 싶다면(그리고 명백한 이유로 linux-vdso.so.1을 제외하고 싶다면) 어떻게 해야 합니까? 정규 표현식과 함께 awk를 사용하면 취약해 보입니다. ldd
공유 라이브러리에 대한 전체 경로를 인쇄하는 자세한 플래그(-v)가 있지만 기계에서 읽을 수는 없습니다.
이 문제를 해결할 다른 방법이 있나요? 누군가 이 작업을 수행하는 시스템 호출을 알고 있다면 나도 동의할 것입니다.
추신: 어떤 상황에서는 이 프로그램을 감옥에서 실행하고 싶기 chroot
때문에 공유 라이브러리를 모두 사용할 수 있는지 확인해야 합니다. 이를 정적으로 컴파일하면 이 모든 드라마를 피할 수 있지만 그것이 제가 피하고 싶은 경로입니다.
고쳐 쓰다:
나는 나를 그리워한다가능한나는 Michael Kerrisk의 책 "Linux 프로그래밍 인터페이스"를 읽으면서 더 적합할 수 있는 것을 발견했습니다. 프로그램을 실행하면 $ LD_DEBUG=libs lshw
온갖 유용한 정보가 출력됩니다. 예를 들어:
$ LD_DEBUG=libs lshw
32058: find library=libresolv.so.2 [0]; searching
32058: search cache=/etc/ld.so.cache
32058: trying file=/lib64/libresolv.so.2
32058:
32058: find library=libstdc++.so.6 [0]; searching
32058: search cache=/etc/ld.so.cache
32058: trying file=/lib64/libstdc++.so.6
32058:
32058: find library=libgcc_s.so.1 [0]; searching
32058: search cache=/etc/ld.so.cache
32058: trying file=/lib64/libgcc_s.so.1
32058:
32058: find library=libc.so.6 [0]; searching
32058: search cache=/etc/ld.so.cache
32058: trying file=/lib64/libc.so.6
32058:
32058: find library=libm.so.6 [0]; searching
32058: search cache=/etc/ld.so.cache
32058: trying file=/lib64/libm.so.6
32058:
32058:
32058: prelink checking: ok
32058:
32058: calling init: /lib64/ld-linux-x86-64.so.2
32058:
32058:
32058: calling init: /lib64/libc.so.6
32058:
32058:
32058: calling init: /lib64/libm.so.6
32058:
32058:
32058: calling init: /lib64/libgcc_s.so.1
32058:
32058:
32058: calling init: /lib64/libstdc++.so.6
32058:
32058:
32058: calling init: /lib64/libresolv.so.2
<more output>
"calling init" 라인을 찾으면 프로그램 실행을 시작하기 전에 초기화되는 공유 라이브러리 경로를 갖게 될 것이라고 생각합니다.
답변1
정규식을 사용하지 않고 awk를 시도해 볼 수 있습니다.
ldd /bin/ls | awk 'NF == 4 {print $3}; NF == 2 {print $1}'
산출:
/lib/x86_64-linux-gnu/libselinux.so.1
/lib/x86_64-linux-gnu/librt.so.1
/lib/x86_64-linux-gnu/libacl.so.1
/lib/x86_64-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/libdl.so.2
/lib64/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/libpthread.so.0
/lib/x86_64-linux-gnu/libattr.so.1
답변2
정규식이 필요하지 않다고 말씀하셨지만 해당 줄의 "=>"를 사용하면 구문 분석이 쉬워집니다. 장황한 모드에서도 이를 사용하므로 장황한 출력을 정규식에 전달할 수도 있습니다(일부 조정 포함). 나는 chroot 환경을 설정하기 위해 루프 변수 목록(for i in ...)으로 이와 같은 명령을 사용합니다.
먼저 sed를 사용하는 두 가지 방법을 알려 드리겠습니다.
ldd /path/to/binary | egrep -v 'linux-vdso|ld-linux-x86-64' | sed 's/.*\=> \(.*\) (.*/\1/'
또는 다음과 같이 공백과 잘라내기를 사용하여 구문 분석해 볼 수도 있습니다.
ldd /path/to/binary | egrep -v 'linux-vdso|ld-linux-x86-64' | cut -f 3 -d ' '
이 두 가지 모두 나에게 다음을 제공합니다.
ldd /bin/ls | egrep -v 'linux-vdso|ld-linux-x86-64' | cut -f 3 -d ' '
/lib/libselinux.so.1
/lib/librt.so.1
/lib/libacl.so.1
/lib/libc.so.6
/lib/libdl.so.2
/lib/libpthread.so.0
/lib/libattr.so.1
답변3
GNU grep을 사용하십시오:
ldd /usr/sbin/lshw | grep -Po '/.*(?= \(0x)'
이러한 경로에 공백 문자가 포함되지 않는다고 보장할 수 있다면 다음과 같이 단순화할 수 있습니다.
ldd /usr/sbin/lshw | grep -o '/[^ ]*'
그리고 sed
:
ldd /usr/sbin/lshw | sed -n 's,[^/]*\(/.*\) (0x.*,\1,p'
아이디어는 처음 부터 마지막까지 /
모든 것을 얻는 것입니다.(0x