Some days ago, at the AWS Summit 2014, DamZ renewed my long-sleeping interest for the Google Go language with wonderous stories about its use in infrastructure of the new Commerce Guys Platform they were launching that same days, so I've been doing my homework getting up to date on Go programming: that's what holidays are for, aren't they ?
The symptoms
So this morning it was time to consider deploying to production... but alas, programs which worked normally on my Ubuntu development workstation failed to run on the target server, running Debian Squeeze, with rather mystifying results:
- Laptop: uname -a : Linux ubuntu 3.2.0-64-generic #97-Ubuntu SMP Wed Jun 4 22:04:21 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
- Target: uname -a : Linux v1085 3.2.23-vs2.3.2.12-beng #1 SMP Tue Jul 24 10:15:16 BST 2012 x86_64 GNU/Linux
- binary copied from one machine to the other with its config files, database schema and privileges set up on both machines
- All OK on the laptop.
So, for "file", this is an dynamically linked executable, but not for ldd ? And, even more surprising, a trivial helloworld.go
compiled the same way worked on both machines. What could be going wrong ?
The diagnostic
How about that ldd myapp
on the laptop ?
Now we're going somewhere: the same file is diagnosed differently by the same command on the two machines. How about checking that binary itself ?
So it turns out that this program needs /lib64/ld-linux-x86-64.so.2
which exists on one machine but not on the other. Symlinking ld-linux.so.2
to the missing path does change things (corrupted library error), but does not fix the problem.
OK, then how about installing Go 1.2.2 on that server and compiling there to see the difference ?
The golang-go
package for Debian Squeeze only contains Go 1.0, so it is not a solution either, so let's follow the instructions on http://golang.org/doc/install... and get the same error from the official go
binary for that distribution. Well, not /that/ surprising, at this point: let's build from source ! It's well documented too, on http://golang.org/doc/install/source, so let's proceeed.
So the official distribution does not compile either. Right, Squeeze is probably too old, and that server needed a Wheezy upgrade anyway... let's upgrade.
Well, not that much better... and predefs.h
is actually present in /usr/include/i386-linux-gnu/bits/predefs.h
. Was already there on Squeeze, actually. So it looks like for some reason, the go build appears to have an undocumented dependency on non-default multilib architecture configurations.
The solution
So let's just install that multilib support, even though it was not needed on Ubuntu 12.04 :
At last, the Go install process succeeds ! Let's skip the failing net tests, which cannot handle the IP specifics of the VM anyway (edit src/pkg/net/ipraw_test.go
and src/pkg/net/http/fs_test.go
to swap case on the failing tests), and we have a winner:
Long story short: in such deployment situations, digging into the entrails of binaries can be helpful. The file
, ldd
/ readelf
combo can work wonders.
And special thanks to to taruti on #go-nuts
, who really showed me the path.