Mac OSX El CapitanでRuby on RailsからPostgreSQLを使う 前編
Mac OSX 10.11.4 El CapitanにPostgreSQL 9.5.1をインストールしようとして、試行錯誤する羽目に陥ったので記録しておきます。
RailsからPostgreSQLを使うための作業は、後編に書いています。
目次
いかにしてその心情に至ったか
Ruby on Railsチュートリアルを参考にしてWebアプリを作り、Herokuにデプロイしようとしているのですが、Herokuでは標準のデータベースであるPostgreSQLを使うので、MacにもPostgreSQLを入れて、production環境(Herokuにデプロイした状態)とdevelopment環境(自分のPCの開発環境)を同じにしようと考えました。
PostgreSQLをMacにインストールする
まずは、Homebrew
でPostgreSQL
をインストールします。
注:この時点で/usr/local/var/postgres
ディレクトリが既に存在している場合、バージョン違いによるエラーが生じる可能性があります。と言うか、私の環境ではエラーが起きました。エラーが起きた後のなんやかんやは、秘められた罠からの脱出に記載しています。
$brew install postgresql ==> Installing dependencies for postgresql: readline ==> Installing postgresql dependency: readline ==> Downloading https://homebrew.bintray.com/bottles/readline-6.3.8.el_capitan.bottle.tar.gz ######################################################################## 100.0% ==> Pouring readline-6.3.8.el_capitan.bottle.tar.gz ==> Caveats This formula is keg-only, which means it was not symlinked into /usr/local. OS X provides the BSD libedit library, which shadows libreadline. In order to prevent conflicts when programs look for libreadline we are defaulting this GNU Readline installation to keg-only. Generally there are no consequences of this for you. If you build your own software and it requires this formula, youll need to add to your build variables: LDFLAGS: -L/usr/local/opt/readline/lib CPPFLAGS: -I/usr/local/opt/readline/include ==> Summary 🍺 /usr/local/Cellar/readline/6.3.8: 40 files, 2.0M ==> Installing postgresql ==> Downloading https://homebrew.bintray.com/bottles/postgresql-9.5.1.el_capitan.bottle.tar.gz ######################################################################## 100.0% ==> Pouring postgresql-9.5.1.el_capitan.bottle.tar.gz ==> Caveats If builds of PostgreSQL 9 are failing and you have version 8.x installed, you may need to remove the previous version first. See: https://github.com/Homebrew/homebrew/issues/2510 To migrate existing data from a previous major version (pre-9.0) of PostgreSQL, see: http://www.postgresql.org/docs/9.5/static/upgrading.html To migrate existing data from a previous minor version (9.0-9.4) of PosgresSQL, see: http://www.postgresql.org/docs/9.5/static/pgupgrade.html You will need your previous PostgreSQL installation from brew to perform `pg_upgrade`. Do not run `brew cleanup postgresql` until you have performed the migration. To load postgresql: launchctl load ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist Or, if you dont want/need launchctl, you can just run: postgres -D /usr/local/var/postgres ==> Summary 🍺 /usr/local/Cellar/postgresql/9.5.1: 3,118 files, 35M
インストールが終了したようなので、バージョンを確認してみます。
$postgres --version postgres (PostgreSQL) 9.5.1
brew install postgresql
のSummaryに書いてあるとおり、バージョン9.5.1
がインストールされたようです。
PostgreSQLの設定
PostgreSQLデータベースクラスタの作成と初期化
initdb
コマンドで、データベースクラスタ(データベース格納領域)を作成し初期化します。
データベースクラスタを作成するディレクトリは任意の場所を選択できるようですが、今回の開発環境では一般的に使われている/usr/local/var/postgres
ディレクトリに作成します。
また、初期化の際には念のため、エンコーディングをUTF-8
に設定しておきます。
- initdb … PostgreSQLのデータベースクラスタを新しく作成するコマンド
- -E utf8 … データベースのエンコーディングをUTF-8に設定するオプション
- /usr/local/var/postgres … データベースクラスタ(データベース格納領域)を作成するディレクトリ
$initdb -E utf8 /usr/local/var/postgres The files belonging to this database system will be owned by user "b0npu". This user must also own the server process. The database cluster will be initialized with locale "ja_JP.UTF-8". initdb: could not find suitable text search configuration for locale "ja_JP.UTF-8" The default text search configuration will be set to "simple". Data page checksums are disabled. initdb: directory "/usr/local/var/postgres" exists but is not empty If you want to create a new database system, either remove or empty the directory "/usr/local/var/postgres" or run initdb with an argument other than "/usr/local/var/postgres".
UTF-8
でロケール*1の初期化はできたようですが、表示された文字に、Data page checksums are disabled
とかdirectory "/usr/local/var/postgres" exists but is not empty
とか不穏な文字が並んでいる事に不安が隠せません。
調べてみると、Data page checksums are disabled
は-k
オプションによるデータページのチェックサムが有効化されていないために表示され、directory "/usr/local/var/postgres" exists but is not empty
はbrew install postgresql
の時点で、/usr/local/var/postgres
がデータベースクラスタとして作成されているために表示されているようです。
なにわともあれ、データベースクラスタが初期化されたようなのでPostgreSQLサーバを起動して、動作確認を試みます。
注:PostgreSQLサーバの初回起動時にFATALエラーが出現したため、なんやかんやと再インストールすることにしました。
ここから先は、再インストール後の作業の記述です。なんやかんやの部分は、秘められた罠からの脱出に記載しています。
$postgres -D /usr/local/var/postgres LOG: database system was shut down at 2016-04-05 05:17:18 JST LOG: MultiXact member wraparound protections are now enabled LOG: database system is ready to accept connections LOG: autovacuum launcher started
PostgreSQLサーバが無事に起動した*2ようなので、psql
コマンド、でPostgreSQLインタラクティブターミナルの動作確認*3がてらデータベースのリストを表示してみます。
$psql -l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+-------+----------+-------------+-------------+------------------- postgres | b0npu | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8 | template0 | b0npu | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8 | =c/b0npu + | | | | | b0npu=CTc/b0npu template1 | b0npu | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8 | =c/b0npu + | | | | | b0npu=CTc/b0npu (3 rows)
psql
コマンドの動作確認もできましたのでPostgreSQLサーバを停止しようと思ったのですが、SIGTERM
による停止方法しか分からず、動作確認のために起動しただけのプログラムのpid
を調べてkill
するのも面倒なのでctrl+c
で止めます。
^CLOG: received fast shutdown request LOG: aborting any active transactions LOG: autovacuum launcher shutting down LOG: shutting down LOG: database system is shut down
停止できたようですが、LOG: received fast shutdown request
と表示されたのを見ると、ctrl+c
による停止は早計だった気がします。
PostgreSQLの起動と停止を簡単で安全にする
postgres
コマンドでPostgreSQLサーバが起動できましたが、ユーティリティであるpg_ctl
コマンドを使うことで、PostgreSQLサーバを安全で簡単に起動したり停止したりできるそうです。
また、postgres
はデフォルトではPostgreSQLサーバをフォアグランドで起動しますが、pg_ctl
はバックグラウンドで起動するため、PostgreSQLサーバの起動中に別のターミナルウインドウを開いたりする必要もなくなります。
環境変数PGDATAを設定して起動を楽にする
pg_ctl
で楽をするため、シェルの設定ファイル(bash_profileとかzshrc*4とか)にPostgreSQLの環境変数PGDATA
を記述し、デフォルトのデータディレクトリの場所を設定します。
# PostgreSQLで使うデフォルトのデーベースディレクトリを環境変数に設定 export PGDATA=/usr/local/var/postgres
PGDATA
が設定できたので、pg_ctl
でPostgreSQLサーバを起動してみます。
$pg_ctl start server starting $LOG: database system was shut down at 2016-04-05 05:27:49 JST LOG: MultiXact member wraparound protections are now enabled LOG: autovacuum launcher started LOG: database system is ready to accept connections
起動はできたようですが、サーバログのLOG
が変な場所*5に表示されて戸惑いました。
-l
オプションを使用してサーバログの出力先を指定していないと、このように表示される場合があるようです。
また、PGDATA
を設定していない場合や、デフォルトのデータディレクトリ以外のデータベースクラスタを起動したい場合は、起動時に-D
オプションを使用してデータディレクトリを明示する必要があるようです。
なにわともあれ、起動の確認はできたのでサクッと停止します。
$pg_ctl stop waiting for server to shut down...LOG: received fast shutdown request LOG: aborting any active transactions .LOG: autovacuum launcher shutting down LOG: shutting down LOG: database system is shut down done server stopped
どうやら、安全なサーバの停止ができたようです( •̀ㅂ•́)و✧
postgresql.confでサーバログの出力先を設定する
変な場所にサーバログが表示されて戸惑うのを防ぐ*6ため、データディレクトリ/usr/local/val/postgres
の中にある設定ファイルpostgresql.conf
を編集して、サーバログをテキストファイルに出力するように設定します。
pg_ctl
の-l
オプションでサーバログの出力先を指定する方法もあるようですが、サーバを起動させる度にサーバログの出力先を入力するのも面倒なので、設定ファイルを活用します。
$vi /usr/local/val/postgres/postgresql.conf # - Where to Log - log_destination = 'stderr' # Valid values are combinations of # stderr, csvlog, syslog, and eventlog, # depending on platform. csvlog # requires logging_collector to be on. # This is used when logging to stderr: logging_collector = on # Enable capturing of stderr and csvlog # into log files. Required to be on for # csvlogs. # (change requires restart) # These are only used if logging_collector is on: log_directory = 'pg_log' # directory where log files are written, # can be absolute or relative to PGDATA log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' # log file name pattern, # can include strftime() escapes log_file_mode = 0600 # creation mode for log files, # begin with 0 to use octal notation
- log_destination … 標準エラー出力とかsyslogとかの出力先を指定する項目
- logging_collector … log_destinationからテキストファイルへの出力を許可する項目
- log_directory … ログファイルの格納先ディレクトリ*7を設定する
- log_filename … ログファイルのファイル名を指定する項目
- log_file_mode … ログファイルのパーミッションを指定する項目
postgresql.conf
の設定ができたので、PostgreSQLサーバを起動してサーバログのログファイルへの出力を確認します。
$pg_ctl start server starting LOG: redirecting log output to logging collector process HINT: Future log output will appear in directory "pg_log".
サーバ起動時の表示が変わった事に少し喜びつつ、PostgreSQLサーバを停止します。
$pg_ctl stop waiting for server to shut down.... done server stopped
サーバ停止時の表示も変わっていますので、後はログファイルが作成されていれば一段落です。
$ls /usr/local/var/postgres/pg_log postgresql-2016-04-05_054032.log
$more /usr/local/var/postgres/pg_log/postgresql-2016-04-05_054032.log LOG: database system was shut down at 2016-04-05 05:30:39 JST LOG: MultiXact member wraparound protections are now enabled LOG: autovacuum launcher started LOG: database system is ready to accept connections LOG: received fast shutdown request LOG: aborting any active transactions LOG: autovacuum launcher shutting down LOG: shutting down LOG: database system is shut down
できたーヽ(・ω・)/
後編に続きます。
参考:秘められた罠からの脱出
brew install postgresql
でPostgreSQLをインストールしてinitdb
でデータベースクラスタの初期化を実行した後、PostgreSQLを起動しようとしたらエラーに遭遇しました。
$postgres -D /usr/local/var/postgres FATAL: database files are incompatible with server DETAIL: The data directory was initialized by PostgreSQL version 9.4, which is not compatible with this version 9.5.1.
FATAL?(・・;)
よくわかりませんでしたが、バージョン違いでエラーが起きていることは伝わってきたのでFATAL: database files are incompatible with server
でググってみると、こちらの議論に調べ方が色々と載っているのを見つけ、ここを参考にして調査することにしました。
とりあえずディレクトリの情報を表示してみます。
$ls /usr/local/var /usr/local/var/postgres /usr/local/var: cache postgres /usr/local/var/postgres: PG_VERSION pg_clog pg_multixact pg_subtrans postgresql.conf base pg_hba.conf pg_notify pg_xlog postmaster.opts global pg_ident.conf pg_stat_tmp postgresql.auto.conf server.log
バージョン違いとか言われてる割に、postgres
に関係しそうなディレクトリは1つしか無さそうですし、初めて見るディレクトリの中身を見ても正直よくわからないので、別のデータベースクラスタを作成してみることにします。
そういえば、initdb
のdirectory "/usr/local/var/postgres" exists but is not empty
の後にも、If you want to create a new database system, either remove or empty the directory "/usr/local/var/postgres" or run initdb with an argument other than "/usr/local/var/postgres".
とか書いてましたわ。
$initdb -E utf-8 /usr/local/var/postgres9.5 The files belonging to this database system will be owned by user "b0npu". This user must also own the server process. The database cluster will be initialized with locale "ja_JP.UTF-8". initdb: could not find suitable text search configuration for locale "ja_JP.UTF-8" The default text search configuration will be set to "simple". Data page checksums are disabled. creating directory /usr/local/var/postgres9.5 ... ok creating subdirectories ... ok selecting default max_connections ... 100 selecting default shared_buffers ... 128MB selecting dynamic shared memory implementation ... posix creating configuration files ... ok creating template1 database in /usr/local/var/postgres9.5/base/1 ... ok initializing pg_authid ... ok initializing dependencies ... ok creating system views ... ok loading system objects descriptions ... ok creating collations ... ok creating conversions ... ok creating dictionaries ... ok setting privileges on built-in objects ... ok creating information schema ... ok loading PL/pgSQL server-side language ... ok vacuuming database template1 ... ok copying template1 to template0 ... ok copying template1 to postgres ... ok syncing data to disk ... ok WARNING: enabling "trust" authentication for local connections You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb. Success. You can now start the database server using: pg_ctl -D /usr/local/var/postgres9.5 -l logfile start
なんかようさん出てきた(゚Д゚)
新しくデータベースクラスタの/usr/local/var/postgres9.5
が作成され、初期化も出来たようなので、作成されたデータディレクトリの情報を確認してみます。
$ls /usr/local/var /usr/local/var/postgres9.5 /usr/local/var: cache postgres postgres9.5 /usr/local/var/postgres9.5: PG_VERSION pg_dynshmem pg_notify pg_stat_tmp postgresql.auto.conf base pg_hba.conf pg_replslot pg_subtrans postgresql.conf global pg_ident.conf pg_serial pg_tblspc pg_clog pg_logical pg_snapshots pg_twophase pg_commit_ts pg_multixact pg_stat pg_xlog
なんか、さっき見た/usr/local/var/postgres
よりも中身が多い( ゚д゚)
これまでの調査で、PostgreSQLのインストールは出来ていて、データクラスタの作成も出来るけれども、/usr/local/var/postgres
はバージョンが違うから使えなくて、バージョンが違う理由はおそらく私にはわからないという事が分かったので、環境構築作業を前に進めるための手っ取り早い方法を考えます。
『よろしいならば再インストールだ』
先ほどインストールしたばかりのPostgreSQLを、brew uninstall postgresql
します。
$brew uninstall postgresql Uninstalling /usr/local/Cellar/postgresql/9.5.1... (3,118 files, 35M)
念のためディレクトリも削除します。
$rm -rf /usr/local/var/postgres $rm -rf /usr/local/var/postgres9.5
掃除が終わったので、再インストールを試みます。
$brew install postgresql ==> Downloading https://homebrew.bintray.com/bottles/postgresql-9.5.1.el_capitan.bottle.tar.gz Already downloaded: /Library/Caches/Homebrew/postgresql-9.5.1.el_capitan.bottle.tar.gz ==> Pouring postgresql-9.5.1.el_capitan.bottle.tar.gz ==> /usr/local/Cellar/postgresql/9.5.1/bin/initdb /usr/local/var/postgres ==> Caveats If builds of PostgreSQL 9 are failing and you have version 8.x installed, you may need to remove the previous version first. See: https://github.com/Homebrew/homebrew/issues/2510 To migrate existing data from a previous major version (pre-9.0) of PostgreSQL, see: http://www.postgresql.org/docs/9.5/static/upgrading.html To migrate existing data from a previous minor version (9.0-9.4) of PosgresSQL, see: http://www.postgresql.org/docs/9.5/static/pgupgrade.html You will need your previous PostgreSQL installation from brew to perform `pg_upgrade`. Do not run `brew cleanup postgresql` until you have performed the migration. To load postgresql: launchctl load ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist Or, if you dont want/need launchctl, you can just run: postgres -D /usr/local/var/postgres ==> Summary 🍺 /usr/local/Cellar/postgresql/9.5.1: 3,118 files, 35M
最初にインストールした時は、依存関係にあるreadline
とやらもインストールされていましたが、今回はPostgeSQLのみがインストールされたようです。
慣例的に、データベースクラスタの初期化もしておきます。
$initdb -E utf-8 /usr/local/var/postgres The files belonging to this database system will be owned by user "b0npu". This user must also own the server process. The database cluster will be initialized with locale "ja_JP.UTF-8". initdb: could not find suitable text search configuration for locale "ja_JP.UTF-8" The default text search configuration will be set to "simple". Data page checksums are disabled. initdb: directory "/usr/local/var/postgres" exists but is not empty If you want to create a new database system, either remove or empty the directory "/usr/local/var/postgres" or run initdb with an argument other than "/usr/local/var/postgres".
やはりbrew install postgreql
の時点で、データベースクラスタが作成されているようで不穏な文字が並んでいますが、とりあえず初期化も終わったようなので、PostgreSQLサーバを起動してみます。
$postgres -D /usr/local/var/postgres LOG: database system was shut down at 2016-04-05 05:17:18 JST LOG: MultiXact member wraparound protections are now enabled LOG: database system is ready to accept connections LOG: autovacuum launcher started
良かった、無事にPostgreSQLサーバが起動された(´;ω;`)
脱出のまとめ
initdb -E utf-8 /usr/local/var/postgres
で初期化を試みた際の出力の最後の方に、If you want to create a new database system, either remove or empty the directory "/usr/local/var/postgres"
と書かれているので、/usr/local/var/postgres
の中身を削除して新しいデータベースクラスタを作成するだけで良かったかもしれませんが、自分の過去の行いか、若しくは、Mac OSXにデフォルトで作成されていたものだろうと推測しましたので、ディレクトリ自体の削除と再インストールを実施しました。
次からは、一般的に使われているディレクトリに罠が無いか確認してから作業します。
参考記事
PostgreSQLのインストールについては、こちらの記事を参考にさせていただきました。
開発環境
- OSX 10.11.4 El Capitan
- ターミナルエミュレータ: Macターミナル
- シェル: zsh
- パッケージマネージャ: Homebrew - リレーショナルデータベース
- ORDBMS: PostgreSQL 9.5.1
*2:起動時にネットワーク受信接続の許可を求められたので許可してあります
*3:この時はPostgreSQLサーバがフォアグランドで起動したためPostgreSQLサーバを起動させたターミナルウインドウとは別のターミナルウインドウを開いて確認しました
*5:$が表示されて入力待ちになったように見えた後
*6:サーバログの出力先を設定していても出力先のディレクトリが作成されていない場合はサーバの初回起動時に少し変な事になる場合があるようです