1

我一直在构建一个奇点容器来运行一些 python 代码,尽管阅读了奇点文档,但我无法理解错误/行为。

首先,容器是从 docker 引导的 Ubuntu18.04,即:

Bootstrap: docker
From: ubuntu:18.04

我需要使用一个 python 模块(神经元),它需要事先编译等。%post我在定义文件部分编译代码并添加环境变量:

echo 'export PATH=$PATH:/usr/local/nrn/x86_64/bin' >>$SINGULARITY_ENVIRONMENT
echo 'export LD_LIBRARY_PATH=/usr/local/nrn/x86_64/lib:$LD_LIBRARY_PATH' >>$SINGULARITY_ENVIRONMENT

我可以构建容器而没有太多问题(使用sudo singularity build --sandbox)。但是我一直在尝试运行一个测试脚本(test.py)以确保一切都按预期工作。在脚本中,我导入有问题的模块(神经元),然后尝试将列表保存到 csv 以确保可以正确保存数据。所以它看起来像这样:

import neuron #this fails and gives an unusual error in specific circumstances I don't understand (described below)
import numpy as np

some_data = [1,2,3]
np.savetxt('test_results.csv',np.asarray(some_data),delimiter=',') 

根据我在使用时提供的标志,singularity exec我会得到不同的结果,我不明白(或知道从哪里开始理解——这是神经元、奇点还是ubuntu问题?)。

为了完整起见,容器(和 test.py)位于我从中运行这些命令的同一目录中(在我的示例中为 dir)。因此,如果我挂载 $HOME,则不使用该--no-home标志并尝试像这样运行 test.py: singularity exec --writable --bind /home/bidby/path/to/some/dir:/mnt my_container.simg python3 /mnt/test.py

我得到一个像这样的错误:dlopen failed - x86_64/.libs/libnrnmech.so: undefined symbol: celsius我已经尝试过用谷歌搜索,可能是一个 c++ 链接错误(但我只知道 python,所以调试它并不容易)。

但是,如果我使用--no-home标志,即: singularity exec --no-home --writable --bind /home/bidby/path/to/some/dir:/mnt my_container.simg python3 /mnt/test.py

然后模块成功导入并出现新错误:

Traceback (most recent call last):
  File "/mnt/test.py", line 15, in <module>
    np.savetxt('test_results.csv',np.asarray(some_data),delimiter=',')
  File "/usr/local/lib/python3.6/dist-packages/numpy/lib/npyio.py", line 1352, in savetxt
    open(fname, 'wt').close()
PermissionError: [Errno 13] Permission denied: 'test_results.csv'

我已经连续几天在谷歌上搜索这个,但我无法弄清楚问题是什么。根据我所学和测试的内容,我认为这可能与环境变量如何传递到容器中有关,尽管我无权在此处保存的原因超出了我的范围。但我觉得如果我能理解为什么使用--no-home标志会影响模块导入,这可能会得到解决。

这可能无助于解决问题,但我注意到/尝试过的其他事情:

如果我使用该--containall标志,我可以毫无问题地运行 test.py,但是我尝试保存的 csv 文件永远找不到。我检查了文档说:

使用 --containall(或简称 -C)标志,$HOME 不会被挂载,并且会在 $HOME 点创建一个虚拟绑定挂载。您不能使用 -B`(或 --bind)来绑定您的 $HOME 目录,因为它会创建一个空挂载。因此,如果您的文件位于 /home/user 的映像中, --containall 标志会将它们全部隐藏。

我认为这个“虚拟绑定安装”是文件被写入的位置,因此我永远无法真正找到它。

如果我壳到容器中,带有sudo--writable标志,我可以毫无问题地导入神经元。如果我不使用这些标志中的任何一个,那么我会从上面得到相同的“未定义符号”错误。

如果我不导出 LD_LIBRARY_PATH,那么我会得到一个不同的 dlopen 错误,它指的是不同的 .so 文件,说该文件不存在 - 这再次证实了我的想法,即这是一个路径问题。

我知道我没有包含足够的代码来重现这个错误,因为我猜没有人有时间/精力来构建这个容器(因为它相当大),但我认为我已经包含了最相关的部分。如果需要,我们很乐意添加更多内容。

调试这对我来说是一场噩梦,如果有人能指出我应该在谷歌上搜索的正确方向,我将不胜感激。

4

1 回答 1

3

这当然看起来像是一个环境问题,但远程调试比本地调试更难。可以帮助的一件事:使用该--clean-env选项以及--no-home. 这应该使您的容器环境独立于主机环境。这可能会解决您的问题,或者至少指向一个新问题。

您接下来显示的写入错误来自您的测试脚本,您在其中使用了您正在编写的文件的相对路径。通常这意味着它被写入执行脚本的目录。您是否对该目录具有写入权限,或者是否存在具有该名称的现有文件您没有写入权限?

可能不相关,但是:您使用的是什么版本的奇点?.simg在 2.x 文档中使用,而.sif通常用于 3.x。如果您仍在使用 2.x,我强烈建议您更新到最新的 3.x。2.x 不再被开发,大多数 < 2.6.1 的版本都存在安全问题。如果您的集群管理员更新缓慢,指出这一点可以帮助激励他们。

于 2020-07-02T11:20:34.397 回答