WSL2のUbuntuにpdftkをインストールするためのsnapのためにsystemdを起動する(必要はない)
TL;DR
WSL2のUbuntu (18.10以降)でPDFtkを使うためには、以下のようにすれば良い。
sudo apt install -y pdftk-java
WSL2のUbuntuでPDFtkを使いたい
PDFを切り出したり、複数のPDFをくっつけたりしたいことが結構あります。そんな用途に便利なツールがPDFtkです。しかし、PDFtkはGCJ (GNU Compile for Java)に依存しており、GCC 7.1からGCJが消えてしまったため、aptで素直に入らなくなりました。
そのworkaroundとして、以下のやり方が有名です。
sudo apt-get update && sudo apt-get install -yqq daemonize dbus-user-session fontconfig
sudo daemonize /usr/bin/unshare --fork --pid --mount-proc /lib/systemd/systemd --system-unit=basic.target
exec sudo nsenter -t $(pidof systemd) -a su - $LOGNAME
sudo snap install pdftk
これは、
- WSL2のUbuntuではデフォルトで起動していないsystemdをdaemonizeを使って簡易コンテナで起動し、
- nsenterを使ってそのコンテナにログインすると、
- snapdに接続できるようになるので
- snapが使えてpdftkがインストールできる
という仕組みになっています。
Ubuntu 18.04まではPDFtkを使うには上記のようなことをするとかGCJをなんとかするとか面倒なことが必要だったのですが、18.10以降からはpdftk-javaというforkがあるので、それをインストールすればpdftk
が問題なく使えます。
で、上記の仕組みを散々調べた後に、Ubuntu 18.10 以降はpdftk-java
を使えば解決、ということを自分のツィートで知ったので膝から崩れ落ちました。悲しいので、調べたことをまとめておきます。
systemd on WSL2
pdftkを入れる方法として、Snappy経由で入れる、という方法があります。Snappyはパッケージ管理システムの一種で、ディストリビューションに依存せずにソフトウェアを管理、インストールできます。しかし、パッケージマネージャsnapを使うには、snapdというデーモンが動いている必要があります。
snapdはsystemd上で動きますが、WSL2のUbuntuでは、デフォルトでsystemdが動いていません。代わりにプロセスIDの1番としてinit
が動いています。
$ ps -p 1 -o comm=
init
そこで、まずはなんとかしてsystemdを起動する必要があります。そのためのコマンドが以下です。
sudo daemonize /usr/bin/unshare --fork --pid --mount-proc /lib/systemd/systemd --system-unit=basic.target
詳細はこちらの記事を読んでいただくことにして、これによりsystemdを別の名前空間で起動することができました。
$ pidof systemd
5229
systemdがプロセスIDの5229番として起動しています。これにより、snapdも起動します。
$ pidof snapd
5518
$ systemctl status snapd
● snapd.service - Snap Daemon
Loaded: loaded (/lib/systemd/system/snapd.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2021-09-09 21:17:30 JST; 1min 2s ago
TriggeredBy: ● snapd.socket
Main PID: 279
Tasks: 25 (limit: 7529)
Memory: 90.8M
CGroup: /system.slice/snapd.service
└─279 /usr/lib/snapd/snapd
(snip)
しかし、systemdが別の名前空間で動いているので、snapdと通信はできません。
$ snap version
snap 2.49.2+20.04
snapd unavailable
series -
snapdがunavailableになっていますね。
そのために、nsenterコマンドで、先ほど作ったコンテナの中にログインします。
exec sudo nsenter --target $(pidof systemd) --all su - $LOGNAME
これにより、systemd
がプロセスIDとして1番を持つ世界に入れます。
$ pidof systemd
584 1
systemdのPIDとして584番と1番が割り当てられています。
これでsnapdとやりとりできるようになりました。
$ snap version
snap 2.51.4
snapd 2.51.4
series 16
ubuntu 20.04
kernel 4.19.128-microsoft-standard
これによりsnap経由でpdftkがインストールできます。
sudo snap install pdftk
$ pdftk --version
pdftk 2.02 a Handy Tool for Manipulating PDF Documents
Copyright (c) 2003-13 Steward and Lee, LLC - Please Visit: www.pdftk.com
This is free software; see the source code for copying conditions. There is
NO warranty, not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
無事に入りました。
トラブルシューティング
一度WSL2を終了すると簡易コンテナからも抜けているので、snapが使えません。
$ snap version
snap 2.49.2+20.04
snapd unavailable
series -
それならまた簡易コンテナに入ろうと
exec sudo nsenter --target $(pidof systemd) --all su - $LOGNAME
を実行しようとするとターミナルが落ちます。その理由は、systemdが二つのPIDを持っているからです。先ほど、systemdのPIDは以下の二つでした。
$ pidof systemd
584 1
この状態でWSL2を閉じて、もう一度開くと、別のPIDになります。
$ pidof systemd
5991 5229
pidof systemd
が値を二つ持っているので、$(pidof systemd)
がおかしくなって、nsenter
が正しく動作しません。
killで殺しても良いですが、なんか気持ち悪いので、PowerShellから
wsl --shutdown
で一度全プロセスをきれいにするのが良いと思います。
まとめ
WSL2のUbuntuでpdftkを使うためにsnapを使うためにsystemdを起動したりなんだりしましたが、Ubuntu 18.10以降はpdftk-java
を使えば一発です。Ubuntu 20.04はsudo apt install pdftk
でも入りますが、多分pdftk-java
と同じものです。
$ sudo apt install pdftk
$ pdftk --version
pdftk port to java 3.0.9 a Handy Tool for Manipulating PDF Documents
Copyright (c) 2017-2018 Marc Vinyals - https://gitlab.com/pdftk-java/pdftk
Copyright (c) 2003-2013 Steward and Lee, LLC.
pdftk includes a modified version of the iText library.
Copyright (c) 1999-2009 Bruno Lowagie, Paulo Soares, et al.
This is free software; see the source code for copying conditions. There is
NO warranty, not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
もうWSL2のUbuntuでpdftkを使いたい人が面倒な思いをしないように本記事を埋葬しておきます。
Discussion