とーますメモ

Ruby on Rails / Goなどの学習メモ

【Rails5】Systemdを使用したPumaの自動起動設定

自分用メモ。

Systemctlは、Systemdを管理するためのコマンド。
Systemdは、デーモンプロセスを自動立ち上げるるために使用される。
以下のサイトが詳しい。
Systemd メモ書き
いまだにsysvinitの手癖が抜けない人のためのsystemd
Linux女子部 systemd徹底入門

前提

Capistrano3を使用し、デプロイしていることが前提。
公式を見ると、Systemd用の設定が載っていたので
以下のページを参考に設定する。
puma/systemd.md at master · puma/puma · GitHub

公式には、「Type=simple」での設定例、「Type=forking」での設定例が存在するが
「Type=forking」の場合は、サービスが落ちたときなど自動で再起動する機能が使用できないため、
ここでは「Type=simple」での設定を行うこととする。

but is not performing continuous restarts. Therefore running Puma in cluster mode, where the master can restart workers, is highly recommended.

by puma/systemd.md at master · puma/puma · GitHub

またこの設定を使用する場合、Capistranoで「capistrano/puma」を読み込んでいて、且つ「set :puma_daemonize, ture」を設定している場合は必ず「set :puma_daemonize, false」もしくは、設定自体を削除すること!

[参考]
Puma silently exits after "Daemonizing..." from systemd script · Issue #941 · puma/puma · GitHub


deploy.rb

# before
set :puma_daemonize, true
# after
set :puma_daemonize, false

これを設定していると、puma.serviceが動作せず、後述するjournalctlのログには「No Pid 'xxxxx' found」というエラーが表示される。

puma.serviceの作成

「/etc/systemd/system/」内に「puma.service」というファイルを作成

$ cd /etc/systemd/system/
$ vim puma.service

puma.serviceには以下の内容を設定。
{{ working_directory }}はcapistranoの「xxx/current」を指定
{{ shared_directory }}はcapistranoの「xxx/shared」を指定

またsystemdは.barshrcや.bash_profileを読み込まないので
ExecStartには「/bin/bash -lc」でログインシェルを読み込む、.bashrcを読み込む設定にした。
[SOLVED] Where to put environment vars regarding SystemD / System Administration / Arch Linux Forums

[Unit]
Description=Puma Application Server
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory={{ working_directory }}
ExecStart=/bin/bash -lc "/root/.rbenv/bin/rbenv exec bundle exec puma -C {{ shared_directory }}/puma.rb"
ExecStop=/root/.rbenv/bin/rbenv exec bundle exec pumactl -S {{ shared_directory }}/tmp/pids/puma.state stop
TimeoutSec=300
Restart=always

[Install]
WantedBy=multi-user.target

Restartをalwaysにすることで、サービスの再起動を行う。例えばサーバリスタート時や、何らかの理由でpumaが異常終了したとしても自動的に起動する。
※stopで止めた場合は、再起動しない。
WantedBy=multi-user.targetはランレベル3で動作することを意味する。

※forkingを使用する場合は、以下のようにPIDFileを設定する必要がある。

PIDFile={{ shared_directory }}/tmp/pids/puma.pid

systemctlコマンド

# puma.serviceを新規作成後または変更後はこのコマンドを叩かないと反映されない。
systemctl daemon-reload

# 有効化
systemctl enable puma.service

# 起動
systemctl start puma.service

# 停止
systemctl stop puma.service

# ステータス確認
systemctl status puma.service

# 再起動
systemctl restart puma.service

Journalctlコマンド

Systemdのログは、Journalctlコマンドを利用することで確認できる。

journalctl

  • u (Unit): 指定ユニットに関係するログのみ表示
  • b: 直前のサーバ起動以降のログを表示
  • f: tail -f のように、順次表示する
    • no-pager: less コマンドを使用しない
  • a : 長いメッセージを省略しない
    • since='YYYY-MM-DD hh:mm:ss': 指定日以降のログ表示
    • until='YYYY-MM-DD hh:mm:ss': 指定日までのログ表示

by
Systemd メモ書き

自分の場合は、よく以下を使用する。

pumaのログだけを、リアルタイムで確認

$ journalctl -f -u puma

その他所感

capistrano/pumaを読み込んだ状態で、Capistranoを利用しデプロイすると
以下のコマンドが流れる。

$HOME/.rbenv/bin/rbenv exec bundle exec puma -C /var/www/recipe_post/shared/puma.rb --daemon

見ての通り、「--daemon」がついているため、デーモン化されて動作する。
これを変更したりすることは現時点では無理そう。
なぜならpuma.rakeに固定して記述されているため。

以下ページのソースを参照。
capistrano-puma/puma.rake at master · seuros/capistrano-puma · GitHub


[その他参考]
Pumaをsystemdで起動するメモ
Manage Puma with systemd on Ubuntu 16.04 and rbenv · GitHub
「Systemd」を理解する ーシステム管理編ー | ギークを目指して
Systemd入門(4) - serviceタイプUnitの設定ファイル - めもめも
CentOS7系と6系のコマンドの違いについて

【Rails5】アセットパイプライン(Asset Pipeline)についてのまとめ

自分用メモ。

そもそもアセットパイプラインのプリコンパイルとは?

プリコンパイルは、複数のファイルをいっこにまとめて、圧縮して、ファイル名にフィンガープリント(ダイジェスト)をつけて、公開ディレクトリにデプロイする、などの作業と解釈してます。
プリコンパイルされていないアセットは、production環境では見ることができません。配信したいアセットがプリコンパイルの対象になっていることを確認する必要があります。

by Rails Asset Pipelineがうまくいかないときの問題の切り分けかた


自分が思っているProduction環境でのアセットパイプラインの流れ

1)コンパイル対象のファイル(デフォルトだとapplication.jsとapplication.css)を追加
追加することでパイプラインで生成されるファイルを増やすことができる。

2)アセット対象のパスを追加
追加することでコンパイル対象ファイル内に記述することができる。

3)パイプラインから生成されたファイルをstylesheet_link_tagやjavascript_include_tagで読み込む

アセット対象のパスを追加

config/initializers/assets.rb内

Rails.application.config.assets.paths << Rails.root.join("vendor", "original_assets", "images")
Rails.application.config.assets.paths << Rails.root.join("vendor", "original_assets", "stylesheets")
Rails.application.config.assets.paths << Rails.root.join("vendor", "original_assets", "javascripts")

指定したファイルをコンパイル対象にする

Rails.application.config.assets.precompile += %w( user.js admin.js user.css admin.css )

フォント系の問題

外部ライブラリのCSSファイル内で相対パスで書いてある場合、Production環境だと
CSSがapplication.cssに集約されるため、フォントが読み込めなくなる。
その場合は、「絶対パス」に変更するなどの対応が必要になる。

その他トラブルシューティング

以下参照。
Rails Asset Pipelineがうまくいかないときの問題の切り分けかた

作成されたアセットファイル群を消す方法

$ bundle exec rake assets:clobber

現在設定されているassetsのパス

$ bundle exec spring rails c
$> Rails.application.config.assets.paths

プレコンパイル済みのアセットが配置されるディレクトリ

$ bundle exec spring rails c
$> Rails.application.config.assets.prefix

【Rails】Production環境のために必要な設定

自分用メモ。

1)環境変数の設定
以下の環境変数を「.bashrc」に設定。※Capistranoで読み込む環境変数の場合、.bash_profileだと読み込んでくれないため。
以下の詳細。
thoames.hatenadiary.jp

①RAILS_ENV(設定しておけば、コマンドで逐一入れなくても良くなる)
②DATABASE_PASSWORD(production環境のDBに接続するためのパスワード)
③SECRET_KEY_BASE(秘密鍵の設定)

2)assets:precompileの設定

5.1からyarnが必須になったっぽい。
npmをインストールし、yarnを以下のようにインストールすれば良い。

$ npm install yarn -g

3)config/environments/production.rbの設定

config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?

config.public_file_server.enabled = true

に変更

[参考]
Rails5でnginx+pumaでproduction環境を構築する · atwata developer blog

【Capistrano】環境変数が読み込まれない!? その場合の対応方法

自分用メモ。

環境変数を「.bash_profile」に設定した場合
読み込まれなかったため、原因を検索してみたら以下の記事がひかかった。

Capistrano で.bash_profileに書いてある環境変数が読まれない件
ruby on rails - Capistrano and environment variables - Stack Overflow

どうやらCapistranoは.bash_profileは読み込ま長い、.bashrcは読み込むらしい。

ただ注意しないといけないのは、以下の行より「上」に環境変数を設定しないといけないこと。

# If not running interactively, don't do anything
[ -z "$PS1" ] && return


話は変わるが、以下のようにCapistrano自体に環境変数の設定をすることも可能っぽい。

set :default_environment, { 
  'env_var1' => 'value1',
  'env_var2' => 'value2'
}

またデバックとして、「require 'capistrano/console'」をCapfileに入れることで
以下のコマンドが使用でき、Capistranoと同じ条件で、サーバに入ることができる。

例)production環境に入る例

$ bundle exec cap production console


[参考]
Capistrano で.bash_profileに書いてある環境変数が読まれない件

【Rails】Mac上でImagemagick + RMagickをインストール

Imagemagickはコマンドラインから画像の操作や表示ができるツール。
多くのOS及び言語から使用できるため人気がある。

RMagickはRuby用のImagemagickインターフェース。
RubyからImagemagickを使用する場合は、このgemをインストールする。

Imagemagickのインストール

RMagickはimagemagickのバージョン6にしか対応していないので
バージョン6をインストール。

$ brew install imagemagick@6

パスを.bash_profileに設定

export PATH="/usr/local/opt/imagemagick@6/bin:$PATH"
$ source ~/.bash_profile

以下のコマンドでバージョン情報が表示されれば、インストール完了

$ convert --version

RMagickのインストール

インストール

gem 'carrierwave'
gem 'rmagick'

このままインストールすると、以下のエラーが出てインストールできない。

Package MagickCore was not found in the pkg-config search path.
Perhaps you should add the directory containing `MagickCore.pc'
to the PKG_CONFIG_PATH environment variable
No package 'MagickCore' found

MagickCore.pcが含まれるパスであるPKG_CONFIG_PATHを
環境変数に設定する必要がある。

.bash_profile

export PKG_CONFIG_PATH="/usr/local/opt/imagemagick@6/lib/pkgconfig:$PATH"
$ source ./bash_profile

インストール

$ bundle install

[参考]
Macにrmagickをインストールする - Qiita
RMagickのインストールでエラー - Qiita

【Ansible】Macのbrew経由でAnsibleのバージョンを上げたら、ansible.cfgを読み込まなくなったっぽい。

自分用メモ。

以前はansible.cfgを「/usr/local/bin/ansible/ansible.cfg」に置いており、
「/usr/local/bin/ansible/」内に「apps」ディレクトリを作成し、
さらにその中に各プロジェクトのディレクトリを作成し、プレイブックをその中に置いていた。

こんなイメージ

├── apps
│   └── project1
│       ├── hosts
│       │   ├── production
│       │   └── staging
│       ├── log
│       │   └── ansible.log
│       └── playbook
│           ├── dbservers.yml
│           ├── group_vars
│           │   ├── production.yml
│           │   └── staging.yml
│           ├── roles
├── ansible.cfg

実行するときは、各プロジェクト内に移動し、その後にプレイブックをのコマンドを叩いていた。

例)

$ cd apps/project1 && ansible-playbook -i hosts/staging playbook/site.yml

以前(バージョンは忘れた・・・2.2とかだった気がする)は、上記の構成とコマンドでansible.cfg内の設定を
読み込んでくれていたが、バージョンを2.5.3に上げたら、読み込まなくなりansible.cfg内で設定していたremote_userが効かなくなったため
サーバにSSHログインできなくなった。

公式ドキュメントを見ると、以下の順でansible.cfgは読み込まれる。

① ANSIBLE_CONFIG (environment variable if set)
② ansible.cfg (in the current directory)
③ ~/.ansible.cfg (in the home directory)
④ /etc/ansible/ansible.cfg

Ansible Configuration Settings — Ansible Documentation

このドキュメントを見ると、そもそもプロジェクトのフォルダに移動して、コマンドを実行してもansible.cfgは読み込まれないように見えるが
以前のバージョンでは動作していた。。。

なので、ansible.cfgを各プロジェクト内直下に置き、実行してみたところ動作した。
以下がその構成。

├── apps
│   └── project1
│       ├── ansible.cfg
│       ├── hosts
│       │   ├── production
│       │   └── staging
│       ├── log
│       │   └── ansible.log
│       └── playbook
│           ├── dbservers.yml
│           ├── group_vars
│           │   ├── production.yml
│           │   └── staging.yml
│           ├── roles

[参考]
Ansible: path to ansible.cfg - Stack Overflow