Troubleshooting¶
When installing scientific software you are bound to run into problems that make the installation fail sooner or later, even when using EasyBuild...
In this part we take a look at how you can troubleshoot a failing installation, and focus on a couple of EasyBuild aspects that can be helpful in that context, like the error messages produced by EasyBuild, the detailed log file that is available for the installation and the build directory where most software is being compiled before it actually gets installed.
At the end of this part an exercise is available in which you get to fix a failing installation, so pay attention!
EasyBuild error messages¶
When EasyBuild detects that something went wrong, it will usually produce a short (and hopefully helpful) error message.
Things that could go wrong during an installation include:
- missing source or patch files;
- a checksum error on a downloaded source or patch file;
- required dependencies that are not specified in the easyconfig file;
- failing shell commands;
- running out of available memory or disk space;
- a segmentation fault caused by a flipped bit triggered by a cosmic ray (really, it happens!);
Unfortunately this is not an exhaustive list, there are plenty of other potential problems that could result in a failing installation...
For each of the shell commands that EasyBuild executes during an installation, it will check the exit status. If the exit status is zero, EasyBuild will usually assume that the shell command ran correctly, and it will continue with the rest of the installation procedure.
If the exit status of the shell command is anything but zero, EasyBuild will assume that a problem has occurred, and the installation will be interrupted.
Example¶
Here is an example of an EasyBuild error message (slightly reformatted for clarity):
$ eb example.eb
...
== building...
== FAILED: Installation ended unsuccessfully (build directory: /tmp/example/example/1.0/GCC-10.2.0):
build failed (first 300 chars): cmd "make" exited with exit code 2 and output:
/usr/bin/g++ -O2 -ftree-vectorize -march=native -fno-math-errno -std=c++14 -c -o core.o core.cpp
g++: error: unrecognized command line option '-std=c++14' (took 1 sec)
== Results of the build can be found in the log file(s) /tmp/eb-dbobppfh/easybuild-example-1.0-20200613.145414.aUEJA.log
ERROR: Build of /home/easybuild/subread.eb failed (err: ...)
Let's break this down a bit: during the build
step of the installation
procedure EasyBuild was running make
as a shell command, which
failed (exit code 2, so not zero).
The make
command tripped over the compilation of core.cpp
that failed because
-std=c++14
is not a known option to the g++
command.
OK fine, but now what? Can you spot something suspicious here?
Wait a minute... Why is make
using /usr/bin/g++
for the compilation?!
That's not where our toolchain compiler is installed,
that's somewhere under /easybuild/software
.
Let's see what /usr/bin/g++
is:
$ /usr/bin/g++ --version
g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)
Oh my that's pretty ancient (GCC 4.8.5 was released in June 2015). That could definitely explain why it doesn't know about the C++14 standard yet...
Your next step in this case should probably be figuring
out why /usr/bin/g++
is being used rather than just g++
, which would
result in using the right compiler version because EasyBuild sets up the build
environment carefully.
This is a imaginary example of course, but hopefully it gives you a feeling of how errors that occur during the installation are handled.
EasyBuild log files¶
Finding the cause of a problem that made the installation fail is, unfortunately, not always that straightforward...
EasyBuild includes (only) the first 300 characters of the output produced by a failing shell command in the error message, which is a simple way to try include actionable information in the error message while not flooding your terminal with the full output of the command that failed.
In some cases there won't be any useful information in there however, since the actual error message(s) could only appear way later, perhaps even after the command was already running for several minutes.
In that case, you will have the dive into the log file that is created by EasyBuild for every installation, which is located in the unique temporary directory for the EasyBuild session.
See for example this output line from our earlier example error message:
== Results of the build can be found in the log file(s) /tmp/eb-dbobppfh/easybuild-example-1.0-20200613.145414.aUEJA.log
You can open this file with your favorite text editor or a tool like less
to take a look at the information collected in the log file, which includes
things like:
- informative messages produced by both the EasyBuild framework and the easyblock describing how the installation is progressing;
- how the build environment was set up: which modules were loaded, which environment variables were set;
- the exact shell commands that were executed, and in which directory they were run;
- the full output produced by these commands, and their exit code;
Note that the installation log is also copied into each software installation
directory for successful installation, into the easybuild
subdirectory.
For example:
/easybuild/software/HDF5/1.10.7-gompi-2020b/easybuild/easybuild-HDF5-1.10.7-20210616.055237.log
Last log¶
The eb
command supports a handy little option that prints the location
to the most recently updated build log. You can leverage this to quickly
open the build log of the last failed EasyBuild session in an editor:
vim $(eb --last-log)
Navigating log files¶
Usually you want to go to the end of the log file and then work your way up, either by scrolling or by searching for specific patterns. Here are a couple of suggestions of patterns you can use to locate errors:
ERROR
Error 1
error:
failure
not found
No such file or directory
bazel
Segmentation fault
Using "error
" as a search pattern is not very useful: you will hit a lot of log lines
that are not actually errors at all (like the compilation of an error.c
file),
and you will miss others that do include errors but mention ERROR
or Error
rather than error
.
When using less
to view a log file, you can navigate it by:
- hitting '
$
' followed by 'G
' to go to the end of the log file; - using your arrow keys to scroll up/down;
- typing '
?
' followed by some text and Enter to search backwards for a particular pattern ('/
' to search forwards, 'n
' for next match); - hitting '
q
' to exit;
It can also be helpful to zoom in on a specific step of the installation procedure, which you can do by looking for step markers like these:
== 2020-06-13 01:34:48,816 example INFO configuring...
== 2020-06-13 01:34:48,817 example INFO Starting configure step
...
== 2020-06-13 01:34:48,823 main.EB_HPL INFO Running method configure_step part of step configure
If you want to look at the start of the output produced by a particular command,
you can look for the log message that looks like this (this is from the installation
log for HDF5
):
== 2020-06-09 13:11:19,968 run.py:222 INFO running cmd: make install
== 2020-06-09 13:11:25,186 run.py:538 INFO cmd " make install " exited with exit code 0 and output:
Making install in src
make[1]: Entering directory `/tmp/example/HDF5/1.10.7/gompi-2020b/hdf5-1.10.7/src'
...
It can be useful to look for the first error that occurred in the output of a command, since subsequent errors are
often fallout from earlier errors. You can do this by first navigating
to the start of the output for a command using "INFO running cmd
" as a search pattern, and then looking for patterns
like "error:
" from there.
Inspecting the build directory¶
When an installation fails the corresponding build directory is not cleaned up automatically, that is only done for successful installations. This allows you to dive in and check for clues in the files that are stored there.
The location of the build directory is mentioned in the EasyBuild error message:
== FAILED: Installation ended unsuccessfully (build directory: /tmp/example/example/1.0/GCC-10.2.0): ...
For software using a classic configure
script, you may have to locate
and inspect the config.log
file in the build directory to determine the underlying cause of an error. For software using CMake as a configuration tool you often have to check in
CMakeOutput.log
or CMakeError.log
for clues, which are sneakily hidden by CMake in a CMakeFiles
subdirectory of the build directory.
As a side note here: as EasyBuild does not clean out build directories for failed builds, you will need to eventually manually remove them from the buildpath
directory.
Exercise¶
Let's work our way through a less smooth software installation, using the easyconfig file that is provided below.
Don't worry if most of this is still unclear to you, we'll get to writing easyconfig files from scratch later in this tutorial.
easyblock = 'MakeCp'
name = 'Subread'
version = '2.0.1'
homepage = 'http://subread.sourceforge.net'
description = "High performance read alignment, quantification and mutation discovery"
toolchain = {'name': 'GCC', 'version': '8.5.0'}
# download from https://download.sourceforge.net/subread/subread-2.0.1-source.tar.gz
sources = ['subread-%(version)s-source.tar.gz']
checksums = ['d808eb5b1823c572cb45a97c95a3c5acb3d8e29aa47ec74e3ca1eb345787c17b']
start_dir = 'src'
# -fcommon is required to compile Subread 2.0.1 with GCC 10,
# which uses -fno-common by default (see https://www.gnu.org/software/gcc/gcc-10/porting_to.html)
buildopts = '-f Makefile.Linux CFLAGS="-fast -fcommon"'
files_to_copy = ['bin']
sanity_check_paths = {
'files': ['bin/featureCounts', 'bin/subread-align'],
'dirs': ['bin/utilities'],
}
sanity_check_commands = ["featureCounts --version"]
moduleclass = 'bio'
Do you spot any potential problems yet with this easyconfig file?
Preparation
Start by copying the text above in a file named subread.eb
,
so you can gradually fix the problem you'll encounter.
Also make sure that the pre-installed software stack is available, and that the EasyBuild module is loaded (unless you installed EasyBuild yourself):
module use /easybuild/modules/all
module load EasyBuild
For this exercise, make sure EasyBuild is configured to
use $HOME/easybuild
as prefix
, and to use /tmp/$USER
as buildpath
:
export EASYBUILD_PREFIX=$HOME/easybuild
export EASYBUILD_BUILDPATH=/tmp/$USER
Check your configuration via eb --show-config
.
Strictly speaking the configuration doesn't matter much for the sake of this exercise, but it may help with the step-wise approach we'll take and grasping the solutions.
Remember though: no peeking before you tried to solve each step yourself!
Exercise T.1 - Sources
Try to install the subread.eb
easyconfig file, see what happens.
Can you fix the problem you run into, perhaps without even changing the easyconfig file?
(click to show solution)
The installation fails because the source file subread-2.0.1-source.tar.gz
is not found:
$ eb subread.eb
...
== FAILED: Installation ended unsuccessfully (build directory: /tmp/example/Subread/2.0.1/GCC-8.5.0): build failed (first 300 chars):
Couldn't find file subread-2.0.1-source.tar.gz anywhere, and downloading it didn't work either...
Paths attempted (in order): ...
In this case, the problem is that the easyconfig file does not specify where the sources can be downloaded from. Not automatically at least, but there is a helpful comment included:
# download from https://download.sourceforge.net/subread/subread-2.0.1-source.tar.gz
sources = ['subread-%(version)s-source.tar.gz']
We can download the source tarball ourselves,
and move it to the location where EasyBuild expects to find it
(in the sourcepath
directory):
curl -OL https://download.sourceforge.net/subread/subread-2.0.1-source.tar.gz
mv subread-2.0.1-source.tar.gz $HOME/easybuild/sources/s/Subread/
If downloading is problematic for some reason, the source tarball is also available
in /easybuild/sources/s/Subread
.
Or, we can change the easyconfig file to specify the location where the easyconfig file can be downloaded from:
source_urls = ['https://download.sourceforge.net/subread/']
sources = ['subread-%(version)s-source.tar.gz']
source_urls
value is a list of candidate download URLs,
without the filename of the source file itself.
This way, EasyBuild will download the source file when running eb subread.eb
.
The source tarball is fairly large (23MB), so don't be alarmed if the download takes a little while.
$ ls -lh $HOME/easybuild/sources/s/Subread
total 23M
-rw-rw-r-- 1 easybuild easybuild 23M Jun 13 17:42 subread-2.0.1-source.tar.gz
Exercise T.2 - Toolchain
After fixing the problem with missing source file, try the installation again.
What's wrong now? How can you fix it quickly?
Take into account that we just want to get this software package installed, we don't care too much about details like the version of the dependencies or the toolchain here...
(click to show solution)
The installation fails because the easyconfig specifies that GCC 8.5.0 should be used as toolchain:
$ eb subread.eb
...
== FAILED: Installation ended unsuccessfully (build directory: /tmp/easybuild/Subread/2.0.1/GCC-8.5.0): build failed (first 300 chars):
No module found for toolchain: GCC/8.5.0 (took 1 sec)
We don't have this GCC version installed, but we do have GCC 10.2.0:
$ module avail GCC/
----------------- /easybuild/modules/all ------------------
GCC/10.2.0
So let's try using that instead.
Edit the easyconfig file so it contains this:
toolchain = {'name': 'GCC', 'version': '10.2.0'}
Exercise T.3 - Build step
With the first two problems fixed, now we can actually try to build the software.
Can you fix the next problem you run into?
(click to show solution)
The compilation fails, but the error message we see is incomplete due to EasyBuild truncating the command output (only the 300 first characters of the output are shown):
== FAILED: Installation ended unsuccessfully (build directory: /tmp/easybuild/Subread/2.0.1/GCC-10.2.0): build failed (first 300 chars):
cmd " make -j 1 -f Makefile.Linux CFLAGS="-fast -fcommon"" exited with exit code 2 and output:
gcc -mtune=core2 -O3 -DMAKE_FOR_EXON -D MAKE_STANDALONE -D SUBREAD_VERSION=\""2.0.1"\" -D_FILE_OFFSET_BITS=64 -fmessage-length=0 -ggdb -fast -fcommon -c -o core.o core.c
gcc: error: unrecognized command line opti (took 1 sec)
If you open the log file and scroll to the end, the error is pretty obvious:
gcc: error: unrecognized command line option -fast; did you mean -Ofast?
make: *** [core.o] Error 1
The easyconfig file hard specifies the -fast
compiler flag via the CFLAGS
argument to the build command:
# -fcommon is required to compile Subread 2.0.1 with GCC 10,
# which uses -fno-common by default (see https://www.gnu.org/software/gcc/gcc-10/porting_to.html)
buildopts = '-f Makefile.Linux CFLAGS="-fast -fcommon"'
EasyBuild sets up the build environment, so there should be no need
to hard specify compiler flags (certainly not incorrect ones).
The comment above the buildopts
definition makes it clear that the -fcommon
flag is required though, because GCC 10 became a bit stricter by
using -fno-common
by default. Note that we are using -fcommon
as an escape mechanism here: it would be better to fix the source code
and create a patch file instead.
An easy way to fix this problem is to replace the -fast
with -Ofast
,
as the compiler error suggests.
In this case it is advised to change the CFLAGS
argument that is added
to be build command to replace the -fast
with $CFLAGS
,
which is defined in the build environment by EasyBuild.
buildopts = '-f Makefile.Linux CFLAGS="$CFLAGS -fcommon"'
Note that we need to be careful with quotes here: we use inner double quotes
to ensure that $CFLAGS
will be expanded to its value when the build command is run.
Exercise T.4 - Sanity check
After fixing the compilation issue, you're really close to getting the installation working, we promise!
Don't give up now, try one last time and fix the last problem that occurs...
(click to show solution)
Now the installation itself works but the sanity check fails, and hence the module file does not get generated:
$ eb subread.eb
...
== FAILED: Installation ended unsuccessfully (build directory: /tmp/easybuild/Subread/2.0.1/GCC-10.2.0): build failed (first 300 chars):
Sanity check failed: sanity check command featureCounts --version exited with code 255
(output: featureCounts: unrecognized option '--version'
...
If you look at the full output in the log file you can see
that the correct option to check the version of the featureCounts
command
is "-v
" rather than "--version
", so we need to fix this in the easyconfig file.
Make the following change in the easyconfig file:
sanity_check_commands = ["featureCounts -v"]
After doing so, you don't have to redo the installation
from scratch, you can use the --module-only
option to only run the
sanity check and generate the module file again:
eb subread.eb --module-only
In the end, you should be able to install Subread 2.0.1 with the GCC 10.2.0 toolchain by fixing the problems with the subread.eb
easyconfig file.
Check your work by manually loading the module and checking the version
via the featureCounts
command, which should look like this:
$ featureCounts -v
featureCounts v2.0.1
next: Module naming schemes - (back to overview page)