Sometimes it is necessary to copy a Linux binary with its lib dependencies to a folder or archive. For example when creating an chroot environment, create an initramfs or copy a binary with required libs from one machine to another with the same architecture and kernel interface (this is hackish, yes)

Because I frequently needed to do this, I wrote a small shell-script for that purpose. Here comes the script, explanation will follow:

#!/bin/bash

if [ $# != 2 ] ; then
    echo "usage $0 PATH_TO_BINARY TARGET_FOLDER"
    exit 1
fi

PATH_TO_BINARY="$1"
TARGET_FOLDER="$2"

# if we cannot find the the binary we have to abort
if [ ! -f "$PATH_TO_BINARY" ] ; then
    echo "The file '$PATH_TO_BINARY' was not found. Aborting!"
    exit 1
fi

# copy the binary to the target folder
# create directories if required
echo "---> copy binary itself"
cp --parents -v "$PATH_TO_BINARY" "$TARGET_FOLDER"

# copy the required shared libs to the target folder
# create directories if required
echo "---> copy libraries"
for lib in `ldd "$PATH_TO_BINARY" | cut -d'>' -f2 | awk '{print $1}'` ; do
   if [ -f "$lib" ] ; then
        cp -v --parents "$lib" "$TARGET_FOLDER"
   fi  
done

# I'm on a 64bit system at home. the following code will be not required on a 32bit system.
# however, I've not tested that yet
# create lib64 - if required and link the content from lib to it
if [ ! -d "$TARGET_FOLDER/lib64" ] ; then
    mkdir -v "$TARGET_FOLDER/lib64"
fi

The script uses ldd to get a list of all libraries the binary is linked to. Then it copies the libraries – keeping their folder structure – to the target folder. I saved the above script to exportbin.sh. Here comes an usage example that exports bash and ls to a folder that will be used as a tiny chroot environment later:

thorsten@home:/tmp$ mkdir -v my_chroot
thorsten@home:/tmp$ ./exportbin.sh /bin/bash my_chroot
---> copy binary itself
/bin -> my_chroot/bin
»/bin/bash“ -> »my_chroot/bin/bash“
---> copy libraries
/lib -> my_chroot/lib
/lib/x86_64-linux-gnu -> my_chroot/lib/x86_64-linux-gnu
»/lib/x86_64-linux-gnu/libtinfo.so.5“ -> »my_chroot/lib/x86_64-linux-gnu/libtinfo.so.5“
»/lib/x86_64-linux-gnu/libdl.so.2“ -> »my_chroot/lib/x86_64-linux-gnu/libdl.so.2“
»/lib/x86_64-linux-gnu/libc.so.6“ -> »my_chroot/lib/x86_64-linux-gnu/libc.so.6“
/lib64 -> my_chroot/lib64
»/lib64/ld-linux-x86-64.so.2“ -> »my_chroot/lib64/ld-linux-x86-64.so.2“
---> link all libraries from /lib to /lib64
»my_chroot//lib64/libtinfo.so.5“ -> »../lib/libtinfo.so.5“
»my_chroot//lib64/libdl.so.2“ -> »../lib/libdl.so.2“
»my_chroot//lib64/libc.so.6“ -> »../lib/libc.so.6“
thorsten@home:/tmp$ $ ./exportbin.sh /bin/ls my_chroot
---> copy binary itself
»/bin/ls“ -> »my_chroot/bin/ls“
---> copy libraries
»/lib/x86_64-linux-gnu/libselinux.so.1“ -> »my_chroot/lib/x86_64-linux-gnu/libselinux.so.1“
»/lib/x86_64-linux-gnu/librt.so.1“ -> »my_chroot/lib/x86_64-linux-gnu/librt.so.1“
»/lib/x86_64-linux-gnu/libacl.so.1“ -> »my_chroot/lib/x86_64-linux-gnu/libacl.so.1“
»/lib/x86_64-linux-gnu/libc.so.6“ -> »my_chroot/lib/x86_64-linux-gnu/libc.so.6“
»/lib/x86_64-linux-gnu/libdl.so.2“ -> »my_chroot/lib/x86_64-linux-gnu/libdl.so.2“
»/lib64/ld-linux-x86-64.so.2“ -> »my_chroot/lib64/ld-linux-x86-64.so.2“
»/lib/x86_64-linux-gnu/libpthread.so.0“ -> »my_chroot/lib/x86_64-linux-gnu/libpthread.so.0“
»/lib/x86_64-linux-gnu/libattr.so.1“ -> »my_chroot/lib/x86_64-linux-gnu/libattr.so.1“
---> link all libraries from /lib to /lib64
»my_chroot//lib64/librt.so.1“ -> »../lib/librt.so.1“
»my_chroot//lib64/libpthread.so.0“ -> »../lib/libpthread.so.0“
»my_chroot//lib64/libattr.so.1“ -> »../lib/libattr.so.1“
»my_chroot//lib64/libselinux.so.1“ -> »../lib/libselinux.so.1“
»my_chroot//lib64/libtinfo.so.5“ -> »../lib/libtinfo.so.5“
»my_chroot//lib64/libdl.so.2“ -> »../lib/libdl.so.2“
»my_chroot//lib64/libc.so.6“ -> »../lib/libc.so.6“
»my_chroot//lib64/libacl.so.1“ -> »../lib/libacl.so.1“

Note that your output may differ from that depending on your distribution and system architecture. Let’s chroot to the exported environment to test if it works:

thorsten@home:/tmp$ chroot my_chroot /bin/bash # uses the exported bash
bash-4.2$ # we are now into the chroot env. bash works. lets try ls
bash-4.2$ ls
bin lib lib64
bash-4.2# exit # ls is working too. leave the chroot env
thorsten@home:/tmp$

A binary will in many cases not only depend on libraries. It cab depend on configuration files or other files too. You’ll have to copy that files by your own to the target folder.

have fun!

3 Responses to “Export a linux binary with its lib dependencies to a chroot or initramfs, …”

  1. yash Says:

    das ist ubergut! dank

  2. thorsten Says:

    @yash thanks! :)

  3. ITALIC™ » Ubuntu 14 chroot sftp et rsync Says:

    […] U NEED DIS: http://www.metashock.de/2012/11/export-binary-with-lib-dependencies/ […]

Leave a Reply