Running old Linux apps on new Distros

I have a number of customers running older Linux apps. Sometimes they have source for the app, sometimes they don't. Sometimes the original app vendor still exists and is willing to be helpful, sometimes they are out of business or uninterested in the old app because they want to sell something newer.

Often the app will make a graceful transition across operating system upgrades and changes. Sooner or later though, it probably breaks.

Sometimes the fix is simple. Defining and exporting LD_ASSUME_KERNEL might let an older app run on a newer kernel.

Sometimes it takes a bit more. I recently had an app that had come from RedHat 6 days and had successfully aged until the latest Debian stopped it cold. To solve that, I asked "ldd" to show what libraries it used. That returned: =>  (0xb7fac000) => /lib/i686/cmov/ (0xb7f7c000) => /lib/i686/cmov/ (0xb7e21000)
	/lib/ (0xb7fad000)

You can ignore linux-gate. That meant I needed, and from a system where the app worked. I copied them to the new Debian and stuck them in a new directory I called /oldlibs.

I then changed the calling script to look something like this:


/oldlibs/  oldapp 

If you just type "/lib/ld-linux.s0.2", you'll see what's going on here:

You have invoked `', the helper program for shared library executables.
This program usually lives in the file `/lib/', and special directives
in executable files using ELF shared libraries tell the system's program
loader to load the helper program from this file.  This helper program loads
the shared libraries needed by the program executable, prepares the program
to run, and runs it.  You may invoke this helper program directly from the
command line to load and run an ELF executable file; this is like executing
that file itself, but always uses this helper program from the file you
specified, instead of the helper program file specified in the executable
file you run.  This is mostly of use for maintainers to test new versions
of this helper program; chances are you did not intend to run this program.

But we really did intend it here.

That worked, but we very quickly ran into another problem - the app makes calls to shell scripts and other utilities. Most of those won't work when running with the old libraries. What now?

There are several ways around it. In this case, we had some source (well, source and object files). The program supposedly could be statically linked. That would eliminate the need for old libraries. However, we had no luck getting the code to link statically and the app vendor was uninterested or unavailable.

Wrap it

Another way is to wrap the shell calls in a new environment. You can see that at work easily with a couple of shell scripts:



That breaks with:

/bin/ls: relocation error: /lib/i686/cmov/ symbol
errno, version GLIBC_PRIVATE not defined in file with link
time reference

We can fix that if we create another script (I'll call it "runit"):


/lib/ $*

We'd change the original script like this:


runit   /bin/ls

The problem here is that we have to modify every call. That's not impossible, but it is annoying. So is messing with PATH to front-end commands. But we could make wrappers for every command used and put them early in PATH - our "/newbin/ls" (and everything else) would be:


/lib/   $0 $*

Note the use of $0 here. That lets us use the same script everywhere.

But it can't be that simple because a shell script isn't going to work - the shell gets called from the oldlib environment and it needs the normal libraries. We'd need to write something that will work and have it reset the environment for the next call.

Maybe something like this (haven't tried it yet):

main (int argc, char** argv)
	char *env[]= { (char *)0 };
	execve (argv[0],argv, env);

You'd compile that on the OLD system, not the new. It's going to run in the /oldlib environment so it needs to have come from there.

That just runs whatever it is passed with no environment, which isn't going to work for a lot of things. Hmmm.. this is tricky, isn't it?

Probably what we want is something like this:

main (int argc, char** argv, char **envp)
	execve (argv[0],argv, envp);

That unsets the stuff we don't want. Will it work? I don't know.

These aren't the only issues, though. See How to Run Binary-Only Application Packages on Various Versions of Linux for more on that.

What about a VM?

He could run the old OS and old app in a VM. There are a few things not to like about that. First, running in a VM is always going to be slower than running natively. Always? Well, no: if the app is coming from an old OS on old hardware, it can sometimes run faster under a VM. However, in this specific case, that wasn't true: he would have to take some performance loss.

The other disadvantage is security and features. The old OS is an old OS. It may lack features we need or want and may have security weaknesses that can be hard to fix. Life is such fun, isn't it?

With some effort, you might be able to avoid that by turning the old app into a two or three tier client-server app. That is, you write a new app on your new OS that makes protected back-end calls to a tightly protected process running on the VM. That could be a fair amount of work, though.

Getting old isn't fun for us or our applications.

Got something to add? Send me email.

(OLDER) <- More Stuff -> (NEWER)    (NEWEST)   

Printer Friendly Version

-> -> Running old Linux apps on new Distros

Increase ad revenue 50-250% with Ezoic

More Articles by

Find me on Google+

© Anthony Lawrence

Kerio Samepage

Have you tried Searching this site?

Support Rates

This is a Unix/Linux resource website. It contains technical articles about Unix, Linux and general computing related subjects, opinion, news, help files, how-to's, tutorials and more.

Contact us