第5章 パッケージ管理の応用(dpkg/apt・rpm/dnf)

LPIC-1 102.3〜102.5 相当

初級の第9章では apt / dnf / pacman の基本操作を扱いました。ここでは、パッケージ管理の内部の仕組みにもう一歩踏み込みます。

dpkg — Debian系パッケージの低レベル操作

apt は依存関係を自動解決してくれる高レベルなツールですが、その内部では dpkg がパッケージファイル(.deb)そのものを扱っています。

$ sudo dpkg -i package.deb     # .debファイルを直接インストール
Selecting previously unselected package myapp.
Unpacking myapp (1.2.0-1) ...
Setting up myapp (1.2.0-1) ...
$ dpkg -l                      # インストール済みパッケージ一覧
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
||/ Name           Version         Architecture Description
+++-==============-===============-============-=================
ii  nginx          1.24.0-2ubuntu7 amd64        small, powerful, scalable web...
ii  openssh-server 1:9.6p1-3ubuntu13 amd64      secure shell server
...(この後もインストール済みパッケージが続く)
$ dpkg -L nginx                # nginxが持つファイル一覧
/etc/nginx
/etc/nginx/nginx.conf
/usr/sbin/nginx
/var/log/nginx
...(この後も所属ファイルが続く)
$ sudo dpkg -r nginx           # 削除(設定ファイルは残る)
(Reading database ... 184291 files and directories currently installed.)
Removing nginx (1.24.0-2ubuntu7) ...

この行のこの値に注目: dpkg -lの各行先頭にあるiiは「Installed(インストール済み・設定完了)」を示す状態コードで、rc(削除済みだが設定ファイルが残っている)などとの違いを見分けられます。dpkg -Lはパッケージ名から所属ファイルを調べる向きで、逆にファイルパスからパッケージ名を調べたいときは後述のdpkg -Sを使います。

rpm — Red Hat系パッケージの低レベル操作

$ sudo rpm -ivh package.rpm    # インストール(-i: install, -v: verbose, -h: 進捗表示)
Verifying...                          ################################# [100%]
Preparing...                          ################################# [100%]
Updating / installing...
   1:myapp-1.2.0-1.el9              ################################# [100%]
$ rpm -qa                      # インストール済みパッケージ一覧
httpd-2.4.57-5.el9_4.x86_64
openssh-server-8.7p1-38.el9.x86_64
...(この後もインストール済みパッケージが続く)
$ rpm -ql httpd                # httpdが持つファイル一覧
/etc/httpd/conf/httpd.conf
/usr/sbin/httpd
/var/log/httpd
...(この後も所属ファイルが続く)
$ sudo rpm -e httpd            # 削除(erase)
(正常に削除できた場合、rpm -eは既定では何も表示しない)

この行のこの値に注目: rpm -ivhの[100%]という進捗バーが最後まで到達し、エラー行が出ていなければインストール成功です。rpm -qaの各行はパッケージ名-バージョン-リリース.アーキテクチャという形式になっており、dpkgの表形式とは表示のされ方が異なる点に注意してください。

高レベルツールと低レベルツールの対応

操作Debian系(低レベル/高レベル)Red Hat系(低レベル/高レベル)
ファイルからインストールdpkg -irpm -ivh
依存関係解決込みでインストールapt installdnf install
一覧表示dpkg -lrpm -qa
検索apt searchdnf search

共有ライブラリの確認

多くのプログラムは、共通の機能を「共有ライブラリ」として外部化しています。実行に必要なライブラリが見つからないと、プログラムは起動できません。

$ ldd /usr/bin/nginx     # 実行ファイルが依存する共有ライブラリを確認
	linux-vdso.so.1 (0x00007ffcabf12000)
	libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007f2a1c000000)
	libssl.so.3 => /lib/x86_64-linux-gnu/libssl.so.3 (0x00007f2a1bf00000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2a1bd00000)
$ sudo ldconfig          # 共有ライブラリのキャッシュを更新
(正常に完了した場合は何も表示しない)

この行のこの値に注目: lddの出力で、探しているライブラリの右側に実際のパス(=> /lib/...)が表示されていれば正しく解決できています。もしここがnot foundになっている場合、そのライブラリが未インストールか、後述のldconfigによるキャッシュ更新が必要な状態です。

リポジトリの設定

apt や dnf は、あらかじめ設定された「リポジトリ」と呼ばれるサーバーからパッケージ情報を取得します。

ディストリ系統リポジトリ設定ファイル
Debian系/etc/apt/sources.list、/etc/apt/sources.list.d/*.list
Red Hat系/etc/yum.repos.d/*.repo
$ sudo apt update              # リポジトリの最新パッケージ一覧を取得
Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease
Reading package lists... Done
$ apt-cache policy nginx       # インストール候補のバージョンと取得元を確認
nginx:
  Installed: 1.24.0-2ubuntu7.4
  Candidate: 1.24.0-2ubuntu7.4
  Version table:
 *** 1.24.0-2ubuntu7.4 500
        500 http://archive.ubuntu.com/ubuntu noble-updates/main amd64 Packages
$ sudo dnf repolist            # 有効なリポジトリの一覧(Red Hat系)
repo id                repo name
appstream               Rocky Linux 9 - AppStream
baseos                  Rocky Linux 9 - BaseOS
extras                  Rocky Linux 9 - Extras

この行のこの値に注目: apt-cache policyのInstalled行とCandidate行が一致していれば、そのパッケージは最新の候補バージョンがすでに入っている状態です。両者が異なる場合は、apt upgradeで更新できる新しいバージョンが存在することを意味します。

依存関係の問題と検証

手動でdpkg/rpmを操作したり、インストールが途中で失敗したりすると、依存関係が壊れた状態になることがあります。

$ sudo apt --fix-broken install   # 壊れた依存関係を解決
Reading package lists... Done
Building dependency tree... Done
Correcting dependencies... Done
The following packages will be upgraded:
  libssl3
1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
$ rpm -Va                          # インストール済みパッケージのファイルを検証(改変・欠落を検出)
S.5....T.  c /etc/nginx/nginx.conf
missing    /etc/nginx/conf.d/old.conf
$ rpm -qf /etc/nginx/nginx.conf     # 特定のファイルがどのパッケージに属するか調べる(-qfはquery fileの意味)
nginx-1:1.20.1-14.el9.x86_64
$ dpkg -S /etc/nginx/nginx.conf     # 同様の操作をDebian系で行う場合
nginx-common: /etc/nginx/nginx.conf

この行のこの値に注目: rpm -Vaの行頭記号は変更点の種類を表し、Sはファイルサイズが変わった、5はMD5チェックサムが変わった、Tはタイムスタンプが変わったことを意味します(.は変更なし)。missingは本来あるはずのファイルが存在しないことを示し、設定ファイルの改変や欠落を調査する手がかりになります。

試験対策: 「あるファイルがどのパッケージに属するか」を調べる操作(rpm -qf / dpkg -S)と、「パッケージが持つファイル一覧を調べる」操作(rpm -ql / dpkg -L)は向きが逆であることを混同しないようにしましょう。
apt install nginx nginx libssl.so.3 libpcre2-8.so.0 libc.so.6 同じ依存関係を、ツールによってこう扱う: apt / dnf(高レベル) 依存関係を自動計算し、libssl・ libpcre2・libcもまとめて導入 dpkg -i / rpm -i(低レベル) 依存パッケージが無いとエラー で失敗。事前に手動導入が必要
パッケージ管理の依存関係解決。nginxはlibsslとlibpcre2に依存し、libsslはさらにlibcに依存しています。apt/dnfのような高レベルツールはこの依存関係全体を自動的にたどってまとめてインストールしますが、dpkg -i/rpm -iのような低レベルツールは依存関係を解決せず、必要なライブラリが無いとインストールに失敗します。

特定パッケージのバージョンを固定する

運用中のシステムでは、動作確認済みのバージョンから意図せず更新されてしまうと困る場合があります。そのようなときは、パッケージを「更新対象から除外(保留)」する機能を使います。

$ sudo apt-mark hold nginx        # nginxを更新対象から除外(Debian系)
nginx set on hold.
$ apt-mark showhold                # 保留中のパッケージ一覧を確認
nginx
$ sudo apt-mark unhold nginx      # 保留を解除
Canceled hold on nginx.
$ sudo dnf install python3-dnf-plugin-versionlock  # Red Hat系では versionlock プラグインで同様のことを行う
...(インストール処理。完了時は Complete! と表示される)
$ sudo dnf versionlock add nginx
Adding versionlock on: nginx-1:1.20.1-14.el9.*

この行のこの値に注目: apt-mark hold実行直後にnginx set on hold.という確認メッセージが返り、apt-mark showholdで一覧に含まれていれば保留設定が有効です。この状態ではapt upgradeを実行してもnginxだけは対象から除外されます。

パッケージの署名検証

信頼できないパッケージを誤ってインストールしてしまわないよう、多くのディストリビューションでは配布パッケージにGPG署名を付け、リポジトリ設定に登録された公開鍵で検証してからインストールする仕組みが標準で有効になっています。

$ sudo apt-key list                 # 登録済みの信頼済み鍵を確認(新しめのDebian系では非推奨、代わりに/etc/apt/trusted.gpg.d/を使う)
/etc/apt/trusted.gpg.d/ubuntu-keyring-2018-archive.gpg
------------------------------------------------------
pub   rsa4096 2018-09-17 [SC]
      F6EC B376 2474 EDA9 D21B  7022 8719 20D1 991B C93C
uid           [ unknown] Ubuntu Archive Automatic Signing Key (2018) <ftpmaster@ubuntu.com>
$ sudo rpm --import RPM-GPG-KEY-example   # Red Hat系で公開鍵を手動でインポート
(正常にインポートできた場合は何も表示しない)
$ rpm -K package.rpm                 # 個別のrpmファイルの署名を検証
package.rpm: digests signatures OK

この行のこの値に注目: rpm -Kの結果がdigests signatures OKであれば、ファイルの改ざんがなく、登録済みの鍵で正しく署名されていることが確認できています。ここがNOT OKやMISSING KEYSと表示された場合は、出所不明なパッケージである可能性があるため、インストールを見送るべきです。

注意: 署名が検証できないパッケージのインストールには警告が出ます。出所の分からないリポジトリやファイルを追加する際は、信頼できる配布元かどうかを必ず確認しましょう。

キャッシュのクリーンアップ

apt・dnfはダウンロードしたパッケージファイルをローカルにキャッシュするため、長く使っているとディスクを圧迫することがあります。

操作Debian系Red Hat系
キャッシュのクリアsudo apt cleansudo dnf clean all
使われなくなった依存パッケージの削除sudo apt autoremovesudo dnf autoremove

豆知識: パッケージ形式の変換

alienというツールを使うと、.rpmファイルを.debに変換する(あるいはその逆)といったことも可能です。ただし依存関係やパッケージ内のスクリプトの互換性までは保証されないため、あくまで応急的な手段として扱われます。可能な限り、そのディストリビューション向けに公式に配布されているパッケージを使うのが安全です。

依存関係グラフをたどる:なぜ「消したいだけなのに大量に消えそうになる」のか

あるパッケージをremoveしようとすると、「これに依存している他のパッケージも一緒に削除されます」という警告が表示され、想定より遥かに多いパッケージ名がずらりと並ぶことがあります。これは、パッケージ管理システムが依存関係を双方向に把握しているために起きる現象です。たとえば汎用的なライブラリパッケージを削除しようとすると、それに依存しているアプリケーションもまとめて削除候補に挙がってしまいます。このような警告が出たときは、慌ててyを押さず、削除候補の一覧を落ち着いて確認する習慣をつけましょう。本当に消したいのがライブラリ側なのか、それとも動作確認のために入れた別のパッケージが原因で依存関係が複雑化しているだけなのかを見極めることが重要です。

パッケージのダウングレード

アップデート後にソフトウェアの挙動がおかしくなった場合、原因が更新にあると判断できれば、以前のバージョンに戻す(ダウングレードする)ことも選択肢になります。apt環境ではキャッシュに残っている過去バージョンの.debファイルからdpkg -iで戻す方法や、リポジトリで公開されているバージョンを明示的に指定してインストールし直す方法があります。ただしダウングレードは他のパッケージとの依存関係の整合性を崩すリスクがあるため、まずは可能であれば動作確認用の別環境で試してから本番に適用するのが安全です。

確認クイズ

Q1. apt の内部で、実際に.debファイルをインストール・削除している低レベルのツールはどれですか?

解説: aptは依存関係解決などを行う高レベルツールで、その内部でdpkgが実際のパッケージ操作を行っています。

Q2. Red Hat系で、インストール済みパッケージの一覧を表示するコマンドはどれですか?

解説: rpm -qa(query all)はRed Hat系でインストール済みの全パッケージを一覧表示します。Debian系の同様の操作は dpkg -l です。

Q3. 実行ファイルが依存している共有ライブラリを確認するコマンドはどれですか?

解説: ldd コマンドは、指定した実行ファイルが依存している共有ライブラリの一覧とその解決状況を表示します。

Q4. dpkg -i package.deb を実行した場合の動作として正しいものはどれですか?

解説: dpkgは低レベルツールのため、依存関係の自動解決は行いません。依存関係も含めて解決したい場合は apt を使います。