Displaced Geek

Just a city geek and father coming to terms with being replanted in farm country

Basic Linux Executable Troubleshooting

Fair warning, that’s the last cute Gabriella picture in this post. Sorry Jen!

If you use a computer, you’re bound to run into something that doesn’t work every once in a while. Even worse is when something fails silently, or almost silently. With no clear error message, you might think you’re stuck, but one of the perks of running linux is that you’re never actually stuck. When something fails silently, you make it talk, see what it says, and fix it. The steps I outline below are not advanced techniques, they’re not mystical greybeard tactics, they’re just the first steps to take when you don’t know why a downloaded program isn’t running on your linux desktop.

Before we get started, a word of warning. Make sure you execute all of the following commands as a regular user, NOT as root. All debugging tools are inherently dangerous, running them as root when you don’t need to is a recipe for mistakes you cannot undo.

Okay, first we need some information about the box we’re running on, and for that we use the command ‘uname -a’:

$uname -a
Linux Jack 3.1.0-1.2-desktop #1 SMP PREEMPT Thu Nov 3 14:45:45 UTC 2011 (187dde0) x86_64 x86_64 x86_64 GNU/Linux

That’s a lot of information, but all we really need right now is the kernel release, machine, processor, and hardware platform.

Linux Jack 3.1.0-1.2-desktop #1 SMP PREEMPT Thu Nov 3 14:45:45 UTC 2011 (187dde0) x86_64 x86_64 x86_64 GNU/Linux

Alright, we’re clearly dealing with a 64bit machine here.

Now that we know what type of machine we’re working with, let’s see what it is we’re trying to run. The fastest way to see what the system thinks of our mystery program is to run ‘file’

At this point you’ll have to take a look at your output for one of four key elements:
NB: your output may be wildly different, but the key elements to look for will be the same for the purposes of this post.

$file /path/to/executable
/path/to/executable: symbolic link to '/some/other/path'


$file /path/to/executable
/path/to/executable: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, stripped


$file /path/to/executable
/path/to/executable: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.8, stripped


$file /path/to/executable
/path/to/executable: POSIX shell script, ASCII text

Your next step is completely dependent on which of the above key highlighted elements is present in your output. There are plenty of other possible outputs that I might cover later, but for now let’s look at those four.

If your executable is a shell script, then it’s quite likely not dependent on a specific kernel version or hardware platform – you’re going to want to take a look at it without changing anything. Go ahead and type ‘cat’, and you’ll get something like this:

$cat ./df
DF_DIR=$(dirname "$0")
cd "${DF_DIR}"
export SDL_DISABLE_LOCK_KEYS=1 # Work around for bug in Debian/Ubuntu SDL patch.
#export SDL_VIDEO_CENTERED=1 # Centre the screen. Messes up resizing.
./libs/Dwarf_Fortress $* # Go, go, go! : )

Most non-functional scripts are longer than that, and not commented as nicely, but you get the idea
There isn’t much advice that’ll cover all scripting error scenarios, so at this point if viewing the script doesn’t help, I suggest you either ask for help in a forum somewhere, or go learn to script for yourself.

If your executable is actually a symlink, like the first snippet above, try running actual executable file directly. It may fail with an actual error you can troubleshoot, and it may even work automagically. If it produces the same silent fail as the link pointing to it, then determine what kind of executable it is and follow the appropriate steps below.

The last two options are more complex, and as such provide us with more troubleshooting options. First make sure that there are no known issues with your particular platform, and the executable you’re trying to run. As a rule, 32bit programs run on 64 bit machines, but not the other way around. And as another rule, all rules have exceptions and workarounds, but if you simply need a different file, go get it and save yourself the time and effort of troubleshooting something that is known not to work.

The most common problem I’ve encountered when running a dynamic executable, is a missing or improperly linked library. Fortunately ‘ldd‘ is a simple tool to see what it is your file is looking for.

$ldd ./libs/Dwarf_Fortress
linux-gate.so.1 => (0xffffe000)
libSDL-1.2.so.0 => /usr/lib/libSDL-1.2.so.0 (0xf769c000)
libgraphics.so => /home/PHPete/DF/libs/libgraphics.so (0xf728d000)
libstdc++.so.6 => /home/PHPete/DF/libs/libstdc++.so.6 (0xf71b0000)
libm.so.6 => /lib/libm.so.6 (0xf7185000)
libgcc_s.so.1 => /home/PHPete/DF/libs/libgcc_s.so.1 (0xf7169000)
libc.so.6 => /lib/libc.so.6 (0xf6ffd000)
libpthread.so.0 => /lib/libpthread.so.0 (0xf6fe2000)
libasound.so.2 => /usr/lib/libasound.so.2 (0xf6efd000)
libdl.so.2 => /lib/libdl.so.2 (0xf6ef8000)
libmissing.so.num => (file not found)

Now you just have to find where to download ‘libmissing.so.num’ for your particular distro, and that should do it. Of course your dynamic executable is having some other issue, you can try the steps below.

We can usually figure out where a static executable is going wrong by seeing what it’s trying to do every step of the way. For this, we’re going to use a program called strace.

Strace is a powerful tool, and we’re barely going to scratch the surface for our purposes, but even so, if you’re reading this, then you’ll have bucketloads more information than you know what to do with, and tracking down your issue may begin to feel like searching for a needle in a pile of fake needles, but the information is there, I promise.

In this case I like to run:

$strace -q ~/bin/unb

Alright, now if you just ran that your screen probably looks like this

connect(8, {sa_family=AF_FILE, path=@"/tmp/.X11-unix/X0"}, 20) = 0
getpeername(8, {sa_family=AF_FILE, path=@"/tmp/.X11-unix/X0"}, [20]) = 0
uname({sys="Linux", node="Jack", ...}) = 0
access("/home/PHPete/.Xauthority", R_OK) = 0
open("/home/PHPete/.Xauthority", O_RDONLY) = 9
fstat(9, {st_mode=S_IFREG|0600, st_size=159, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f1bfdd98000

and you’re screaming “NO! NO! NO! Slow down! AAAARGH!”
Okay, maybe you’re not that melodramatic, but you’re overwhelmed. That’s because I left something out. Our filter, also known as awk.


Running linux without at least knowing the basics of awk is similar to riding a bike without ever changing gears, or rather without knowing HOW to change gears. It’s perfectly possible, but you’re making life harder on yourself.

But I digress. The full command we want to use is

strace -q ~/bin/unb 2>&1 |awk '/ENOENT/ {print $0}'.

Without breaking the whole thing down, let’s suffice to say that will show you most of the files that your executable looked for and couldn’t find. If you want to see every error that your executable ran into as it was running, (you really really don’t) simply replace /ENOENT/ (the no such file code) with /-1 E/ (-1 is the error value, and the ‘space-E’ matches all the error codes).

At this point you should have more than enough information to see what’s going wrong. Remember – Google is your friend, and there ARE people who are willing to help newbies with their questions. You just have to find us ๐Ÿ˜‰

Written by Peter

January 21, 2012 at 015

Posted in geek

Tagged with , , , ,

2 Responses

Subscribe to comments with RSS.

  1. I appreciate the photo…. Can all your future Linux posts start this way? Please? That way I’ll actually read them and not just Mark As Read in Google Reader. ๐Ÿ™‚


    January 21, 2012 at 1105

    • Yeah, I figure I’ve gotta give my adoring public what it wants, right?
      Alright, so maybe adoring is a bit of a stretch, but still. ๐Ÿ˜‰


      January 21, 2012 at 1256

Comments are closed.

%d bloggers like this: