はじめに
近頃のLinuxは複数バージョンのアプリケーションを共存させ、簡単にデフォルトバージョン切り替えできるようにするための管理ツールalternativesが用意されている。
今回CentOS 7において、Postgresql 9.x がインストールされた環境で Postgresql 10.x を追加でインストールするとpostgresqlの関連コマンドが10.xものに切り替わらないという問題が発生した。 以降で調査の流れとその解決策を提示する。
環境
- OS: CentOS 7.6.1810 (Dockerコンテナ)
再現手順
再現環境準備
まずDockerコンテナとしてCentOSの環境を構築し、ログインする。
% docker pull centos
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 9f38484d220f 3 months ago 202MB
% docker run --rm -it centos
[root@6c2ed6cf1a10 /]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
調査に利用するコマンドを事前にインストールしておく。
[root@dc85a6cd4673 /]# yum install -y which file
Postgresql 9.x インストール
まず Postgresql 9.x をインストールする。
[root@6c2ed6cf1a10 /]# yum list | egrep '^postgresql(|10)(|-libs)\.x86_64'
postgresql.x86_64 9.2.24-1.el7_5 base
postgresql-libs.x86_64 9.2.24-1.el7_5 base
[root@6c2ed6cf1a10 /]# yum install -y postgresql
…
Installed:
postgresql.x86_64 0:9.2.24-1.el7_5
Dependency Installed:
postgresql-libs.x86_64 0:9.2.24-1.el7_5
Complete!
[root@6c2ed6cf1a10 /]# yum list | egrep '^postgresql(|10)(|-libs)\.x86_64'
postgresql.x86_64 9.2.24-1.el7_5 @base
postgresql-libs.x86_64 9.2.24-1.el7_5 @base
バージョンとインストールされたコマンドの実体を確認。
コマンドやドキュメントなど色々なものがインストールされるが、ここでは代表例としてpsqlコマンドで確認する。
[root@6c2ed6cf1a10 /]# psql -V
psql (PostgreSQL) 9.2.24
[root@6c2ed6cf1a10 /]# which psql
/usr/bin/psql
[root@6c2ed6cf1a10 /]# ls -l /usr/bin/psql
-rwxr-xr-x 1 root root 449320 Aug 23 2018 /usr/bin/psql
[root@6c2ed6cf1a10 /]# file /usr/bin/psql
/usr/bin/psql: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=235f9861cb4f57cf25eb086c3132e11c413b1a2e, stripped
9.xのコマンドであることが確認できる。
またコマンドがalternativesで管理されていないことも確認できる。
[root@6c2ed6cf1a10 /]# alternatives --list | grep pgsql
[root@6c2ed6cf1a10 /]# ls -l /etc/alternatives/pgsql*
ls: cannot access /etc/alternatives/pgsql*: No such file or directory
[root@6c2ed6cf1a10 /]# ls -l /var/lib/alternatives/pgsql*
ls: cannot access /var/lib/alternatives/pgsql*: No such file or directory
Postgresql 10.x インストール
9.xがインストールされた状態で、続けて10.xをインストールする。
10.xはデフォルトのパッケージレポジトリには含まれていなかったので、以下の手順を参考にした。
まずはパッケージレポジトリを追加する。
[root@6c2ed6cf1a10 /]# yum -y localinstall https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-
…
Installed:
pgdg-redhat-repo.noarch 0:42.0-4
Complete!
10.xのパッケージ確認。
[root@6c2ed6cf1a10 /]# yum list | egrep '^postgresql(|10)(|-libs)\.x86_64'
postgresql.x86_64 9.2.24-1.el7_5 @base
postgresql-libs.x86_64 9.2.24-1.el7_5 @base
postgresql10.x86_64 10.8-1PGDG.rhel7 pgdg10
postgresql10-libs.x86_64 10.8-1PGDG.rhel7 pgdg10
10.xのパッケージインストール。
[root@6c2ed6cf1a10 /]# yum install -y postgresql10
…
Installed:
postgresql10.x86_64 0:10.8-1PGDG.rhel7
Dependency Installed:
libicu.x86_64 0:50.1.2-17.el7 postgresql10-libs.x86_64 0:10.8-1PGDG.rhel7 systemd-sysv.x86_64 0:219-62.el7_6.6
Dependency Updated:
systemd.x86_64 0:219-62.el7_6.6 systemd-libs.x86_64 0:219-62.el7_6.6
Complete!
psqlコマンドでバージョン確認。
[root@6c2ed6cf1a10 /]# psql -V
psql (PostgreSQL) 9.2.24
[root@6c2ed6cf1a10 /]# which psql
/usr/bin/psql
[root@6c2ed6cf1a10 /]# ls -l /usr/bin/psql
-rwxr-xr-x 1 root root 449320 Aug 23 2018 /usr/bin/psql
alternativesで管理されるはずだがバージョンは9.xのまま。
コマンドの実体にも変化はない。
alternativesの管理状態を確認。
管理されているように見えるがコマンドは9.xのまま。
[root@6c2ed6cf1a10 /]# alternatives --list | grep pgsql
pgsql-createdb auto /usr/pgsql-10/bin/createdb
pgsql-clusterdbman auto /usr/pgsql-10/share/man/man1/clusterdb.1
pgsql-reindexdb auto /usr/pgsql-10/bin/reindexdb
pgsql-pg_basebackup auto /usr/pgsql-10/bin/pg_basebackup
pgsql-createdbman auto /usr/pgsql-10/share/man/man1/createdb.1
pgsql-createuserman auto /usr/pgsql-10/share/man/man1/createuser.1
pgsql-psqlman auto /usr/pgsql-10/share/man/man1/psql.1
pgsql-pg_dumpman auto /usr/pgsql-10/share/man/man1/pg_dump.1
pgsql-psql auto /usr/pgsql-10/bin/psql
pgsql-vacuumdb auto /usr/pgsql-10/bin/vacuumdb
pgsql-reindexdbman auto /usr/pgsql-10/share/man/man1/reindexdb.1
pgsql-pg_dumpallman auto /usr/pgsql-10/share/man/man1/pg_dumpall.1
pgsql-pg_restoreman auto /usr/pgsql-10/share/man/man1/pg_restore.1
pgsql-pg_dumpall auto /usr/pgsql-10/bin/pg_dumpall
pgsql-dropdbman auto /usr/pgsql-10/share/man/man1/dropdb.1
pgsql-dropuser auto /usr/pgsql-10/bin/dropuser
pgsql-ld-conf auto /usr/pgsql-10/share/postgresql-10-libs.conf
pgsql-pg_basebackupman auto /usr/pgsql-10/share/man/man1/pg_basebackup.1
pgsql-clusterdb auto /usr/pgsql-10/bin/clusterdb
pgsql-pg_dump auto /usr/pgsql-10/bin/pg_dump
pgsql-dropdb auto /usr/pgsql-10/bin/dropdb
pgsql-pg_restore auto /usr/pgsql-10/bin/pg_restore
pgsql-createuser auto /usr/pgsql-10/bin/createuser
pgsql-dropuserman auto /usr/pgsql-10/share/man/man1/dropuser.1
pgsql-vacuumdbman auto /usr/pgsql-10/share/man/man1/vacuumdb.1
[root@6c2ed6cf1a10 /]# ls -l /etc/alternatives/pgsql*
…
lrwxrwxrwx 1 root root 22 Jun 19 09:06 /etc/alternatives/pgsql-psql -> /usr/pgsql-10/bin/psql
…
[root@6c2ed6cf1a10 /]# head /var/lib/alternatives/pgsql*
…
==> /var/lib/alternatives/pgsql-psql <==
auto
/usr/bin/psql
/usr/pgsql-10/bin/psql
1000
…
alternativesはコマンドだけでなく、設定ファイルやmanのドキュメントなども管理していることがわかる。
問題対処
psqlコマンドで言えば、以下のようにリンクが生成され、10.xに紐づくようになっていることが期待される。
/usr/bin/psql
-> /etc/alternatives/pgsql-psql
-> /usr/pgsql-10/bin/psql
しかし実際には/usr/bin/psql
が9.xのバイナリとして存在してしまっているため、alternativesの設定通りに管理できていないと思われる。それを確かめるためにalternatives --auto
コマンドでシンボリックを生成させてみる。
このコマンドは/var/alternatives
配下のコマンド毎の設定に基づきリンクの貼り直しを行ってくれる。
面倒なので、/var/alternatives
配下のpostgresql関連の設定を全て再設定する。
[root@6c2ed6cf1a10 /]# for target in `alternatives --list | cut -f1 | grep pgsql`; do alternatives --verbose --auto ${target}; done
reading /var/lib/alternatives/pgsql-createdb
failed to link /usr/bin/createdb -> /etc/alternatives/pgsql-createdb: /usr/bin/createdb exists and it is not a symlink
reading /var/lib/alternatives/pgsql-clusterdbman
reading /var/lib/alternatives/pgsql-reindexdb
failed to link /usr/bin/reindexdb -> /etc/alternatives/pgsql-reindexdb: /usr/bin/reindexdb exists and it is not a symlink
reading /var/lib/alternatives/pgsql-pg_basebackup
reading /var/lib/alternatives/pgsql-createdbman
reading /var/lib/alternatives/pgsql-createuserman
reading /var/lib/alternatives/pgsql-psqlman
reading /var/lib/alternatives/pgsql-pg_dumpman
reading /var/lib/alternatives/pgsql-psql
failed to link /usr/bin/psql -> /etc/alternatives/pgsql-psql: /usr/bin/psql exists and it is not a symlink
reading /var/lib/alternatives/pgsql-vacuumdb
failed to link /usr/bin/vacuumdb -> /etc/alternatives/pgsql-vacuumdb: /usr/bin/vacuumdb exists and it is not a symlink
reading /var/lib/alternatives/pgsql-reindexdbman
reading /var/lib/alternatives/pgsql-pg_dumpallman
reading /var/lib/alternatives/pgsql-pg_restoreman
reading /var/lib/alternatives/pgsql-pg_dumpall
failed to link /usr/bin/pg_dumpall -> /etc/alternatives/pgsql-pg_dumpall: /usr/bin/pg_dumpall exists and it is not a symlink
reading /var/lib/alternatives/pgsql-dropdbman
reading /var/lib/alternatives/pgsql-dropuser
failed to link /usr/bin/dropuser -> /etc/alternatives/pgsql-dropuser: /usr/bin/dropuser exists and it is not a symlink
reading /var/lib/alternatives/pgsql-ld-conf
reading /var/lib/alternatives/pgsql-pg_basebackupman
reading /var/lib/alternatives/pgsql-clusterdb
failed to link /usr/bin/clusterdb -> /etc/alternatives/pgsql-clusterdb: /usr/bin/clusterdb exists and it is not a symlink
reading /var/lib/alternatives/pgsql-pg_dump
failed to link /usr/bin/pg_dump -> /etc/alternatives/pgsql-pg_dump: /usr/bin/pg_dump exists and it is not a symlink
reading /var/lib/alternatives/pgsql-dropdb
failed to link /usr/bin/dropdb -> /etc/alternatives/pgsql-dropdb: /usr/bin/dropdb exists and it is not a symlink
reading /var/lib/alternatives/pgsql-pg_restore
failed to link /usr/bin/pg_restore -> /etc/alternatives/pgsql-pg_restore: /usr/bin/pg_restore exists and it is not a symlink
reading /var/lib/alternatives/pgsql-createuser
failed to link /usr/bin/createuser -> /etc/alternatives/pgsql-createuser: /usr/bin/createuser exists and it is not a symlink
reading /var/lib/alternatives/pgsql-dropuserman
reading /var/lib/alternatives/pgsql-vacuumdbman
実態があるため登録できない。(失敗していないものは9.xでは用意されていないコマンドだと思われる。)
よって、一旦9.xを削除する。
[root@6c2ed6cf1a10 /]# yum list | egrep '^postgresql(|10)(|-libs)\.x86_64'
postgresql.x86_64 9.2.24-1.el7_5 @base
postgresql-libs.x86_64 9.2.24-1.el7_5 @base
postgresql10.x86_64 10.8-1PGDG.rhel7 @pgdg10
postgresql10-libs.x86_64 10.8-1PGDG.rhel7 @pgdg10
[root@6c2ed6cf1a10 /]# yum remove -y postgresql postgresql-libs
…
Removed:
postgresql.x86_64 0:9.2.24-1.el7_5 postgresql-libs.x86_64 0:9.2.24-1.el7_5
Complete!
[root@6c2ed6cf1a10 /]# yum list | egrep '^postgresql(|10)(|-libs)\.x86_64'
postgresql10.x86_64 10.8-1PGDG.rhel7 @pgdg10
postgresql10-libs.x86_64 10.8-1PGDG.rhel7 @pgdg10
postgresql.x86_64 9.2.24-1.el7_5 base
postgresql-libs.x86_64 9.2.24-1.el7_5 base
9.xを削除すると、実体(psqlコマンドであれば/usr/bin/psql)が消えるだけなので、この時点では10.xにはならない。
[root@6c2ed6cf1a10 /]# psql -V
bash: /usr/bin/psql: No such file or directory
[root@6c2ed6cf1a10 /]# ls -l /usr/bin/psql
ls: cannot access /usr/bin/psql: No such file or directory
実体が消えたところで、alternatives --auto
コマンドでシンボリックを生成させてみる。
[root@6c2ed6cf1a10 /]# for target in `alternatives --list | cut -f1 | grep pgsql`; do alternatives --verbose --auto ${target}; done
reading /var/lib/alternatives/pgsql-createdb
reading /var/lib/alternatives/pgsql-clusterdbman
reading /var/lib/alternatives/pgsql-reindexdb
reading /var/lib/alternatives/pgsql-pg_basebackup
reading /var/lib/alternatives/pgsql-createdbman
reading /var/lib/alternatives/pgsql-createuserman
reading /var/lib/alternatives/pgsql-psqlman
reading /var/lib/alternatives/pgsql-pg_dumpman
reading /var/lib/alternatives/pgsql-psql
reading /var/lib/alternatives/pgsql-vacuumdb
reading /var/lib/alternatives/pgsql-reindexdbman
reading /var/lib/alternatives/pgsql-pg_dumpallman
reading /var/lib/alternatives/pgsql-pg_restoreman
reading /var/lib/alternatives/pgsql-pg_dumpall
reading /var/lib/alternatives/pgsql-dropdbman
reading /var/lib/alternatives/pgsql-dropuser
reading /var/lib/alternatives/pgsql-ld-conf
reading /var/lib/alternatives/pgsql-pg_basebackupman
reading /var/lib/alternatives/pgsql-clusterdb
reading /var/lib/alternatives/pgsql-pg_dump
reading /var/lib/alternatives/pgsql-dropdb
reading /var/lib/alternatives/pgsql-pg_restore
reading /var/lib/alternatives/pgsql-createuser
reading /var/lib/alternatives/pgsql-dropuserman
reading /var/lib/alternatives/pgsql-vacuumdbman
エラーは発生しない。
バージョンが10.xになったことを確認。
[root@6c2ed6cf1a10 /]# psql -V
psql (PostgreSQL) 10.8
[root@6c2ed6cf1a10 /]# which psql
/usr/bin/psql
[root@6c2ed6cf1a10 /]# ls -l /usr/bin/psql
lrwxrwxrwx 1 root root 28 Jun 19 09:18 /usr/bin/psql -> /etc/alternatives/pgsql-psql
alternativesを経由して10.xに紐づいていることがわかる。
まとめ
alternativesで管理されていない9.xがインストースされている環境に10.xをインストールするとコマンド群が9.xを向いたままになってしまう。もし10.xのみ必要な場合は、一旦9.xを削除した上で、以下のコマンドを発行し、紐付けを有効化できる。
# for target in `alternatives --list | cut -f1 | grep pgsql`; do alternatives --verbose --auto ${target}; done
感の良い方は、単純に10.xを再インストールすれば良いだけではと思われると思うが、、、その通りである。
もし10.xのpostgresqlが稼働中で、再インストールはしたくないという状況であれば利用できるかもしれない。
あとがき
なんでこんな実際には起きないだろうという状況の問題解決を書いたかというと、、、
実際に起こった問題を、簡単化しようとして、問題をすり替えてしまったからである。
実際に起こった問題は以下の通り。
- 10.xがインストールされている状態で9.xをインンストール
- 10.xを既に運用していたのに、コマンド群が9.xをさすようになってしまった
- (10.xに戻すために)あわてて9.xを削除したところ、コマンド群が利用できなくなった
- 10.xを再インストールすることなくコマンド群が利用できる状態にしたい
でも状況の説明が難しいし、問題簡単化すればいいかと思って問題の提示方法を変えてしまった。
それによって、その状況なら再インストールすれば良くない?という感じになってしまった。
まあ、alternativeってこんな仕組みなんだということが伝わればいいかなということで、ご勘弁いただければと思う。