前回はソフトウェア・ツールズの考え方と基本的な使い方を紹介しました。その際にも説明しましたが,ソフトウェア・ツールズでは,最近のGUIベースのソフトウェアのように1つのソフトウェアに多くの機能を詰め込むのではなく,1つの機能に特化した小さなコマンドをさまざまに組み合わせて,複雑な処理を実現しようとします。
これらのコマンドは前の結果を確認しながら対話的に実行していくこともできますが,あらかじめ実行したいコマンドを並べたファイルを用意して一気に実行することもできます。このファイル(シェルスクリプト)を保存しておけば,別の機会に同じ操作を再び行うことも可能ですし,先頭行にシェバン(#!/bin/bash等)を付けて実行パーミッションを与えておけば,新しいコマンドとして直接実行することも可能です。
ユーザが作った新しいコマンドも,PATH環境変数で指定するコマンドのサーチパスに保存しておけば,システムにあらかじめインストールされているコマンドと同様に利用できるようになります。このように自分で作ったコマンドでシステムを拡張していけるのも,Linux/UNIXの魅力のひとつです。
かつて1台のUNIXマシンを複数のユーザが利用していたころは,このような自作コマンドのうち,自分専用のものはホームディレクトリの適当なディレクトリに,他のユーザにも使ってもらいたいものは/usr/local/bin/ディレクトリに置いてみんなで使えるようにしていました。大学の研究室などでは,代々の管理者が作ったコマンドを引き継ぎ,成長させて,使いやすい環境を作っていったもので,そのようなコマンドを読んで理解することが,管理者の卵にとってはいい勉強になりました。
今までにも何度かシェルスクリプトの読み方を紹介しましたが,今回はシェルスクリプトを作っていく例を紹介しましょう。
Plamo Linuxのパッケージ管理システム
筆者がまとめ役をやっているPlamo Linuxでは元々のベースとしていたSlackwareのパッケージ管理システムを改良して利用しています。そのためパッケージをインストールするinstallpkgとインストール済みのパッケージを削除するremovepkgコマンドはあるものの,削除とインストールを自動的に行うようなコマンドはなく,パッケージのアップデートが必要な際はremovepkgコマンドでインストール済みのパッケージを削除してからinstallpkgコマンドを実行していました。
少数のパッケージを更新するだけならばこれでも別に困らないのですが,前回紹介したようにPlamo-4.5を出してからアップデートされたパッケージをまとめて更新しようとすると,400近いパッケージをアップデートする必要があります。これだけ多数のパッケージを一々手動でアップデートするのは大変なので,updatepkgコマンドを作ることにしました。
ちなみにPlamo-4.51で更新されるパッケージは,X11をR74にするために必要なパッケージが約270,Pythonを2.6にするために必要なパッケージが約100ほどになりました。細かくモジュール化されたX11R74は覚悟していたものの,Pythonのライブラリやスクリプトを使っているソフトウェアがこれほど多いとはちょっと予想外で,最近ではPythonも基盤ソフトウェアなみに更新の際には注意する必要がありそうです。
updatepkgスクリプトを考える前に,Plamo Linuxで採用しているパッケージ管理システムの概要を紹介しておく方がいいでしょう。Plamo Linuxでは,パッケージ名はパッケージのベース名とバージョン番号,対象アーキテクチャ,ビルド番号の4つの部分を'-'(ハイフン)でつないだ形になっています。たとえば,今回のアップデートで更新するPython 2.6のパッケージ名はpython-2.6-i586-P1.tgzです。このパッケージ名の場合,ベース名がpython,バージョンが2.6,対象アーキテクチャがi586,ビルド番号がP1となります。
installpkgコマンドでパッケージ名を指定してパッケージをインストールすると,そのパッケージのベース名のファイルが/var/log/packages/ディレクトリに作成され,このファイルにはパッケージ名や説明,インストールしたファイルやディレクトリの一覧が記録されます。
% cat /var/log/packages/python PACKAGE NAME: python-2.6-i586-P1 COMPRESSED PACKAGE SIZE: 17855 K UNCOMPRESSED PACKAGE SIZE: 61720 K PACKAGE LOCATION: ./Python/python-2.6-i586-P1.tgz PACKAGE DESCRIPTION: FILE LIST: install/ install/doinst.sh usr/ usr/include/ usr/include/python2.6/ usr/include/python2.6/cellobject.h usr/include/python2.6/bytearrayobject.h ...
一方,インストールしたパッケージを削除したい場合は,removepkgコマンドにパッケージのベース名を指定して実行します。
# removepkg rhythmbox Removing package rhythmbox... Removing files: --> Deleting symlink usr/lib/librhythmbox-core.so --> Deleting symlink usr/lib/librhythmbox-core.so.0 --> Deleting etc/gconf/schemas/rhythmbox.schemas --> Deleting usr/bin/rhythmbox ...
removepkgコマンドは/var/log/packages/以下にあるパッケージのベース名のファイルからそのパッケージでインストールされたファイルやディレクトリを調べ,それらを削除していきます。
updatepkgコマンドでは,指定されたパッケージをインストールする前にそのパッケージと同じベース名のファイルが/var/log/packages/ディレクトリ以下にあるかどうかを調べ,ファイルがあればremovepkgでアンインストールしてからinstallpkgでインストールするようにすればいいでしょう。
このような簡単な仕組みになっているので,一種の裏技ですが,/var/log/pacakges/以下にあるファイル名を変更することで,パッケージをアンインストールせずに更新する,ということも可能です。たとえばカーネルパッケージの場合,ドライバモジュール類はバージョン番号が付されたディレクトリに配置されているため,バージョンが異なるパッケージを共存させることも可能なので,/var/log/packages/kernelというファイルを/var/log/packages/old_kernelとでも変更すれば,古いパッケージを残したまま新しいパッケージをインストールすることができます。

