RedmineでPlantUML(+Graphviz)を使おうとしてはまった話

RedmineでPlantUMLを使いたいと思い立ち、自分のBitnami Redmine環境にインストールした話です。 なかなかPlantUML(というよりGraphviz)が思い通りに動かずはまりました。 結論を言うと、PlantUMLのPluginを修正してやっと解決しました。

事象

シーケンス図は正常に表示される
Alice -> Bob: Authentication Request
Bob --> Alice: Authentication Response

Alice -> Bob: Another authentication Request
Alice <-- Bob: another authentication Response

f:id:bawbr:20190106094334p:plain

f:id:bawbr:20190106094429p:plain

クラス図はエラーとなる。
Class01 <|-- Class02
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class09 -- Class10

f:id:bawbr:20190106104534p:plain

f:id:bawbr:20190106105620p:plain

原因追求1

表面上の原因は、Graphvizが正常に動作していない。 エラーメッセージの

Warning: Could not load "/usr/lib/graphviz/libgvplugin_pango_so.6" - file not found dot

がヒントだろうと思われた。

原因追求2

シェルから、Graphvizが正常に動作しているかどうかを確かめてみる。

$ plantuml -testdot
The environment variable GRAPHVIZ_DOT has been set to /usr/bin/dot
Dot executable is /usr/bin/dot
Dot version: dot - graphviz version 2.38.0 (20140413.2041)
Installation seems OK. File generation OK

正常にインストールができていることが確認できた。シェルから実行すると、エラーが再現しない。 なお、plantumlの中身は、以下のようになっている。

$ cat /usr/bin/plantuml
#!/bin/bash

/usr/bin/java -Djava.io.tmpdir=/var/tmp -Djava.awt.headless=true -DGRAPHVIZ_DOT=/usr/bin/dot -jar /usr/share/plantuml/plantuml.jar ${@}

原因追求3(原因箇所特定の巻)

Rubyの外部コマンド起動の方法により、Graphvizが正常に起動できるかを確認してみる。

$ ruby -e 'system("/usr/bin/plantuml -testdot")'
The environment variable GRAPHVIZ_DOT has been set to /usr/bin/dot
Dot executable is /usr/bin/dot
Dot version: Warning: Could not load "/usr/lib/graphviz/libgvplugin_pango.so.6" - file not found dot - graphviz version 2.38.0 (20140413.2041)
Error: dot generates empty file. Check you dot installation.

ということで、Rubyから起動したときに、エラーが再現することがわかった。また、redmine の pluginに使われていいるplantumlのスクリプトも確認してみる。

plantuml/plantuml_helper.rb at master · dkd/plantuml · GitHub

      `"#{settings_binary}" -charset UTF-8 -t"#{frmt[:type]}" "#{plantuml_file(name, '.pu')}"`

ここで、

#{settings_binary}

は、plantumlが代入されたもの。つまり、バッククオート形式で、plantumlを呼び出している。シェルから、ruby -eでバッククオート形式で試してみる。

$ ruby -e 'p `/usr/bin/plantuml -testdot`'
"The environment variable GRAPHVIZ_DOT has been set to /usr/bin/dot\nDot executable is /usr/bin/dot\nDot version: Warning: Could not load \"/usr/lib/graphviz/libgvplugin_pango.so.6\" - file not found dot - graphviz version 2.38.0 (20140413.2041)\nError: dot generates empty file. Check you dot installation.\n"

ということで、やはり同じようなエラーとなる。

原因追及4(試行錯誤の巻)

インターネットで調べてみると、環境変数LD_LIBRARY_PATHが外部コマンドplantumlに引き渡されていないことが原因のようなので、plantumlのシェルスクリプトをいろいろといじってみるがうまくいかない。rubyの呼び出し側で何かできないか、ruby側で調べてみる。

原因追及5(解決の巻)

ここでrubyの文法を調査して、環境変数を与えられる外部コマンド起動の方式を確認すると、下記の記法を確認した。

system(env, command, options={}) -> bool | nil

Kernel.#system (Ruby 2.7.0 リファレンスマニュアル)

そこで、バッククオートされている部分を下記に置換した。

system({"LANG"=>"ja_JP.UTF-8","LD_LIBRARY_PATH"=>"/usr/lib/graphviz"},"#{settings_binary} -charset UTF-8 -t#{frmt[:type]} #{plantuml_file(name, '.pu')}")

すると、クラス図が、正常に表示されるようになった。

f:id:bawbr:20190106184333p:plain

自分の環境

Redmine

Environment: Redmine version 3.4.5.stable Ruby version 2.3.7-p456 (2018-03-28) [x86_64-linux] Rails version 4.2.8 Environment production Database adapter Mysql2 SCM: Subversion 1.10.0 Cvs 1.12.13 Git 2.17.1 Filesystem
Redmine plugins: graphviz 0.2.3 mega_calendar 1.7.0 pdf_export_redmine 0.0.2 plantuml 0.5.1

Java

openjdk version "1.8.0_191" OpenJDK Runtime Environment (build 1.8.0_191-8u191-b12-0ubuntu0.16.04.1-b12) OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)

Dot

dot - graphviz version 2.38.0 (20140413.2041)