Transplanting Linux Libraries to a Shared Host

The goal is to run Linux binaries on a shared host where we do not have root access, and there are no package managers installed (because it’s shared hosting). The shared libraries need to be copied over manually. Here is how we can do it.

If you’re like me, you might have a (few) shared hosting accounts around town. They’re inexpensive and convenient. When I want to run tools like Xvfb and wkhtmltoimage they need shared libraries (the .so files). Some shared libraries might be helpfully present (e.g. libc.so, libgtk-x11-2.so, libasound.so), but some are not (e.g. libstdc++). Since it is a shared host there are no package managers installed, or else we could just yum-install it.

You can find the Xvfb package online (e.g. from rpmfind.net), but it has dependencies and those dependencies might have more dependencies1. Even if I manually find all the best-match packages and extract the libraries, the gotcha is that there may still be problems like the following.

The shared host in this example is using an older version of GLibc. First, I need to know which one by running /lib64/libc.so.6 or ldd --version.

This means that on this example system I must use libraries that at most link to GLibc 2.12. I’d like to avoid recompiling the binaries I’m trying to use to change the “baked in” path of /lib64/libc.so.6 (but we can), and unfortunately we cannot use LD_PRELOAD (more info) for a local version of libc.so.6:

So I either change hosts, switch over to a VPS, or perform a transplant from a compatible system. Let’s continue with the latter.

This shared host is a 64-bit RHEL.

One trick is to find a VMWare/VirtualBox image of 64-bit CentOS (e.g. from osboxes.org), get that running (install VMware tools – here is an easy install guide – and configure networking via system-config-network), and yum the packages needed.

GLibc version 2.12
CentoOS 6.8 GLibc version 2.12

The CentOS 6.8 virtual machine I’m using here has the target GLibc 2.12 so I can go ahead and install packages, and transfer the shared libraries from the /usr/lib64 folder.

Continuing this example with Xvfb, which is used in a SlimerJS project, we can install it like so:

Let’s see what non-system dependencies were created in the /usr/lib64 folder:

These are the shared libraries residing in /usr/lib64 that are being linked against by Xvfb, and are symlinked to the actual libraries. With tar we can get them dereferenced and compressed for transport to the target machine. Using the Xvfb binary example the tarball of the shared libraries can be created.

Assume for this discussion that the following environment variable is set:

Let’s construct our tar script step by step. First we’ll print out all the libraries we want to transplant.

This will list the full path to the shared libraries, symlink or not. The greps only include libraries in the usr/lib64 folder, and exclude any libraries which are not found.

Next we need to print the paths all on one line to prepare it for tar.

This results in

Let’s preview the expanded command before the tarball is made.

The above command should produce a similar result to that below.

The tar options are where the magic happens. Importantly, the -h or --dereference switch tells tar to follow any symlinks and include the actual file in the tarball. The --xform='s|.*/||' strips the directory structure from the resulting tarball so all the library files at the base of the archive2.

This is the final command to create our tar’d archive of shared libraries.

The result is a tarball of the actual shared libraries needed with dereferenced symlinks ready to be uploaded to the shared server3.

Tarball of linux shared libraries
Tarball of linux shared libraries

From here we can uncompress them on the shared host in a local library folder and reference that folder in LD_LIBRARY_PATH.

Notes:

  1. Some packages like Xorg require additional binaries (e.g. xkb, xkbcomp, setxkbmap, etc.) so this process can take some time to copy everything over.
  2. The xform/sed solution is thanks to this StackOverflow answer.
  3. If we want to upgrade/update the binary, the above likely has to be repeated. There is no yum update available on a shared host.