📄

サーバー上でlibreofficeを使ったpdf変換を高速化する勘所

2022/02/17に公開

最初に

調査過程などが長いので、結論だけ先に書いておきます。
結論だけみれば恐らく十分。

検証Libreバージョン: LibreOffice 7.0.6.2 144abb84a525d8e30c9dbbefa69cbbf2d8d4ae3b

結論

  • libreofficeをdaemonとして、事前に動かしておく
  • 事前起動や印刷コマンドでは -env:UserInstallation を同じ値に設定するか、使用しない
# 常駐起動。systemdなどを使用してバックグラウンドで動作させておく
# systemd のサービスファイルは最後付近のセクションを参考にする。
soffice --quickstart
soffice --headless --convert-to pdf --outdir 出力ディレクトリ 変換元ファイルパス

概要

みなさん、pdf出力していますか?
libreofficeのpdf変換が便利ですよね。

ローカルで利用する分には困らないのですが、サーバー内でサービスに組み込む際は問題があります。
1 ods(xlsx)ファイルをpdfに変換するとき、3-5秒程度かかります。
pdf出力で3-5秒もかかると、Webサービスの1機能に組み込みづらいですよね。おそすぎです。

プロセスを見ていると、1コマンドで soffice プロセスが立ち上がり、変換が終わると soffice プロセスが終了します。普通ですね。

実は、 soffice コマンドは引数を複数渡すと1回の実行で100ファイル以上をpdfへ変換できます。
1コマンドで100ファイルを変換しても、1コマンドで1ファイルの100倍の時間がかかるわけではありません。長くて10倍程度です。このことから、私は soffice の起動コストが高いと判断しました。

「常駐起動しておけば、高速で soffice を使った変換ができるかも...?」

検索しても情報がない

英語サイトを検索しました。
daemon化の記事はいくつか引っかかるのですが、期待した動作の回答は見つかりませんでした。
(常駐起動して、Javaでlibreの機能を使う系の記事はありました)

「違う。そうじゃない。私は常駐daemonとコマンド実行の組み合わせで実行したいんだ。」

ひらめきと気付き

事前に

soffice

を実行すると、常駐のような状態になりました。
このタブを tab_A とします。

別タブで変換コマンドを実行すると、0.5秒程度で変換完了しました。
爆速化してる。ヨシ!

...惜しいことに、 tab_A の処理は終了してしまい、常駐できていませんでした。

終了しないで常駐するオプションもあると思い、片っ端からオプションを試して見つけました。

soffice --quickstart

です。

解決策

事前にlibreofficeを常駐起動

常駐起動します。systemdであれば、以下のようになります。

[Unit]
Description=Soffice Server
After=network.target

[Service]
Type=simple
User=実行ユーザー

ExecStart=/usr/bin/soffice --quickstart

TimeoutSec=300
Restart=always

[Install]
WantedBy=multi-user.target
sudo systemctl enable soffice.service
sudo systemctl start soffice.service

のように起動しておきましょう。

印刷コマンド

RubyやPHPなどでコマンドを実行して変換しましょう。

soffice --headless --convert-to pdf --outdir 出力ディレクトリ 変換元ファイルパス

注意点

Rubyには、LibreOfficeの変換用ラッパーライブラリ libreconvがあります。
これを使用すると、常駐のlibreofficeは使用されず新しく soffice のプロセスが作られてしまい高速化できません。 -env:UserInstallation の指定が原因で毎度新しいlibreインスタンスが作成されます。

そのため、直でコマンドで扱う必要があります。(少し古いlibreconvであれば、 -env:UserInstallation が実装されていないバージョンがあるかも)
ほかライブラリからlibreのpdf変換を使う場合も、上記を気をつけましょう。

また、 -env:UserInstallation の指定がない or 同じことで、同時に変換処理ができなくなるので注意が必要です。(CPUの多コアが活かせない、大量リクエストが来たときにタイムアウトするなど)

おわりに

みんな同じことで困っている人いるはず。このノウハウほとんど記事になっていないようなので、どんどん広まって欲しい。libreofficeは便利。

Discussion