まずはシステムアップデートの流れから復習
私が使用しているディストリビューションがCachyOS(Arch Linux系)ということもあり、その標準パッケージマネージャーpacmanを例に書いていこうかと思います。aptにしろ、Fedoraなどで使われるdnfにしろその見た目や、各サーバーのデータベースや構造は違ってもどれもLinuxという枠組みで見ると同じようなことをしています。
Arch系のシステムアップデートはsudo pacman -Syu(パッケージのデータベースの同期とシステム全体のアップデート)をターミナルやGUIのパッケージマネージャで(システムのアップデートとして)実行すると、システム内部では以下のような感じでトランザクションが処理されます。
- データベースの更新(Sync Database)
- アップデート前の事前準備
- リポジトリから最新のパッケージ一覧をダウンロードします。どのパッケージに更新があるかを調べるためです
- 依存関係の解決と計算(Dependency Resolution)
- 矛盾がないかのチェック
- アップグレード対象のパッケージと、それに必要な依存ライブラリの整合性を検証します。競合や不整合(パッケージの衝突)が発生しないか、この段階で事前に計算します。
- パッケージのダウンロード(Fetch Archives)
- 更新に必要な
.pkg、.tar、.zstパッケージファイルをローカルキャッシュ(/var/cache/pacman/pkg)へダウンロードし、署名(PGP)を検証します
- 更新に必要な
- トランザクションの初期化(Transaction Initialize)
- ここから変更フェーズ
- ユーザーの確認(Y/n)後、pacman内部でトランザクションが作成されます
- システムデータベースのロック(
/var/lib/pacman/db.lckの作成) - インストール前のフック処理の実行
- システムデータベースのロック(
- 変更コミット・適用(Commit Transaction)
- ダウンロードしたパッケージを展開し、古いファイルを新しいファイルへと置き換えていきます。
- ファイルの展開中にエラーが発生した場合、pacmanは未完了の変更をロールバックし、壊れた状態が残らないように安全中断しようと試みます
- ダウンロードしたパッケージを展開し、古いファイルを新しいファイルへと置き換えていきます。
- トランザクションの完了・解放(Release Transaction)
- すべてのファイルの配置とインストール後のフック処理が完了したらロックファイルを削除して、トランザクションを正常完了させます。
流れとしてはこういうことです。
トランザクションをわかりやすく
トランザクションという言葉が何をしているのかがわかりにくくさせていると思います。トランザクションは「取引・商売」というような意味ですが、ITやコンピューターの世界では単にそれらの単語からイメージするものとは少し異なります。
例えば、「銀行を例にしてAさんの口座からBさんの口座へ1万円振り込む」という流れでいうと、
- Aさんの口座から1万円を減らす
- Bさんの口座に1万円増やす
こういう処理が行われます。もし「1」の減らした状態直後にシステムエラーや停電が起きたらAさんのお金だけが消えてBさんには届かないと言うことになります。
この全て成功するか、全く処理されないかを保証する一連の処理の事を銀行の取引にちなんでトランザクションと呼ぶようになりました。
これはどこかで聞いた覚えがあるかも知れませんが、FedoraでいうAtomicというものとそっくりです。Fedora Atomic各種スピンなどのImmutable(不変)更新というのは、この仕組みをシステム全体、OSのルートレベルまで拡張した仕組みです。
トランザクションフックとは何をしているか
「トランザクションフックを実行しています(Running transaction hooks…)」という表示は、パッケージのファイル展開(置き換え)が完了した直後または直前に、「システムを正しく動作させるための仕上げ処理」を自動で実行している状態です。
ダウンロードして展開しただけではシステムはそれを認識できないので、特定のタイミング(イベント)に引っ掛けて自動実行するプログラムスクリプトの事をフック(Hook)と呼びます。
トランザクションフック…というような表示が出ている時、次のような仕上げ作業が順番に行われています。
- カーネルと初期応答機能の更新(mkinitcpio)
- Linuxカーネルが更新された場合、パソコン起動時に必要な初期イメージ(initramfs)を再生成します。
- 共有ライブラリのキャッシュ更新(ldconfig)
- 追加・更新された新しいライブラリ(.so ファイル)をシステムが即座に見つけられるよう、リンク情報を更新します。
- デスクトップやアイコンのデータベース更新
- 新しいアプリを入れた際、アプリ一覧にアイコンや名前(.desktop)が正しく表示されるようキャッシュを再構築します。
- フォントキャッシュの更新(fc-cache)
- 新しいフォントを追加した際、文字化けせずに使えるようシステムに認識させます。
- 不要な設定ファイルや古い一時ファイルのクリーンアップ
システムファイルだけでなく、GIMPや様々なアプリを更新したとしても同様に処理が行われます。1回ごとに処理するのではなくまとめて処理したあと、仕上げ処理を1回で行うための方法です。
トランザクションの初期化中などとあった場合は、銀行で言うと「誰から誰へ、いくらのやり取りをするか」というような計画(伝票)を作成して、取引を安全に行うための整備を事前準備しているというようなこととなります。
この辺りは言われてみれば「それはそうだ」と思われることだと思います。けれどもどこにも説明なく、その単語をそのままカタカナにして書かれても意味がわからないとなるのは当然のことです。
「トランザクションフックを実行しています」の最中は、すでにシステムファイルが書き換わっており、最後の仕上げ段階にいます。ここで強制終了(電源オフやターミナルの閉鎖)をすると、カーネルイメージの生成が途中で止まるなどして次回OSが起動しなくなる危険性が高いため、処理が完了するまで必ず待つ必要があります。
他のディストリビューションではどうなっているのか?
本質的にやっていることは、どのパッケージマネージャでも全く同じです。
- メタデータの同期
- リモートサーバー(リポジトリ)の最新リストをダウンロードしてローカル情報と比較する。
- 依存関係の計算
- どのパッケージが必要か、バージョン衝突が起きないかを判定し、変更リスト(トランザクション)を作成する。
- アーカイブの取得
- 更新に必要なファイル群(.deb や .rpm など)をローカルキャッシュに一括ダウンロードする。
- 展開・適用
- 旧ファイルを削除し、新ファイルを配置する。途中で失敗した場合は安全に中断・変更を破棄する。
- フック処理
- キャッシュ再構築、サービスの再起動、カーネルイメージ(initramfs)の再生成などを一括実行する。
| 項目 | ArchLinux(pacman) | Debian/Ubuntu(apt) | Fedora(dnf) |
|---|---|---|---|
| パッケージ形式 | .pkg.tar.zst |
.deb |
.rpm |
| 同期・更新コマンド | pacman -Syu |
apt update && apt upgrade |
dnf upgrade |
| データベースの場所 | /var/lib/pacman |
/var/lib/apt |
/var/lib/dnf |
| ダウンロードキャッシュ | /var/cache/pacman/pkg/ |
/var/cache/apt/archives |
var/cache/dnf |
| フックの仕組み | alpm-hook(/usr/share/libalpm/hooks/) |
DPkg::Post-Invoke などのスクリプト | DNF Plugin / RPM trigger |
| 低階層の処理実行ツール | libalpm(pacmanに内蔵) |
dpkg |
rpm |
と言う感じですが、かなり似通っていることがわかると思います。「リポジトリからリストを取ってきて、依存関係を計算し、取ってきて適用し、最後に後始末(フック)をする」 という思想・設計はLinuxの世界で完全に標準化されています。
NixOSでは、例えばPythonでもバージョン違いが共存できるじゃないかと言われる方がいるかも知れません。NixOSは同じアプリのバージョン違いは、それぞれにハッシュを付与してハッシュ管理しているため、Pythonのバージョンが違っても別物として共存できるようになっています。
違うバージョンというのはハッシュの違いでしかないので、従来のトランザクションが抱えていた上書きによる破損のリスクはそもそも存在しないのです(そう言う処理をしないため)。 そんなにNixOSが優れているなら、他のディストリビューションも追従するはずでは?とも思われるかも知れませんが、従来のトランザクションは無駄ができにくくストレージの節約にも繋がります。なのでメリットがないわけでもないのです。NixOSが超特殊だと考えるほうが良いと思います。
Windowsではどうなっているのだろうか?
Windowsのアップデートってダウンロードも勝手にして、勝手に再起動が入ってその間何もできなくて面倒が過ぎますよね。
| 項目 | Linux(pacman、apt、dnfなど) | Windows(Update) |
|---|---|---|
| 使用中のファイルの上書き | 可能(Linuxファイルシステムの特性) | 不可(Windowsがファイルを厳重にロックする) |
| アップデート中の作業 | そのままPCを使用継続可能 | 再起動時・電源オフ時に待たされる |
| 再起動のタイミング | 好きなタイミングでok | 強制、または強く強要 |
Linuxの場合
Linuxでは、プログラムがファイルを実行中でも、ディスク上のファイルを新しいものに差し替えることができます。
Linuxは中央集権型と言えます。
- OS(カーネル)からデスクトップ環境、ブラウザ、プログラミング言語、ドライバ、果ては普通のフリーソフトまで、システムに存在するほぼ全てのソフトを一括管理・更新します。
今回のトランザクションの話でもそうですが、ターミナル上にログが残ります。これはシステムファイルでも、サードパーティーアプリでも同様です。今、裏で何が起きているかがログとしてすべてリアルタイムに画面に可視化されます。
Windowsの場合
Windowsでは、実行中のDLLやシステムファイルはOSレベルで固くロックされます。
Windowsは分散型(基本はOS+一部マイクロ製品)です。
- Windows Updateが管理するのは、基本的にWindows OS本体、標準機能、Defender(セキュリティ)、一部の標準アプリやドライバのみです。
- Chrome、Steam、Photoshopなどのサードパーティ製アプリは、アプリごとに独自の更新機構(バックグラウンドサービス)が個別に動いてアップデートします。
Windowsでは更新内容は公開されているとは言え、画面には「○% 完了しました」や「準備しています」といった抽象的な表示しか出ず、裏で具体的にどのファイルが置換されているかは隠蔽されています。
アップデートのまとめ
Linuxは、走行中の電車(OS)のパーツを、乗客を乗せたまま1つずつ新しいものに組み替えていく」ようなアプローチ。フックを使ってその場で整合性を整えます。
Linuxは停止時間をできるだけ作らずに、最小限の時間でシステム・アプリの更新ができるようなサーバー・エンジニア向けの設計となっており、Windowsは一般ユーザーがファイルを壊さないようにOSが確実に整合性を保てる状態(作業中以外・停止時)に処理する設計を取っているという違いがあります。
本来であればWindowsの方が確実に思われるでしょうが昨今のアップデートの不具合から考えると、何をしたからおかしくなったがわかるほうが、最初に試して問題が起きた人が即座にフィードバックできるという点を考えると何をしているのかが隠蔽されるのはある意味問題です。
Windowsでは、それらは一応あるので問題があるファイルを配信して色んな人に怒られている現状があります。
おまけ pacmanあれこれ
pacmanの更新時にはpacman -Syuとしますが、他にもいくつか便利なものをかいておきます。
| オプション文字 | 意味 | 役割 |
|---|---|---|
-S |
Sync(Synchronize) | 同期モード。リポジトリ(サーバー)からパッケージを取得・同期して操作する大枠のモード。 |
y |
refresh | データベースの更新。 ローカルにある「サーバーのパッケージ一覧リスト」を最新に更新(refresh)します。 |
u |
sysupgrade(システムアップグレード) | パッケージの更新。 システム全体(インストール済みアプリ)を最新バージョンへアプデ(upgrade)します。 |
本来ならrefreshなのでrなどを使いたいところですが、既に他で使用されている(予約されている)ためキーボードで押しやすい位置にもあること、Syncという意味からもyが選ばれたと言う経緯があるそうです。pacman -Syでリポジトリのリスト(DB)を1回更新すると言う事ですが、pacman -Syyとすると「リストが最新に見えても、強制的にもう一度完全にダウンロードし直す」と、文字を重ねることでより強く「強制的に(Force状態)で動作させる」というルールがあります。
ローカルスクリプト(.pkg.tar.zst)をインストールする際にはpacman -Uと大文字のUになっています。小文字のuとは意味が異なり、Upgrade/Install local packageとなります。cURLなどを使用してダイレクトにできるものもあるのにどうしてpacman -U <スクリプト>等としてわざわざ入れるのかは、アンインストールする時にpacmanでさっくりと削除するためです。
これらはオプションを全部覚えておく必要があるのではなく、「そういう機能があったな」と理解しておき、必要に迫ったらArch Wikiなどで調べて使用すればよいと思います。
Wait/Download only
sudo pacman -Syuw
ダウンロードだけ先に済ませておいて、後から時間ができたときに、sudo pacman -Suとすると一瞬でインストールを終わらせると言った使い方ができます。wはwaitで、Wait/Download onlyという意味になります。
ダウングレードを許可する更新
sudo pacman -Syyuu
配信側が配信した後、何かの問題で配信自体をロールバックしてしまって、それらをダウンロードしたPCでローカルの方が新しいとなった場合に、たいていは数日で更新されると思うので「ローカルの方が新しい」のは放置しておいても良いと思いますが、(サウンド系の配信等で)音が出なくなったとかとシステムがおかしくなるほどではないが問題が出た場合にそれでは困るので、ダウングレードを許可する更新をして、以前の正常だったバージョンに強制的に戻すと言う事が可能です。
Search
pacman -Ss <keyword>
リポジトリにあるパッケージをキーワード検索します。Searchです。
Query Search
pacman -Qs <keyword>
「自分のPCにすでにインストールされているパッケージ」の中から検索します。自分が入れたかどうか確認したい時に便利です。
Search Info
pacman -Si <package>
未インストールのパッケージの「説明、依存関係、ダウンロードサイズ」などの詳細情報を確認します。Search Infoになります。
Query Info
pacman -Qi <package>
インストール済みパッケージの詳細情報(「いつ入れたか」「どのパッケージに依存されているか」など)を確認できます。Query Infoになります。
Query Dependencies True Orphans
pacman -Qdt
以前別のソフトを入れた際についでにインストールされ、現在はどのソフトからも必要とされていない「孤立したパッケージ」を一覧表示します。Query Dependencies True Orphansと言う意味になります。
Remove Nosave Recursive
sudo pacman -Rns <package>
パッケージを消す際、単に消す(-R)だけでなく、「そのアプリしか使っていなかった不要な依存ライブラリ」や「設定ファイルのバックアップ」もまとめて綺麗に削除します。アプリをアンインストールする時は基本これを使います。Remove Nosave Recursiveと言う意味です。
インストールあれこれ
インストールする際に、sudo pacman -S firefox等とすることはよくあります。firefox自体はそれでよいのですが、共用されているライブラリが最新でない可能性というのはあったりします。
pacmanは最新のFirefoxと、そのfirefoxが使用する最新のライブラリをダウンロードして配置しようとします。この時、もしpacmanが必要なライブラリの一部しか更新しなかったり、あるいはローカルの古いライブラリと噛み合わなくなると依存関係の不整合が起こる可能性が発生します。sudo pacman -Syu firefoxとその時の最新にシステムもしておく方が間違いがないとされるのです。
sudo pacman -Sy firefoxなどは特に危険これはデータベースだけ更新することになり、アプリは最新が入りますが、周りの古いライブラリが放置されるため一番危険な「部分更新(Partial Upgrade)」の状態になります。
他にもたくさんのオプションがありますが、探して入れて削除するということができれば何でもできるのではないかと思う次第です。
まとめ
主にトランザクション中心に書きました。これらは「そう言われたらわかる」となると思いますが、それに合うような日本語がない、あるいはパッと思いつかない程度に逆に難しい単語となるならトランザクションでいいかとなるのもわかるとも言えます。
またWindowsのアップデート(特にメジャーアップデート)は、裏でOS丸ごと入れ替え大作戦を実行しています。Windows.old)からユーザーデータや設定を新しいOSへ引き継ぐ(移行・移動する)ため、膨大なディスクI/Oと処理時間がかかります。
一方Linuxでは、作業中にでもファイルの更新はでき、更には好きなタイミングで更新作業に入れるので、余裕を持ちながら更新作業ができます。
良いことばかりのLinuxではありませんが、はじめて更新をされた人はその更新作業の速さに驚かれることかと思います。
システムの設定などは色んなところで書かれているのである程度は分かるものの、どう使用していけばよいのかはあまり書かれていないので、本来は問題ないけれども間違った方法で運用すると不具合が出てしまう事があります。
WindowsはそれらをOSができるだけやっているだけで、どっちもどっちなのです。Linuxでもログは見れますがGUIでアップデートやアプリのインストールをすればWindowsと変わりません。