こんにちは、プロダクト&サービス事業部の白石です。
唐突ですが、日本はよく豊かな国だと言われることがあります。
それは、ただ単に日本人の所得が高いというわけではなく選択の幅があるからです。
いざ美味しいものを食べたいなと思った時、
日本の料理はもちろんのこと、中華料理、韓国料理、イタリア料理などすぐに見つかります。
さらにちょっと手間を掛けて、大きな街中に足を運んだりするともっと多彩な国のグルメを楽しむことが出来ます。
また、こだわりのあるバーなんかに行くと世界中のお酒が並んでたりしますよね。
こういった選択の幅がある国って他にはなかなか無いそうですよ。
このように何かしようと思った時に、
色々あるものの中から好きなものを選べるのことはとても恵まれていることだと思いませんか?
そんな選択肢を文字通りLinuxに与えてくれるのが update-alternatives というコマンドです。
今回はCentOSでの検証を基に話をしますが、
CentOSの他に、Debian、RedHat系(RHEL、Fedora)にも
この update-alternatives という
シンボリックリンクを管理してデフォルトのコマンドを決定(man参照)するコマンド
があります。
簡単に言うと、複数のバージョン(または似たような機能)を持つプログラムを切り替える(管理する)コマンドです。
CentOSにSUNの Java を入れたことがある方は、一度は使ったことがあるのではないかと思います。
今回はこの update-alternatives コマンドについて解説したいと思います。
目次
- update-alternatives とは
- update-alternatives の使い方
- スレーブとは
- update-alternatives の簡単なファイル構成
- 共通オプション
- まとめ
- 参考ドキュメント
- おまけ – SUNのJDKをCentOS 5.3にインストールする
使用したソフトウェアのバージョン
今回、使用したソフトウェアのバージョンは下記のようになります。
| バージョン | |
|---|---|
| CentOS | 5.3 x86_64(インストール直後のもの) |
| update-alternatives | 1.3.30.1 |
update-alternatives とは
長いので使い方のみを知りたい方はこの節は飛ばして、update-alternatives の使い方へどうぞ。
update-alternatives コマンドとは冒頭の通り、
複数のバージョン(または似たような機能)を持つプログラムを切り替える(管理する)コマンド
です。
# which update-alternatives /usr/sbin/update-alternatives # ls -l /usr/sbin/update-alternatives lrwxrwxrwx 1 root root 12 4月 25 02:02 /usr/sbin/update-alternatives -> alternatives |
どうやら、update-alternatives は /usr/sbin/alternatives へのシンボリックリンクのようです。
では、/usr/sbin/alternatives を見てみましょう。
# ls -l /usr/sbin/alternatives -rwxr-xr-x 1 root root 26384 5月 24 2008 /usr/sbin/alternatives |
/usr/sbin/alternatives が本体みたいですね。
ということは、
# update-alternatives |
とコマンドを実行するよりも、
# alternatives |
と実行した方が入力の手間が省けますが、
CentOSの『man alternatives』では”UPDATE-ALTERNATIVES”となっているので、
本エントリでは基本的に update-alternatives として話を進めることにします。
さて、この update-alternatives ですが、
元はDebianの機能だったのが、現在ではRedHat系のディストリビューションにも移植されています。
今回、update-alternatives の機能を説明をするには、
Java が適しているので Java をもとに簡単にどんな機能なのか見ていきたいと思います。
まずは Java の確認
# which java /usr/bin/java # java -version java version "1.6.0" OpenJDK Runtime Environment (build 1.6.0-b09) OpenJDK 64-Bit Server VM (build 1.6.0-b09, mixed mode) |
このことからCentOS 5.3には標準で OpenJDK が入っていることが分かります。
けれど、実はCentOS 5.3にはデフォルトで Java が2種類入っており、
update-alternatives の機能を利用して管理されています。
# update-alternatives --config java 2 プログラムがあり 'java' を提供します。 選択 コマンド ----------------------------------------------- *+ 1 /usr/lib/jvm/jre-1.6.0-openjdk.x86_64/bin/java 2 /usr/lib/jvm/jre-1.4.2-gcj/bin/java Enter を押して現在の選択 [+] を保持するか、選択番号を入力します: |
本来はステータスを参照する場合には --display オプションを使用するのですが、
見やすさのため --config オプションを指定しました。
上記の結果から、
- update-alternatives で管理されている Java グループには OpenJDK と GCJ の2種類がある
- プログラムは OpenJDK の方が選択されているっぽい
ということが何となく分かると思います。
それでは update-alternatives の機能を使って Java グループのプログラムを切り替えてみましょう。
# update-alternatives --config java 2 プログラムがあり 'java' を提供します。 選択 コマンド ----------------------------------------------- *+ 1 /usr/lib/jvm/jre-1.6.0-openjdk.x86_64/bin/java 2 /usr/lib/jvm/jre-1.4.2-gcj/bin/java Enter を押して現在の選択 [+] を保持するか、選択番号を入力します: 2 <---- 入力!! |
では、もう一度 Java の確認を行ってみましょう。
# which java /usr/bin/java # java -version java version "1.4.2" gij (GNU libgcj) version 4.1.2 20080704 (Red Hat 4.1.2-44) Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
同じ /usr/bin/java を実行しているはずなのにさっきと結果が変わりました!!
これは操作上では同じプログラムを実行しているようでも、
実は update-alternatives が裏で頑張ってプログラムを切り替えてくれているからなんです。
このように
- 複数のバージョンの同一のプログラム
- 同じジャンルに分類される複数のプログラム
などを手軽に切り替えて使えるようにするのが update-alternatives の機能となります。
update-alternatives の使い方
update-alternatives の機能が何となく分かったところで使い方を見ていきましょう。
その前に動作モードと用語の説明をしておきます。
| 解説 | |
|---|---|
| 自動 | update-alternatives が優先度で判断して選択肢を変更する状態。 |
| 手動 | rootが行った設定を保持している状態 |
| 説明 | 記述例 | |
|---|---|---|
| グループ名 | update-alternatives で管理されるプログラムのグループ名 | java |
| 実行リンク | update-alternatives の機能を使ってプログラムを実行するためのパス | /usr/bin/java |
| プログラムパス | update-alternatives で管理するプログラム(ファイル)のパス | /usr/java/jdk1.6.0_14/bin/java |
| 優先度 | “自動モード”の場合、優先度が高いものが選択される | 16014 |
グループのプログラムを切り替える
update-alternatives のグループで管理されているプログラムを切り替えます。
update-alternatives --config グループ名
update-alternatives --auto グループ名
update-alternatives --set グループ名 プログラムパス
update-alternatives とはでの Java グループのプログラム切り替えと同様の手順となります。
では、 Java グループの選択プログラムを OpenJDK から GCJ に切り替えてみましょう。
# update-alternatives --config java 2 プログラムがあり 'java' を提供します。 選択 コマンド ----------------------------------------------- *+ 1 /usr/lib/jvm/jre-1.6.0-openjdk.x86_64/bin/java 2 /usr/lib/jvm/jre-1.4.2-gcj/bin/java Enter を押して現在の選択 [+] を保持するか、選択番号を入力します: 2 <---- 入力!! |
もしくは、
# update-alternatives --set java /usr/lib/jvm/jre-1.4.2-gcj/bin/java |
とすることでも切り替わります。
こちらは非対話形式なので、
シェルスクリプトの中でグループの選択プログラムを切り替える際に重宝しそうです。
ちなみに上記の2通りの方法で選択プログラムを切り替えた場合、
グループの動作モードは“手動”に変更されます。
逆に次の方法では、
自動モードに変更することで“優先度が最も高いプログラムを選択”します。
# update-alternatives --auto java |
“自動”モードに設定されることにより、
選択されるプログラムが自動で update-alternatives によって決められることになり優先度の最も高いものが選択されます。
グループにプログラムを追加する
指定したプログラムを update-alternatives のグループに追加します。
update-alternatives --install 実行リンク グループ名 プログラムパス 優先度
SUNの JDK1.6.0_update14(以下jdk1.6.0_14) が /usr/java にインストール済みである状態とします。
おまけ – SUNのJDKをCentOS 5.3にインストールする
# update-alternatives --install /usr/bin/java java /usr/java/jdk1.6.0_14/bin/java 16014 |
何も表示されなかった場合にはグループにプログラムが追加されているはずです。
では早速、update-alternatives で管理されている Java グループのリストを見てみましょう。
# update-alternatives --config java 3 プログラムがあり 'java' を提供します。 選択 コマンド ----------------------------------------------- 1 /usr/lib/jvm/jre-1.6.0-openjdk.x86_64/bin/java + 2 /usr/lib/jvm/jre-1.4.2-gcj/bin/java * 3 /usr/java/jdk1.6.0_14/bin/java Enter を押して現在の選択 [+] を保持するか、選択番号を入力します: |
Java グループの中に jdk1.6.0_14 が追加されているのが確認出来ました。
グループの状態を表示する
update-alternatives で管理されているプログラムの状態を表示します。
update-alternatives --display グループ名
Java グループの詳細を見てみましょう。
# update-alternatives --display java java - ステータスは手動です。 リンクは現在 /usr/lib/jvm/jre-1.4.2-gcj/bin/java を指しています。 /usr/lib/jvm/jre-1.6.0-openjdk.x86_64/bin/java - 優先項目 16000 スレーブ keytool: /usr/lib/jvm/jre-1.6.0-openjdk.x86_64/bin/keytool ~中略~ /usr/lib/jvm/jre-1.4.2-gcj/bin/java - 優先項目 1420 スレーブ keytool: /usr/lib/jvm/jre-1.4.2-gcj/bin/keytool ~中略~ /usr/java/jdk1.6.0_14/bin/java - 優先項目 16014 スレーブ keytool: (null) ~中略~ 現在の「最適」バージョンは /usr/java/jdk1.6.0_14/bin/java です。 |
以上のような詳細な状態の確認をすることができます。
--display オプションで確認できる内容は、
- 現在の動作モード
- 現在グループで選択されているプログラム
- グループに登録されているプログラムとその優先度
- プログラムに関連付けられているスレーブ(後述)
- 自動モード時に選択されるプログラム
となります。
上記の実行結果から、
- OpenJDK と GCJ と jdk1.6.0_14 の計3種類の Java が update-alternatives で管理されている
- OpenJDK の優先度は”16000″
- GCJ の優先度は”1420″
- jdk1.6.0_14 の優先度は”16014″
- 現在の動作モードは”手動”
- 現在、jdk1.6.0_14が選択されている
- 各スレーブの状態
- 自動モードにした場合、jdk1.6.0_14 が選択される(最適バージョン)
ということが読み取れます。
グループからプログラムを削除する
グループに追加済みのプログラムをグループから削除します。
update-alternatives --remove グループ名 プログラムパス
それでは、jdk1.6.0_14 を削除してみましょう。
# update-alternatives --remove java /usr/java/jdk1.6.0_14/bin/java |
きちんと削除されたか確認してみます。
# update-alternatives --config java 2 プログラムがあり 'java' を提供します。 選択 コマンド ----------------------------------------------- * 1 /usr/lib/jvm/jre-1.6.0-openjdk.x86_64/bin/java + 2 /usr/lib/jvm/jre-1.4.2-gcj/bin/java Enter を押して現在の選択 [+] を保持するか、選択番号を入力します: |
きちんとプログラムパスで指定したものが消えていますね。
グループからプログラムを削除する際に、
“自動”モードの場合、選択中のプログラムを削除した場合には、update-alternatives が優先度の大きいものに自動で変更します。
“手動”モードの場合には、プログラム情報を削除するだけで選択情報は変更されないみたいです。
また削除後に選択すべきプログラムが無い場合にはグループが削除されます。
ちなみに、プログラムパスを間違えると次のように怒られちゃいます。
# update-alternatives --remove java /usr/java/jdk1.6.0_14/ /usr/java/jdk1.6.0_14/ は java の為の互換用として設定されていません。 |
RedHat系ディストリビューションでは使えないオプション
Debianにはあっても、
残念ながらRedHat系ディストリビューションでは使えないオプションがあるようです。
--list |
グループ内の管理プログラムを一覧表示する |
|---|---|
--remove-all |
グループごと削除する |
--all |
すべてのグループにたいして --config オプションを呼び出す |
使い道の思い浮かばない --all オプションはともかく、
個人的に --list オプションは欲しかったように思います。
--display オプションがありますが、
グループ内のプログラムを参照するだけであれば --config オプションで見た方が視認性が高いかと思います。
スレーブとは
簡単に言ってしまうと、
グループの選択プログラムが変更されると、スレーブとして登録されたプログラムも同時に変更する
機能です。
update-alternatives --install 実行リンク グループ名 プログラムパス --slave 実行リンク グループ名 プログラムパス
では今までの流れから、
既に jdk1.6.0_14 が入ってる状態に、
更に JDK1.5.0_update19(以下jdk1.5.0_19) を入れてスレーブ機能を使ってみましょう。
jdk1.5.0_19 をインストールする際に、
既に jdk1.6.0_14 をRPMパッケージでインストールしている場合、
古いバージョンをRPMパッケージでインストール出来ないので、
RPMパッケージを使わずに jdk-1_5_0_19-linux-amd64.bin を展開し /usr/java に配置します。
配置出来たら、jdk1.5.0_19 も update-alternatives で管理させます。
# alternatives --install /usr/bin/java java /usr/java/jdk1.5.0_19/bin/java 15019 |
では、早速 jdk1.5.0_19 に切り替えてみましょう。
# alternatives --config java 4 プログラムがあり 'java' を提供します。 選択 コマンド ----------------------------------------------- 1 /usr/lib/jvm/jre-1.6.0-openjdk.x86_64/bin/java 2 /usr/lib/jvm/jre-1.4.2-gcj/bin/java *+ 3 /usr/java/jdk1.6.0_14/bin/java 4 /usr/java/jdk1.5.0_19/bin/java Enter を押して現在の選択 [+] を保持するか、選択番号を入力します:4 |
早速 Java のバージョンを確認。
# java -version java version "1.5.0_19" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_19-b02) Java HotSpot(TM) 64-Bit Server VM (build 1.5.0_19-b02, mixed mode) |
うまく切り替わっているのが確認出来ますね。
しかし、
# javac -version
javac 1.6.0_14 |
Java はうまく切り替わっていても、
javac は jdk1.6.0_14 のものを使ってしまっています。
javac をはじめ、jar や javadoc など Java の変更に伴って同時に変更したいプログラムがいくつかあります。
一つ一つを丁寧に update-alternatives に登録 –> 変更と繰り返すことで解決はしますが、
Java を切り替える度にいくつものその他プログラムを切り替えるのは少々骨が折れる作業となります。
そんな時に活用したいのがスレーブ機能です。
スレーブ機能とは最初に紹介した通り、
グループの選択プログラムが変更されると、スレーブとして登録されたプログラムを同時に変更する
です。
なんだか今回の事例にピッタリな機能ですよね。
では、早速スレーブ機能を使ってみましょう。
# alternatives --install /usr/bin/java java /usr/java/jdk1.5.0_19/bin/java 15019\ --slave /usr/bin/javac javac /usr/java/jdk1.5.0_19/bin/javac |
--install オプションでの追加時に --slave オプションを設定するだけです。
(既にグループにプログラムが登録済みでも上書き出来ます。)
これでスレーブを保持する jdk1.5.0_19 の追加が出来ました。
では、早速 update-alternatives で jdk1.5.0_19 に切り替えて、
javac がどうなっているか確認してみましょう。
(既に jdk1.5.0_19 の場合は、他に変更後、再度 jdk1.5.0_19 に変更してください)
# javac -version
javac 1.5.0_19 |
javac も Java と一緒に更新されていることが確認できました。
このスレーブは --install オプションの設定時に何個でも登録することが出来ます。
複数個の登録の場合には、
# alternatives --install /usr/bin/java java /usr/java/jdk1.5.0_19/bin/java 15019\ --slave /usr/bin/jar jar /usr/java/jdk1.5.0_19/bin/jar\ --slave /usr/bin/javac javac /usr/java/jdk1.5.0_19/bin/javac\ --slave /usr/bin/javadoc javadoc /usr/java/jdk1.5.0_19/bin/javadoc |
のように実行してください。
自分で必要なだけスレーブを追加出来るので、
記述は冗長になってしまいますが毎回1つ1つを変更していくよりもはるかに効率的ですね。
ちなみに、
上記の javac の設定だけだと jdk1.6.0_14 に戻した際に、
javac は変更されないので、
jdk1.6.0_14 にも同様に javac などスレーブを設定する必要があります。
update-alternatives の簡単なファイル構成
ここでは簡単な update-alternatives のファイル構成を解説したいと思います。
alternatives ディレクトリ ( /etc/alternatives )
update-alternatives の Java グループでどのJavaが選択されていても、
一様に /usr/bin/java を操作すれば問題無く任意の Java を実行することが出来ました。
# ls -l /usr/bin/java lrwxrwxrwx 1 root root 22 4月 25 02:04 /usr/bin/java -> /etc/alternatives/java |
この /usr/bin/java が /etc/alternatives/java のシンボリックリンクであることが分かります。
では /etc/alternatives/java も見てみましょう。
# ls -l /etc/alternatives/java lrwxrwxrwx 1 root root 30 8月 3 00:41 /etc/alternatives/java -> /usr/java/jdk1.5.0_19/bin/java |
この /etc/alternatives/java が、
グループで選択されたプログラムの実体のシンボリックリンクになっていることが分かります。
つまり、update-alternatives は、
選択したプログラムのシンボリックリンクを作り替えてプログラムを切り替えているみたいですね。
プログラムを実行すると、
実行リンク —-> /etc/alternatives/グループ名 —-> プログラムパス
のようにプログラム本体を参照しているということになります。
ちなみに /etc/alternatives 以下を参照してみると、
# ls -l /etc/alternatives/ 合計 80 lrwxrwxrwx 1 root root 19 4月 25 02:06 antlr -> /usr/bin/antlr-java lrwxrwxrwx 1 root root 30 8月 3 00:41 java -> /usr/java/jdk1.5.0_19/bin/java lrwxrwxrwx 1 root root 31 8月 3 00:41 javac -> /usr/java/jdk1.5.0_19/bin/javac ~後略~ |
スレーブで設定した javac もこちらで切り替えるためにシンボリックリンクになっているのが分かります。
この alternatives ディレクトリは、
--altdir オプションにより /etc/alternatives から別のディレクトリに変更することが出来ます。
管理ディレクトリ ( /var/lib/alternatives )
プログラムを切り替える仕組みは alternatives ディレクトリで確認出来ますが、
グループのモードやスレーブの関係などの情報は管理ディレクトリを見ることで確認することが出来ます。
例えば、Java グループの各情報は /var/lib/alternatives/java にテキストで格納されています。
この管理ファイルの細かいフォーマット形式はよく分かりませんが、
中身はテキストでそのままのことが書いてあるので何となくの情報は読み取れます。
この管理ディレクトリをよく見ると、
スレーブで設定されたグループ(本エントリでは javac)の情報ファイルは作成されていないようですね。
ちなみにこの 管理ディレクトリは、
--admindir オプションにより /var/lib/alternatives から別のディレクトリに変更することが出来ます。
共通オプション
管理プログラムの操作(アクション)について一通り説明しましたが、
ここでは全アクションに対応する共通オプションについて解説します。
--verbose |
詳細な情報を表示します。 |
|---|---|
--quiet |
エラー以外の情報を表示しません。未実装 |
--test |
指定した操作をテストします。実際には何も更新されません。未実装 |
--help |
update-alternatives に関する簡単な使用方法を表示します。 |
--altdir directory |
alternativesディレクトリ(デフォルト : /etc/alternatives(alternatives)を指定したディレクトリに変更します。 |
--admindir directory |
管理ディレクトリ(デフォルト : /var/lib/alternatives)を指定したディレクトリに変更します。 |
まとめ
さて、ひたすら update-alternatives について説明してみましたがいかがだったでしょうか?
意外と簡単だけど案外知らない人も多い update-alternatives コマンド。
上手に使いこなせれば良い武器になると思います。
ここで、僕のもっぱらの使い方を紹介しましょう。
# update-alternatives --config 彼女 致命的なエラー : 何も登録されていません!!! |
・・・・・・・・・・・orz
参考文献
- update-alternatives(8) – Linux man page
- Linux man – update-alternatives(Debianのmanですが日本語に翻訳されています)
おまけ – SUNのJDKをCentOS 5.3にインストールする
簡単に僕がSUNのJDKをインストールする手順を紹介します。
jdk1.6.0_14 のファイルのURIをSUNのサイトから拾ってきます。
# cd /usr/local/src # wget http://cds.sun.com/ ~中略~ /FileName=/jdk-6u14-linux-x64-rpm.bin 名前が長いのでリネーム # mv jdk-6u14-linux-x64-rpm.bin\ ~中略~ \jdk-6u14-linux-x64-rpm.bin jdk-6u14-linux-x64-rpm.bin # chmod u+x jdk-6u14-linux-x64-rpm.bin # ./jdk-6u14-linux-x64-rpm.bin |
これで /usr/java に jdk1.6.0_14 がインストールされます。
環境変数を設定する場合は ~/.bash_profile に
export JAVA_HOME=/usr/java/default export PATH=$PATH:$JAVA_HOME/bin export CLASSPATH=.:$JAVA_HOME/jre/lib:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar |
とでも記述しておくと良い感じです。




