3

Is there a (relatively) simple way to test if an executable not only exists, but is valid?

By valid, I mean that an x86_64 Mach-O (OS X) executable will not run on an ARM Raspberry Pi. However, simply running tool-osx || tool-rpi works on OS X, where the executable runs, but does not fall back to tool-rpi when the x86_64 fails.

How can I fall back to another executable when one is invalid for the processor architecture?

6

Rather than testing for a valid executable, it's probably best to test what the current architecture is, then select the proper executable based on that. For example:

if [ $(uname -m) == 'armv6l' ]; then
    tool-rpi
else
    tool-osx
fi

However, if testing the executable is what you really want to do, GNU file can tell you the architecture of an executable:

user@host:~$ file $(whereis cat)
ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0x4e89fd8f129f0a508afa325b0f0f703fde610971, stripped
2

On Linux glibc, one hack you could use to test whether an dynamically linked executable would run successfully but without actually running it would be to set LD_DEBUG=help in its environment. It it's good it will emit a help message (which you ignore) and exit successfully, and if it is invalid then you will get an error.

Unfortunately this is specific to Linux glibc and it sounds like you are asking about MacOS. Also, it is ineffective with statically linked binaries and with setuid or setgid binaries.

  • Rather than invoke the program directory, invoke the loader and make it print something about the program. That way you'll get an error if the file sin't a dynamically linked executable. That's how ldd works, so just run ldd /path/to/program. – Gilles 'SO- stop being evil' Jan 4 '15 at 23:42
  • Sure, @Gilles if you like. Keep in mind that ldd is nothing but a shell script that does more or less what I said in my answer: set an environment variable and runs the executable. – Celada Jan 5 '15 at 5:05
  • No, there's a difference, which is precisely what I discuss in my comment: ldd invokes the loader explicitly, it runs LD_xxx=… /lib/ld-linux.so /bin/foo, not LD_xxx=… /bin/foo. – Gilles 'SO- stop being evil' Jan 5 '15 at 8:40
  • @Gilles Ah, I didn't know that ldd did that. I understand now. – Celada Jan 5 '15 at 21:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.