[Mac]dyld: Library not loadedでPostgreSQL起動せず


ローカルPCとして使っているMacBook ProでRedmineを使うためにPostgreSQLを起動しようとしたところ、dyld: Library not loadedというエラーメッセージが表示されて起動できなかったので対策しました。

対策の流れ

以下の手順で対策を行いました。

  1. brew upgradeでPostgreSQLをアップグレード
  2. brew postgresql-upgrade-databaseでアップグレード前のPostgreSQLデータベースをアップグレード後のバージョンに対応できるようマイグレーション
  3. brew upgradeの副作用に対する対策)/Users/XXXX/.rbenv/shims/railsに記載のrbenvのバージョンを修正

1.と2.の対策でPostgreSQLは無事に起動するようになりました。
brew upgradeでPostgreSQLをアップグレードした際に一緒にrbenvまでアップグレードされたので、Redmineを起動するためには3.の対策が必要となりました。

以下に詳細な検討結果を記載します。

不具合発生状況

Redmineを使うために、データベースとして使っているPostgreSQLを起動しようとしたところ、以下のエラーが発生して起動できませんでした。

$ postgres -D /usr/local/var/postgres/
dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.62.dylib
  Referenced from: /usr/local/bin/postgres
  Reason: image not found
Abort trap: 6

原因

Dynamic Loaderと呼ばれる、共有ライブラリをロードしたりリンクしたりするためのファイルdyldが(気が付かないうちに)アップデートされていて、ファイル名が変わっていたことが原因でした。
おそらく最近何度か実施していたmacOSのシステムアップデートの際に置き換わったのだと思います。

dyld: Library not loadedというエラーメッセージが示すファイルlibicui18n.62.dylibのディレクトリを見てみると、以下のようにファイル名がlibicui18n.62.dylibからlibicui18n.63.dylibのように変わっていました。

$ ls /usr/local/opt/icu4c/lib/
icu         libicui18n.63.dylib libicuio.dylib      libicutu.63.dylib   libicuuc.dylib
libicudata.63.1.dylib   libicui18n.a        libicutest.63.1.dylib   libicutu.a      pkgconfig
libicudata.63.dylib libicui18n.dylib    libicutest.63.dylib libicutu.dylib
libicudata.a        libicuio.63.1.dylib libicutest.a        libicuuc.63.1.dylib
libicudata.dylib    libicuio.63.dylib   libicutest.dylib    libicuuc.63.dylib
libicui18n.63.1.dylib   libicuio.a      libicutu.63.1.dylib libicuuc.a

PostgreSQLからlibicui18n.62.dylibを参照しに行っている箇所を書き換えれば直るのでしょうが、ピンポイントにどこをどう書き換えるかわからなかったので、Homebrewを使ってPostgreSQLをまるごとアップグレードしてやることにしました。

対策1. brew upgradeでPostgreSQLをアップグレード

brew upgradeでアップグレードを試みました。

$ brew upgrade
Updating Homebrew...
(以下、ログを抜粋)
==> Upgrading 15 outdated packages:
libtiff 4.0.9_4 -> 4.0.10_1, postgresql 10.5 -> 11.2, imagemagick@6 6.9.10-11_1 -> 6.9.10-27, libpng 1.6.35 -> 1.6.36, heroku/brew/heroku 7.19.4 -> 7.22.9, freetype 2.9.1 -> 2.10.0, redis 4.0.11 -> 5.0.4, readline 7.0.5 -> 8.0.0, ruby-build 20180822 -> 20190401, memcached 1.5.10 -> 1.5.12, heroku/brew/heroku-node 11.3.0 -> 11.10.1, node 11.12.0 -> 11.13.0, openssl 1.0.2p -> 1.0.2r, elasticsearch 6.2.4 -> 6.7.0, rbenv 1.1.1 -> 1.1.2

==> postgresql
To migrate existing data from a previous major version of PostgreSQL run:
  brew postgresql-upgrade-database

To have launchd start postgresql now and restart at login:
  brew services start postgresql
Or, if you dont want/need a background service you can just run:
  pg_ctl -D /usr/local/var/postgres start

PostgreSQLは10.5から11.2にアップグレードされました。
しかし、PostgreSQLを起動しようとすると、またしてもエラーが発生しました。

$ pg_ctl -D /usr/local/var/postgres/ start
waiting for server to start....2019-04-09 10:55:56.386 JST [24116] FATAL:  database files are incompatible with server
2019-04-09 10:55:56.386 JST [24116] DETAIL:  The data directory was initialized by PostgreSQL version 10, which is not compatible with this version 11.2.
 stopped waiting
pg_ctl: could not start server
Examine the log output.

アップグレード前の10.5で初期化されたデータベースが、アップグレード後の11.2とコンパチではないとのこと。

対策2. brew postgresql-upgrade-databaseでアップグレード前のPostgreSQLデータベースをアップグレード後のバージョンに対応できるようマイグレーション

brew upgradeのときのログをよく読んでみると、前のメジャーバージョンからデータをマイグレーションするためのコマンドが示されていました。

To migrate existing data from a previous major version of PostgreSQL run:
brew postgresql-upgrade-database

これをそのまま実行すると無事にマイグレーションされ、PostgreSQLが起動できるようになりました。

$ brew postgresql-upgrade-database
$ postgres -D /usr/local/var/postgres/

これでPostgreSQLが起動しない問題については一件落着だったのですが、もともとやりたかったRedmineの起動を行ったところ、以下のエラーが発生してしまいました。

$ RAILS_ENV=production rails s
/Users/XXXX/.rbenv/shims/rails: line 21: /usr/local/Cellar/rbenv/1.1.1/libexec/rbenv: No such file or directory

rbenvへのリンクがエラーの原因のようです。

対策3. (brew upgradeの副作用に対する対策)/Users/XXXX/.rbenv/shims/railsに記載のrbenvのバージョンを修正

これはさきほどのbrew upgradeの副作用として、rbenvがアップグレードされたことに起因するエラーとなっています。
brew upgradeのときのログを再び見直してみると、rbenv1.1.1から1.1.2に上がっていました。

$ brew upgrade
Updating Homebrew...
(以下、ログを抜粋)
==> Upgrading rbenv
==> Downloading https://homebrew.bintray.com/bottles/rbenv-1.1.2.mojave.bottle.tar.gz
######################################################################## 100.0%
==> Pouring rbenv-1.1.2.mojave.bottle.tar.gz
🍺  /usr/local/Cellar/rbenv/1.1.2: 36 files, 65KB
Removing: /usr/local/Cellar/rbenv/1.1.1... (36 files, 62.7KB)

ログを見ると、すでに1.1.1は削除されています。
エラーメッセージからも明らかなように/Users/XXXX/.rbenv/shims/railsの21行目で参照している1.1.1を1.1.2に書き換えてやりました。

/Users/XXXX/.rbenv/shims/rails
exec "/usr/local/Cellar/rbenv/1.1.2/libexec/rbenv" exec "$program" "$@"

echoコマンドとかで書き換えるのが通例かもしれませんが、書き換わったことを確認したいのでvimで開いて直接編集しました。

これで無事にrails sでRedmineを起動することができ、最初の目的を達成することができました。

所感

環境構築に関する課題は、しばしばプログラミング以上に頭の痛い問題として立ちはだかってきますが、「ピンポイントに解決しようとするとドツボにはまりそうだからHomebrewにまかせてしまおう」とか、「素直にファイルを書き換えれば簡単に直りそう」とかいった判断の勘所を掴めるようになってきているようです。

今まではトラブルが発生すると思考停止して為すすべがなく、ひたすらググって途方に暮れていましたが、環境構築についても徐々に成長してきていることを実感して嬉しく思ったので記事にしてみました。