遺伝研スパコンで Singularity を使う際のトラブルシュートあれこれ


このページの内容は古くなっています。

単に最新版のBUSCO (2023.3現在 5.4.6)を実行するだけであれば
```
singularity exec /usr/local/biotools/b/busco:5.4.6--pyhdfd78af_0 busco -m genome -i $GENOME -o OUTPUT -l embryophyta_odb10
```
で実行可能です。

singularity実行時の環境変数の指定やトラブルシュート法について知りたい方は以下をお読みいただくと何かしら手がかりは見つかるかもしれません。
(情報が古くなっている可能性がありますのでご注意ください)


---

# はじめに
以前に書いた[遺伝研スパコンにおける Singularity の使い方](https://qiita.com/nigyta/items/8de4412e590dad7bf2f8)のより実践的なトラブルシュートの例として、BUSCO というツールを使えるようにするまでの過程を記録します。

[BUSCO](https://busco.ezlab.org) はゲノムや予測された遺伝子セットの完全性を評価するツールです。依存ツールが多く手動でインストールすると結構苦労するので Anaconda/Miniconda を使ってインストールすることをおすすめします。また、Docker が使える環境であれば公式のコンテナイメージも配布されています。
しかし、遺伝研スパコンでは Docker が使えないことと、個人的な事情から conda が使えない/使いたくなかったので遺伝研スパコンに用意されている Singularity 版 BUSCO を使用することにしました。

したがって、単に BUSCO を使いたいという人は、conda コマンドを使ってインストールしてしまえば幸せになれます。


```
$ conda install -c bioconda -c conda-forge busco
```

手っ取り早く Singularity 版 BUSCO を動かしたいという人は途中をすっ飛ばして、~~一番最後の__最終的な実行スクリプト__~~下記の__[2021/11/11追記]__の部分をご参照ください。
また、将来コンテナイメージが更新されたりスパコンの実行環境が変わった場合には、ここで書いている通りに動かなくなる可能性があることをご了承ください。

__<font color="red">[2021/11/11追記]</font>__
執筆時点からスパコンに用意されているBUSCOのsingularityイメージが更新されたので、単にBUSCOを使うなら

```
singularity exec --no-mount tmp /usr/local/biotools/b/busco:4.1.4--py_2 busco --mode genome -l eukaryota_odb10 -i $FASTA -o $OUTDIR
```
で実行できます。以下の内容はBUSCOを動かす目的では不要ですが、singularity実行時のトラブルシュートの参考にはなるかもしれません。

<hr>


# 1. とりあえず起動してみる

遺伝研スパコンでは`/usr/local/biotools/`以下に各種生命科学用ツールの Singularity コンテナイメージが格納されている。これらは Biocontainers が提供している Docker イメージを Singularity イメージに変換したものである。
下記コマンドで BUSCO を起動し、ヘルプの表示を試みる。

```
$ singularity exec /usr/local/biotools/b/busco:4.0.2--pyr36_0 busco -h
WARNING: Skipping mount /opt/pkg/singularity/3.5.2/var/singularity/mnt/session/etc/resolv.conf [files]: /etc/resolv.conf doesn't exist in container
Segmentation fault
```

いきなり出鼻をくじかれてしまった。メモリ不足が疑われたので、qlogin 時に要求するメモリを増やしてみる。

```
$ qlogin -l mem_req=16G,s_vmem=16G
```

その後、再び実行。

```
$ singularity exec /usr/local/biotools/b/busco:4.0.2--pyr36_0 busco -h
WARNING: Skipping mount /opt/pkg/singularity/3.5.2/var/singularity/mnt/session/etc/resolv.conf [files]: /etc/resolv.conf doesn't exist in container
usage: busco -i [SEQUENCE_FILE] -l [LINEAGE] -o [OUTPUT_NAME] -m [MODE] [OTHER OPTIONS]
(以下省略)
```

無事にヘルプが表示されたので、まずは第一段階クリア。（警告が出ているが、今のところは無視。この警告は遺伝研スパコンで Singularity を使っていると良く出てくるが、ほとんどのケースでは問題なく動作する）

# 2. コンテナの中を探る

次に、`--list-datasets`オプションを使って BUSCO が利用できる参照データの一覧を表示させてみる。

```
$ singularity exec /usr/local/biotools/b/busco:4.0.2--pyr36_0 busco --list-datasets 
WARNING: Skipping mount /opt/pkg/singularity/3.5.2/var/singularity/mnt/session/etc/resolv.conf [files]: /etc/resolv.conf doesn't exist in container
ERROR:	The config file is necessary here as it contains remote and local path locations for downloading dataset information
ERROR:	Please specify a BUSCO config file using either (i) an environment variable by entering 'export BUSCO_CONFIG_FILE=/path/to/config.ini' or (ii) using the command line flag --config /path/to/config.ini
```
エラー。どうやらコンフィグファイルのパスを実行時のオプションか環境変数で指定する必要があるようだ。そこで、コンフィグファイルがどこにあるのかコンテナ内に入って探すことにする。

```
$ singularity shell /usr/local/biotools/b/busco:4.0.2--pyr36_0
または、
$ singularity exec /usr/local/biotools/b/busco:4.0.2--pyr36_0 bash
```

でコンテナ内に入ることができるので、`/usr/local`以下などの怪しそうな場所を探索してみる。また、コンテナイメージは Bioconda のレシピをもとに生成されたものであるから、[レシピファイル](https://github.com/bioconda/bioconda-recipes/blob/master/recipes/busco/build.sh)を参考にすると目的のファイルがどこにあるかを知る手がかりになる。レシピファイルは Bioconda の[公式ページ](https://bioconda.github.io)でツール名で検索すれば見つけることができる。

結果、`/usr/local/config/config.ini` にコンフィグファイルが存在することが分かった。

__[TIPS]__

  - singularity shell コンテナ名 でコンテナ内に入れる
  - Biocondaのレシピファイルを見ると問題解決の手助けになる


# 3. 環境変数の指定

コンフィグファイルが見つかったので、オプションで指定して実行してみる。

```
$ singularity exec /usr/local/biotools/b/busco:4.0.2--pyr36_0 busco --list-datasets --config /usr/local/config/config.ini 
```
が、エラーは解決せず（理由は不明）。

そこで、環境変数を指定する方法で試してみる。

```
$ export BUSCO_CONFIG_FILE=/usr/local/config/config.ini
$ singularity exec /usr/local/biotools/b/busco:4.0.2--pyr36_0 busco --list-datasets
WARNING: Skipping mount /opt/pkg/singularity/3.5.2/var/singularity/mnt/session/etc/resolv.conf [files]: /etc/resolv.conf doesn't exist in container
INFO:	Downloading information on latest versions of BUSCO data...
```
となって、無事にエラーは解決された。
しかし、画面には最新のデータをダウンロードしているように表示されているものの、すぐに終了してしまってデータが得られていない。これの解決方法は次項に続く。

__[TIPS]__

  - ホスト側で設定した環境変数はコンテナ内にも引き継がれる
  - （ただし、`PATH` など一部の環境変数は引き継がれない）

# 4. ネットワークへの接続を行う


前項でデータがダウンロードできなかった原因は起動時に表示されている警告にヒントがあった。`/etc/resolv.conf`には DNS への参照情報が記載されているが、これがコンテナ内に存在しなかったために、インターネットへの接続ができなかったのが原因であった。

念の為 curl で確認してみると、

```
$ singularity exec /usr/local/biotools/b/busco:4.0.2--pyr36_0 curl http://example.com
WARNING: Skipping mount /opt/pkg/singularity/3.5.2/var/singularity/mnt/session/etc/resolv.conf [files]: /etc/resolv.conf doesn't exist in container
curl: (6) Could not resolve host: example.com
```

やはりネットワークへ接続ができていない。
そこで、`/etc/resolv.conf`がコンテナ内から参照できるようにしてみる。
ちょっと乱暴だけどホスト側の `/etc` を丸ごとマウントする*。

```
$ singularity exec -B /etc:/etc /usr/local/biotools/b/busco:4.0.2--pyr36_0 busco --list-datasets 
```
結果、busco_downloadsというディレクトリができて、参照データのダウンロードもできた。なお、ホスト側とコンテナ側とで同じ場所にディレクトリをマウントする場合は、`-B /etc`というような指定でも良い。

\* 本当は`-B /etc/resolv.conf:/etc/resolv.conf`というように目的のファイルだけをマウントしたかったが出来なかった。コンテナ側の`/etc`を丸ごと置き換えてしまった形になったが、プログラムの動作に必要なファイルが`/etc`に置かれていたら動かなかったかもしれない。
__その後、より安全な方法をご指摘いただいたので追記__
コンテナ内の `/etc/resolv.conf`は`/tmp/resolv.conf`へのシンボリックリンクになっている。そのため、ホスト側であらかじめ`/tmp/にresolv.conf`を配置しておき、`/tmp`をマウントするようにすれば良い。すなわち、

```
$ cp /etc/resolv.conf /tmp/
$ singularity exec -B /tmp /usr/local/biotools/b/busco:4.0.2--pyr36_0 curl http://example.com
```
で動作する。`/tmp/`にコピーした場合はログアウトすると消えてしまうので、カレントディレクトリに `tmp` ディレクトリを作成し、その中にコピーしてもよい。（その場合、`-B $PWD/tmp:/tmp` とする）

__[TIPS]__

* /etc/resolv.confの問題でネットワークへの接続ができないときは`-B /etc`をつける
* より良い方法は、あらかじめ/tmp/にresolv.confを配置しておき、/tmpをマウントするようにする（`-B /tmp`）

__<font color="red">[2021/11/11追記]</font>__

上記の手順を踏むよりも`--no-mount tmp`を指定すればネットワークに接続できますので、下記のようにすることをお勧めします。

```
singularity exec --no-mount tmp <コンテナイメージファイル> <コマンド> (以下省略)
```


# 5. いよいよ実行

バクテリアのゲノムデータを入力ファイルに使って実行。

```
$ singularity exec -B /etc /usr/local/biotools/b/busco:4.0.2--pyr36_0 busco -m genome -i genome.fa -o busco_out -l bacteria_odb10 
```
バクテリア用の参照データ（bacteria_odb10）が自動的にダウンロードされ、無事に BUSCO が実行できた。同じ参照データを使って再度実行する際にはネットワークへの接続が不要なので`-B /etc`を省いて実行可能。

次に、真核生物ゲノムを用いて実行テスト

```
$ singularity exec -B /etc /usr/local/biotools/b/busco:4.0.2--pyr36_0 busco -m genome -i genome_euk.fa -o busco_euk_out -l eukaryota_odb10 -f
WARNING: Skipping mount /etc/localtime [binds]: /etc/localtime doesn't exist in container
(中略)
ERROR:	The environment variable AUGUSTUS_CONFIG_PATH is not set
ERROR:	BUSCO analysis failed !
ERROR:	Check the logs, read the user guide, and check the BUSCO issue board on https://gitlab.com/ezlab/busco/issues
```

真核生物のゲノムの場合、遺伝子の予測に Augustus を使っている。その設定ファイルへの場所を環境変数`AUGUSTUS_CONFIG_PATH`に指定する必要があるようだ。
BUSCOのコンフィグファイルを環境変数で指定したのと同様に設定を行う。Augustusの設定ファイルは/usr/local/configディレクトリに存在しているので、

```
$ export AUGUSTUS_CONFIG_PATH=/usr/local/config
```

で環境変数を設定したのち、再度実行。しかし、今度は、

```
ERROR:	Cannot write to Augustus species folder, please make sure you have write permissions to /usr/local/config/species
```

ということで、ディレクトリへの書き込み権限がないと怒られてしまった。

# 6. コンテナ内から必要なファイルをコピー
前述のようにコンテナ内のディレクトリへの書き込み権限が問題でエラーが生じるケースは少なくない。そのような場合に、
1. コンテナ内からディレクトリをホームディレクトリにコピー
2. コピーしたディレクトリを、実行時に参照できるようにする
という手順で解決できることができる。

まずは、コンテナ内の`/usr/local/config`を`busco_config`という名称でカレントディレクトリにコピーする。

```
$ singularity exec /usr/local/biotools/b/busco:4.0.2--pyr36_0 cp -r /usr/local/config ./busco_config
```

ついで、コピーしたディレクトリを環境変数で指定して実行する。

```
$ export AUGUSTUS_CONFIG_PATH=$PWD/busco_config
$ singularity exec -B /etc /usr/local/biotools/b/busco:4.0.2--pyr36_0 busco -m genome -i genome_euk.fa -o busco_out -l eukaryota_odb10 -f
```

この時、自分のホームディレクトリはコンテナ実行時に自動でマウントされるため、明示的にマウントする必要はない。

これで動くかと思われたがまたしても別のエラー。

```
subprocess.CalledProcessError: Command '['/usr/local/bin/tblastn', '-version']' returned non-zero exit status 127.
```
どうやら tblastn の実行ができないらしい。

__[TIPS]__

- コンテナ内のファイル・ディレクトリへの書き込み権限が必要な場合、いったんそれらをホームディレクトリにコピーしてから環境変数や実行時オプションなどで参照できるようにすれば動くことがある

# 7. コンテナへのライブラリの追加

状況を把握するため、コンテナ内の tbastn を単独で実行してみる。

```
$ singularity exec /usr/local/biotools/b/busco:4.0.2--pyr36_0 /usr/local/bin/tblastn
(中略)
/usr/local/bin/tblastn: error while loading shared libraries: libbz2.so.1: cannot open shared object file: No such file or directory
```

ライブラリが足りていないのがエラーの原因のようだ。

(コンテナ内に入って調べたところ /usr/local/lib/ に libbz2.so.1.0 は存在しているがlibbz2.so.1 が存在していなかったのが原因と考えられる。書き込み権限があればシンボリックリンクを作るなどで簡単に対処できそうだが、残念ながらコンテナ内のファイルに対してはそれができない。）

将来コンテナが更新された際にはライブラリ不足は修正される可能性もあるが、足りないライブラリをホスト側から追加してエラーを回避することもできる。
それには、環境変数`SINGULARITY_CONTAINLIBS`に追加したいライブラリを（複数あればカンマ区切りで）記述すればよい。

```
$ export SINGULARITY_CONTAINLIBS=/lib64/libbz2.so.1
$ singularity exec -B /etc /usr/local/biotools/b/busco:4.0.2--pyr36_0 /usr/local/bin/tblastn
```

ここではホスト側にあった`/lib64/libbz2.so.1`を追加することで無事に tblastn を起動することができた。

__[補足]__
環境変数 `SINGULARITY_CONTAINLIBS` で指定したライブラリはコンテナ内の  `/.singularity.d/libs` にコピーされる。このディレクトリは環境変数` LD_LIBRARY_PATH` に含まれているため、tblastn 実行時にライブラリが参照できるようになっている。

__[TIPS]__

- ライブラリがなく実行できない場合には SINGULARITY_CONTAINLIBS で追加することができる。


# 8. 最終的な実行スクリプト

このような過程を経て出来上がったのが下記のスクリプト。
最初の方では BUSCO のコンフィグファイルのパスを環境変数 BUSCO_CONFIG_FILE で指定したが、その後の手順でコンフィグファイル一式を含んだディレクトリをコンテナ内からホームディレクトリにコピーしたので、実行時オプション --config で指定する方法に変えている。

```
#$ -S /bin/bash
#$ -cwd
#$ -l mem_req=25G,s_vmem=25G

GENOME=/home/xxxxx/path/to/mygenome.fa
OUTDIR=busco_result

# コンテナ内から resolv.conf が参照できるように /tmp にコピーしておく
# 注）コンテナ内では /etc/resolv.conf は /tmp/resolv.conf へのリンクになっている
cp /etc/resolv.conf /tmp/

# BUSCO実行前にコンテナ内からBUSCO・Augustusの設定ファイルを含んだディレクトリをコピーしておく
# 一度コピーした後は、再実行する必要はない
# busco_config/config.ini は必要に応じて編集してもよいが、そのままでも動く
singularity exec /usr/local/biotools/b/busco:4.0.2--pyr36_0 cp -r /usr/local/config ./busco_config

# 環境変数 AUGUSTUS_CONFIG_PATH に先にコピーしておいたディレクトリを指定する
export AUGUSTUS_CONFIG_PATH=$PWD/busco_config

# Buscoが内部的に利用する tblastn の実行に libbz2.so.1 が不足しているので、ホスト側のライブラリを利用できるようにする
export SINGULARITY_CONTAINLIBS=/lib64/libbz2.so.1

# コンテナ内から resolv.conf が参照できるようにホスト側の /tmp をマウントする。
# resolv.conf は参照データのダウンロード時に必要なので、一度取得してしまったら以後は -B /tmp はなくても動作する。
# BUSCOの設定ファイルは --config busco_config/config.ini で指定する。（環境変数 BUSCO_CONFIG_FILE で指定することも可能）
singularity exec -B /tmp /usr/local/biotools/b/busco:4.0.2--pyr36_0 busco --config busco_config/config.ini -m genome -i $GENOME -o $OUTDIR -l eukaryota_odb10
```