Raspberry Pi 4 の CentOS Stream 8 に eog をインストールしてみた 

## はじめに
画像ファイルを表示してくれる `eog` コマンドの導入について、色々と探し回り沼ったのでまとめてみました。また `eog` コマンド実行時に表示されるエラーについても、その内容と対応策をまとめました。

## 環境
* Raspberry Pi 4 Model B
    * CentOS Stream 8

## eog のインストール方法
基本的には以下のように `dnf` コマンドを使ってインストールすればいいのですが、CentOS Stream 8 の公式リポジトリには、CPU アーキテクチャが x86_64 に対応した `eog` しかありません。そして、Raspberry Pi 4 の CPU アーキテクチャは aarch64 であるため以下の方法ではインストールできません（アーキテクチャの違いに気づかずインストールに沼りました）。
```console
[root@localhost ~]# dnf install eog
```
そのため aarch64 に対応した rpm ファイルを探す必要があります。rpm ファイルとは Red Hat 系の Linux で用いられるソフトウェアのパッケージを管理するファイルです（Debian や Ubuntu では deb ファイル）。探し方としては "eog el8 aarch64 rpm" のようにググるといいでしょう。"el" とは Red Hat **E**nterprise **L**inux の略称で、数字と合わせて以下の OS のことを指します。
* el8：CentOS 8, RHEL 8, Rocky Linux 8, AlmaLinux 8
* el9：CentOS 9, RHEL 9, Rocky Linux 9, AlmaLinux 9

基本的に rpm ファイルには OS を識別するために、それぞれ OS に固有のコードが含まれています（例えば、Fedora 37 では "fc37"、Amazon Linux2 では "amzn2" など）。OS に固有のコードを手っ取り早く把握するためには、<a href="https://pkgs.org">pkgs.org</a> というサイトを使うといいでしょう（パッケージをインストールしたい時によくお世話になります）。試しに "eog" と検索してみて下さい。自分が使ってる OS のタブを開くことで OS 固有のコードが分かると思います（中には固有のコードがないものもあります。その場合は検索が厄介かもしれませんね…）。
さて、本題に戻り "eog el8 aarch64 rpm" のようにググった結果、Rocky Linux 8 向けの rpm ファイルが見つかりました。Rocky Linux と CentOS Stream には、OS による違いはほとんどなく、互換性を保った利用が可能です（厳密には CentOS Stream は RHEL のアップストリームであるのに対し、Rocky Linux はダウンストリームなので違いはあると思いますが、ここではほぼ同じような OS ということにします）。それでは、`eog` をインストールしてみましょう。見つけた<a href="https://rockylinux.pkgs.org/8/rockylinux-devel-aarch64/eog-3.28.4-1.el8.aarch64.rpm.html">サイト</a>より rpm ファイルの URL をコピーします。今回の場合（pkgs.org）は `Download` より `Binary Package` の URL をコピーします。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1115291/7c110478-539e-4617-918a-c487c4403415.png)
以下のようなページの場合もありますが、同様に rpm ファイルの URL を右クリックからコピーして下さい。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1115291/ea9ad363-5ae8-b85a-71ef-7663d47dc381.png)
そして、root 権限で以下のコマンドを実行します。
```console:install
[root@localhost ~]# wget コピーした URL
[root@localhost ~]# rpm -Uvh ダウンロードした rpm ファイル
warning: eog-3.28.4-1.el8.aarch64.rpm: Header V4 RSA/SHA256 Signature, key ID 6d745a60: NOKEY
Verifying...                          ################################# [100%]
Preparing...                          ################################# [100%]
Updating / installing...
   1:eog-3.28.4-1.el8                 ################################# [100%]
/sbin/ldconfig: /usr/lib64/llvm14/lib/libclang.so.13 is not a symbolic link
```
このとき警告が出ていますが、rpm パッケージに署名がされていないというだけなので無視して問題ありません。依存パッケージのインストールがされていない場合、以下のようにエラーが吐かれることがあります。
```console:install error
[root@localhost ~]# rpm -Uvh eog-3.28.4-1.el8.aarch64.rpm 
warning: eog-3.28.4-1.el8.aarch64.rpm: Header V4 RSA/SHA256 Signature, key ID 6d745a60: NOKEY
error: Failed dependencies:
        gsettings-desktop-schemas is needed by eog-3.28.4-1.el8.aarch64
        gtk3(aarch-64) >= 3.22.0 is needed by eog-3.28.4-1.el8.aarch64
        libX11.so.6()(64bit) is needed by eog-3.28.4-1.el8.aarch64
        libcairo.so.2()(64bit) is needed by eog-3.28.4-1.el8.aarch64
        libexempi.so.3()(64bit) is needed by eog-3.28.4-1.el8.aarch64
        libexif.so.12()(64bit) is needed by eog-3.28.4-1.el8.aarch64
        libgdk-3.so.0()(64bit) is needed by eog-3.28.4-1.el8.aarch64
        libgdk_pixbuf-2.0.so.0()(64bit) is needed by eog-3.28.4-1.el8.aarch64
        libgnome-desktop-3.so.17()(64bit) is needed by eog-3.28.4-1.el8.aarch64
        libgtk-3.so.0()(64bit) is needed by eog-3.28.4-1.el8.aarch64
        libjpeg.so.62()(64bit) is needed by eog-3.28.4-1.el8.aarch64
        libjpeg.so.62(LIBJPEG_6.2)(64bit) is needed by eog-3.28.4-1.el8.aarch64
        liblcms2.so.2()(64bit) is needed by eog-3.28.4-1.el8.aarch64
        libpeas-1.0.so.0()(64bit) is needed by eog-3.28.4-1.el8.aarch64
        libpeas-gtk-1.0.so.0()(64bit) is needed by eog-3.28.4-1.el8.aarch64
        librsvg-2.so.2()(64bit) is needed by eog-3.28.4-1.el8.aarch
```
以下のようにパッケージを入れ直して再度インストールして下さい。
```console
[root@localhost ~]# dnf -y install gsettings-desktop-schemas-devel gtk3-devel exempi libexif gnome-desktop3 libpeas-gtk librsvg2-devel
```

## eog の使い方
ssh 経由でサーバにアクセスしている場合、画像を表示させるためには X Window System を導入する必要があります。これを導入することで、利用しているパソコンに GUI を転送させることが可能になります。Xサーバの導入については以下の記事を参考にして下さい。

<a href="https://rin-ka.net/windows-x-server/">VcXsrv（Xサーバー）をWindowsにインストールしLinuxのGUIをリモート操作する設定方法</a>

さて、Xサーバを導入することができたら実際に `eog` コマンドを使って画像を表示してみましょう。使い方は以下の通りです。

```console
[guest@localhost ~]$ eog sample-01.png
```
![スクリーンショット 2023-01-30 18.28.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1115291/12877504-d062-01a0-e241-1f7df5c83a8a.png)
画像が表示できていれば成功です。しかし、コンソール上でエラーが発生してしまう場合があります。エラー内容とその対処法について以下でまとめてみました。

## エラー内容とその対処法
### ディスプレイに接続できないことによるエラー
`Unable to init server: Could not connect: Connection refused`
`Gtk-WARNING **: 21:23:03.325: cannot open display:`
Xサーバの設定が正しく行われていないことによるエラーです。解決策として `~/.bashrc` に以下を追加して下さい。`.bashrc` を変更したあとに `source ~/.bashrc` とコマンドを実行するのを忘れないようにしましょう。
```bash:.bashrc
# GUIを表示させたいPCのIPアドレスに置き換えて下さい
export DISPLAY=10.7.74.102:0.0
```
正しく設定をしているのにエラーが吐かれ続けたことがありました。セッションを立ち上げ直したところ治りましたが、再現性がなかったため原因が特定できませんでした。

### アクセス権がないことによるエラー
`dconf-CRITICAL **: 22:39:11.394: unable to create file '/run/user/1000/dconf/user': Permission denied.  dconf will not work properly.`
権限が無くて `/run/user/1000/dconf/user` にアクセスできないというエラーになります。このエラーが発生する原因として `su` コマンドが関係しています。例えば以下のようなことをするとこのエラーが発生します。
1. userID=1000 のユーザに ssh でログイン
2. `su` コマンドを実行
3. root 状態で `eog` コマンドを実行

原因としては `su` コマンドを実行する時に、引数として "-"（-l と --login でも同様）を指定していないからになります。"-" を指定するか指定しないかの違いは、現在のセッションの環境変数を引き継ぐかどうかになります。"-" を指定した場合、現在のセッションの環境変数を全てリセットした上で、引数に指定したユーザの環境変数を持ったセッションを起動します（引数にユーザを指定しない場合 root で起動されます）。"-" を指定しない場合、元のユーザの環境変数が引き継がれます。この**環境変数が引き継がれる**というのがエラーの直接的な原因になります。
上記の例の流れを見てみましょう。2番目で `su` コマンドを実行すると、userID=1000 が引き継がれます。そして、3番目で root が `eog` コマンドを実行すると `/run/user/1000/dconf/user` にアクセスし、root 権限でファイルを上書きしてしまいます。その結果、 `/run/user/1000/dconf/user` の所有者が root になってしまい、userID=1000 のユーザで `eog` コマンドを実行するとアクセス権がないというエラーが吐かれることになります。
また、2番目で `su guest` とした場合でも、同じ問題が起こります。guest の userID が 1002 だとしたら、`eog` コマンドでアクセスすべきは `/run/user/1002/dconf/user` です。ところが、`su` コマンドで環境変数が引き継がれているため `/run/user/1000/dconf/user` にアクセスしようとしてアクセス拒否されるというわけです。
対応策としては、`su` コマンドを実行した上で `eog` コマンド（`evince` や `gedit` などの GUI を開くコマンドでも同様です）を実行しないことになります。間違えて実行してしまった場合は、以下のように `/run/user/1000/dconf/user` の所有者を変更して下さい。
```console:所有権の変更
[root@localhost ~]# chown 1000:1000 /run/user/1000/dconf/user
```
このようなエラーを起こさないためにも、`su` コマンドを実行するときは引数に "-"（-l と --login でも同様）を指定するのがいいでしょう。`su` のマニュアルでも、環境変数の混合による影響を防ぐために、引数を指定することが推奨されています（私はこのことを知らずに、引数なしで `su` コマンドを長年実行していました。特に問題なくサーバの運用ができていたため、気づきませんでした。反省）。

>It is recommended to always use the --login option (instead of its shortcut -) to avoid side effects caused by mixing environments.

### dbus 関連のエラー1
`GLib-GIO-CRITICAL **: 18:50:39.405: g_dbus_proxy_new_sync: assertion 'G_IS_DBUS_CONNECTION (connection)' failed`
dbus とは GNOME などの GUI ウィンドウシステムの制御を目的としたプロトコルです。解決策として以下のコマンドを実行した上で、セッションを再起動して下さい。するとエラーが表示されなくなります。
```console
[guest@localhost ~]$ rm /run/user/1002/bus
```
**1002**の部分はログインしているユーザの userID に置き換えて下さい。userID は以下のコマンドを実行して出てきた数値になります。
```console:userID
[guest@localhost ~]$ cat /etc/passwd|grep guest # 自分のユーザ名に置き換えて下さい
guest:x:1002:1002::/home/guest:/bin/bash
```
`/run/user/1002/bus` を削除するとエラーが治る理由については、よく分かりませんでした（エラーが消えたのでよしとしましょう）。

### dbus 関連のエラー2
`dconf-WARNING **: 23:37:12.282: failed to commit changes to dconf: Could not connect: No such file or directory`
`dconf-WARNING **: 16:13:01.992: failed to commit changes to dconf: Could not connect: Connection refused`
こちらも解決策として以下を実行した上で、セッションを再起動すると表示されなくなります。
```console
[guest@localhost ~]$ rm /run/user/1002/bus
```
### Gnome Accessibility を使っていないことによるエラー
`dbind-WARNING **: 21:06:30.439: Couldn't register with accessibility bus: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.`
詳しいことは分かりませんでしたが Gnome Accessibility を使用していないと起こるエラーだそうです（再現性がなかったです）。
解決策として `~/.bashrc` に以下を追加して下さい。
```bash:.bashrc
export NO_AT_BRIDGE=1 
```

## Xサーバの表示が遅いとき
`eog` コマンドを使用したとき画像が表示されるまで異様に時間がかかることがありました（通常は1秒もかからないのに表示まで25秒くらいかかる）。 色々試してみたところ以下の方法で解決しました
```console
[guest@localhost ~]$ rm /run/user/1002/bus
```
**1002** の部分はログインしているユーザの userID に置き換えて下さい。

## 最後に
パッケージをインストールする時に、アーキテクチャによる違いを意識していなかったため、`eog` のインストールに悪戦苦闘してしまいました。今回は CentOS Stream 8 に `eog` をインストールしてみましたが、同様に CentOS Stream 9 でも似たようなことができそうです（CentOS Stream 9 の公式リポジトリにも aarch64 の `eog` がないため）。そのうち CentOS Stream 9 にアップグレードしようと思うので、その時試してみたいと思います。

## 参考
<a href="https://rin-ka.net/windows-x-server/">VcXsrv（Xサーバー）をWindowsにインストールしLinuxのGUIをリモート操作する設定方法</a>
<a href="https://wiki.archlinux.org/title/GTK#Suppress_warning_about_accessibility_bus"> Suppress warning about accessibility bus </a>