Linux(CentOS)でlocaleのエラーが出た
出たので調べた。
環境
OS X 上の Vagrant/VirtualBox 上の CentOS。
$ cat /etc/redhat-release CentOS release 6.5 (Final) $ arch x86_64 $ uname -a Linux vagrant-centos65.vagrantup.com 2.6.32-431.3.1.el6.x86_64 #1 SMP Fri Jan 3 21:39:27 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
参考:CentOSのバージョン確認コマンドとアーキテクチャ確認コマンド | mawatari.jp
事象
yumコマンドとかlocaleコマンドとかいろいろなコマンドの実行時に以下のようなエラーが出ていた。
$ locale locale: Cannot set LC_CTYPE to default locale: No such file or directory locale: Cannot set LC_MESSAGES to default locale: No such file or directory locale: Cannot set LC_ALL to default locale: No such file or directory LANG=ja_JP.UTF-8 LC_CTYPE="ja_JP.UTF-8" LC_NUMERIC="ja_JP.UTF-8" LC_TIME="ja_JP.UTF-8" LC_COLLATE="ja_JP.UTF-8" LC_MONETARY="ja_JP.UTF-8" LC_MESSAGES="ja_JP.UTF-8" LC_PAPER="ja_JP.UTF-8" LC_NAME="ja_JP.UTF-8" LC_ADDRESS="ja_JP.UTF-8" LC_TELEPHONE="ja_JP.UTF-8" LC_MEASUREMENT="ja_JP.UTF-8" LC_IDENTIFICATION="ja_JP.UTF-8" LC_ALL=
原因
localeのLC_*に設定されているja_JP.UTF-8がシステムに無い。
Macではデフォルトでssh時にMac上のLC_*の設定を接続先に送るようになってる(/etc/ssh_config
内のSendEnv LANG LC_*
)ため、Mac上でja_JP.UTF-8
になってると上記のようになる。
参考:Mac から Ubuntu に ssh ログインするとなんかロケール云々で怒られるやつ - 休刊 ボルシチは食べ物です。
対策
以下で解決した。
$ sudo yum update glibc-common
参考:開発機の仮想マシンで locale が怒られる - @Konboi memo
上のエラー文字列で調べるといろいろヒットして、
とかいくつか解決法が見つかって、確かにこれらでも解決する(下だけ試した)んだけど、なんとなく本来的な解決法じゃないような気がした。(好みの問題かもしれない)
で、どうしよっかなーと思ってたら上のglibc-commonをアップデートしたらいいというページを見つけたのでこれだ!って思った。
要は最初からsudo yum update -y
しとけばよかったんだな。
そもそもlocaleって?
ちゃんと調べたことなかったので、この際に調べてみた。
ロケールとは、ソフトウェアに内蔵される、言語や国・地域ごとに異なる単位、記号、日付、通貨などの表記規則の集合。または単に、利用する言語や国・地域の指定。多くのソフトウェアやプログラミング言語は、使用する言語とともにロケールを設定し、ロケールで定められた方式に基づいてデータの表記や処理を行う。
LC_ALLを設定するとLC_CTYPEなどの個別の設定を全部上書きする。LC_ALLも個別のLC_CTYPEなども設定されていない場合、LANGの値が使用される。
LC_CTYPEとかLC_NUMERICとかのそれぞれ意味は以下のリンクを参照。
Linux Hacks:環境変数によるロケールの管理 (1/2) - ITmedia エンタープライズ
ロケール名は以下の形式になる。
language(_territory)(.encoding)(@modifier)
ja_JP.UTF-8
だと、languageがja、territoryがJP、encodingがUTF-8になる。@modifierが何かとかは上のリンク参考。
"C"ロケールは、
Cロケールとしてもよく知られているPOSIXロケールは、伝統的なUNIX環境を設定するもので、ASCIIエンコーディング、POSIX文字クラス、米国英語の日時、数、通貨の書式を用いる。
とのこと。
localeコマンドの簡単な使い方は以下の通り。
ほか
今回自分はやらなかったけど、manの内容とかも日本語化したければ以下のページが参考になりそう。
VagrantのCentOSを日本語化してみる - yk5656 diary
Linuxシステム[実践]入門 (Software Design plus)
- 作者: 沓名亮典
- 出版社/メーカー: 技術評論社
- 発売日: 2013/07/03
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (13件) を見る
新Linux/UNIX入門 第3版 (林晴比古実用マスターシリーズ)
- 作者: 林晴比古
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2012/07/04
- メディア: 大型本
- クリック: 4回
- この商品を含むブログ (8件) を見る
Unicornの設定をする
昨日↓に引き続き、
一昨日↓の設定ファイルの見直しをする。
今日はUnicorn。
完成形
以下のようにした。
ほぼ、以下二つのページのコピペ。
アプリのルート/config/unicorn.rb
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3) timeout 15 preload_app true listen '/tmp/unicorn.sock' pid '/tmp/unicorn.pid' before_fork do |server, worker| Signal.trap 'TERM' do puts 'Unicorn master intercepting TERM and sending myself QUIT instead' Process.kill 'QUIT', Process.pid end defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect! end after_fork do |server, worker| Signal.trap 'TERM' do puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT' end defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection end
設定内容
上に挙げた二つのリンクだけど、一つ目のリンク先も二つ目を参考にしているとのことなので、結局この設定のベースは二つ目のページになる。
それで二つ目のページは、Heroku Dev Centerの日本語訳なので、Herokuにデプロイする前提の設定例になっているんだけど、基本的にはHerokuじゃなくても使えるだろうと思ってそのまま流用している。
以下では個々の設定内容について自分の理解を簡単に書くけれど、上記Heroku Dev Centerの劣化コピー的な内容でしかないので詳細はそっちを参照することを推奨。
worker_processes
Unicornは、リクエストを振り分ける一つのmasterプロセスと、実際にリクエストを処理する複数のworkerプロセスで構成されるアーキテクチャになっている。
worker_processes
はworkerプロセスの数を指定する。
実際のアプリのメモリ使用量などを見ながらworker数を調節できるように、環境変数を指定できるようにしてあるとのこと。
timeout
timeoutの秒数。
preload_app
trueを指定するとアプリを事前に読み込む。こうすることでworkerプロセスの起動時間を短縮できる。
Signal.trap 'TERM'
UnicornはQUITシグナルを受け取ったときにグレースフルシャットダウンするので、TERMを受け取ったときに適切なアクションに切り替える設定をしている。
QUIT 時には、現在のリクエスト処理が終わるのを待ってからmasterが各workerをシャットダウンし、最後に自身をシャットダウンする。そのため、適切なアクションとは、masterの場合は自身にQUITを送ってシャットダウン処理を開始すること、workerの場合は(masterからシャットダウン指令が来るので)TERMは無視すること、になっている。
defined?(ActiveRecord::Base)らへん
あんまりよくわかっていない。
ActiveRecordを使うなら必要そうだからつけてる。。
まとめ
とりあえずこれで良い…のかな。
Unicorn用のNginxの設定をする
nginx.confを昨日いい加減に書いたので、
設定を見直す。
昨日の書いたのは以下。
nginx.conf
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; upstream unicorn_app { server unix:/tmp/unicorn.sock; } server { listen 80; server_name _; location / { proxy_pass http://unicorn_app; } } }
以下を参考にした。
- nginx documentation
- nginx wiki
- nginx連載4回目: nginxの設定、その2 - バーチャルサーバの設定 - インフラエンジニアway - Powered by HEARTBEATS
- nginx設定メモ - おおにしあきらの日記
serverブロックを別ファイルにする
まず、初期状態のnginx.confのhttpブロックはこうなってる。
http { ... include /etc/nginx/conf.d/*.conf; }
各サーバの設定はconf.d以下にサーバごとにファイルを分けて格納するのがより良い方法なのだろう。
ということで、新たにconf.d/rails_app.confを作って、upstreamブロックとserverブロックをそっちに移動する。
rails_app.conf
upstream unicorn_app { server unix:/tmp/unicorn.sock; } server { listen 80; server_name _; location / { proxy_pass http://unicorn_app; } }
nginx.confは初期状態の、conf.d以下をincludeする形に戻す。
ここまでで一旦動作確認する。本質的には設定内容は変わってないはずなので、問題なく動くはず。
$ unicorn_rails -c config/unicorn.rb
conf.d以下に最初からあるファイル(default.conf、example_ssl.conf)はファイル名末尾に.bkとかを付けてincludeしないようにしておいた。
設定内容の意味を知る
だいたい見た目から予想はつくものの、昨日の時点ではちゃんと調べずに書いてたので、ちょっと調べた。
upstream
Wikiにはこう書いてある。
Defines a group of servers. Servers can listen on different ports.
Module ngx_http_upstream_module
サーバグループを定義するやつみたい。
今回のように一つだけ書く場合には、ただ単に後ろで参照するための名前を付けているのと同じだと思う。
試しにupstreamの内容を後方のproxy_passに直接書いてみる。
rails_app.conf
#upstream unicorn_app { # server unix:/tmp/unicorn.sock; #} server { listen 80; server_name _; location / { #proxy_pass http://unicorn_app; proxy_pass http://unix:/tmp/unicorn.sock; } }
リロード。
$ sudo nginx -s reload $ unicorn_rails -c config/unicorn.rb
問題なく表示された。元に戻しておく。
listen
これは見た目通りリッスンするポート番号だろう。
Sets the address and port for IP, or the path for a UNIX-domain socket on which the server will accept requests.
サーバが受け入れるリクエストのアドレスとポート、またはUNIXドメインソケットのパス。
それはまあそうなんだけど、気になるのはデフォルト。
If the directive is not present then either :80 is used if nginx runs with the superuser privileges, or :8000 otherwise.
とのことなので、superuser権限で実行してたらデフォルトで*:80が使われる。
ということはlisten 80;
の行は要らないから消しちゃおう。
リロード。問題なし。
server_name
これも見た目通り。
Server names are defined using the server_name directive and determine which server block is used for a given request.
nginxはこのリクエストを受け取ると、このホスト名がserver_nameディレクティブに設定したサーバ名に一致するserverディレクティブのバーチャルサーバを選び、そのserverディレクティブ内の設定が適応されます。
nginx連載4回目: nginxの設定、その2 - バーチャルサーバの設定 - インフラエンジニアway - Powered by HEARTBEATS
指定してあるアンダースコア(_
)は全部に一致するやつ。
In catch-all server examples the strange name “_” can be seen:
最初はこれもアンダースコアがデフォルトかと思ったけど、デフォルトは""
だった。
Default: server_name "";
It allows this server to process requests without the “Host” header field
空を意味する""を設定すると、Host:ヘッダ フィールドがない場合に一致します。
nginx連載4回目: nginxの設定、その2 - バーチャルサーバの設定 - インフラエンジニアway - Powered by HEARTBEATS
""
の場合にはHostヘッダフィールドがない場合に一致となっているので、server_name _;
の行を削除すると動かないかと思ったけど、動いた。server_name hoge;
とかにしてみても動いた。
なんでだろうと思ったけど、
複数のバーチャルサーバがあるときには、リクエストのHost:ヘッダ フィールドのホスト名がserver_nameディレクティブのサーバ名に一致するserverディレクティブのバーチャルサーバが適応されます。しかし、一致しない場合にはデフォルトサーバとして選ばれたバーチャルサーバが適応されます。
デフォルトサーバはIPアドレスとポート番号の条件が一致したlistenディレクティブを持つserverディレクティブの中で次のものが選ばれます。
- 一致したlistenディレクティブの中でdefault_serverオプションを持つ
- 設定ファイル内で最初に一致したlistenディレクティブを持つ
listenディレクティブにdefault_serverパラメータを付けると、そのserverディレクティブがデフォルトサーバになります。
nginx連載4回目: nginxの設定、その2 - バーチャルサーバの設定 - インフラエンジニアway - Powered by HEARTBEATS
これの二個目に合致して、デフォルトサーバになってるっぽい。
結果的に動くけど、意図した動作じゃないので、やっぱりアンダースコアは指定した状態にしておく。
location
これも直感的。 指定したパスに一致したリクエストを受けたときの動作をブロック内で設定する。
proxy_pass
プロキシ先のURIやパスを指定する。
Sets the protocol and address of a proxied server and an optional URI to which a location should be mapped.
できあがり
以上を踏まえると以下のような感じになった。
nginx.conf(初期設定のまま)
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; }
conf.d/rails_app.conf
upstream unicorn_app { server unix:/tmp/unicorn.sock; } server { server_name _; location / { proxy_pass http://unicorn_app; } }
まとめ
超シンプルな設定でNginxのパワーを全然活かしてないんだろうけど、今のところこれで全然問題なさそう。
2015/5/28 追記
上記の設定だと、アプリでリダイレクトしたとき(scaffoldでできるcreateとかupdateとか)のときに、ポート番号が引き継がれなくてページが読み込めなかった。
なので、プロキシ時にヘッダ情報を引き継ぐ処理を追加する。
参考:Rails 4.2 + Unicorn + Nginx でアプリケーションサーバの構築 - Qiita
upstream unicorn_app { server unix:/tmp/unicorn.sock; } server { server_name _; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_pass http://unicorn_app; } }
proxy_set_header Host $http_host;
だけで一応上記の問題は解消したんだけど、参考にしたページに従って他の二行も追加しておいた。
続き書いた
Nginx + Unicornをつかう(手抜き記事)
今日はサザンのライブだった!!!
幸せな時間だったなあ。。
サザン最高。桑田さん最高。
ということで、今日はあんまり作業できなかったので、Unicornを使ってみた感じをさっくりと書く。
Vagrantfile書いてNginxインストールしてrbenvでRubyインストールして、みたいなのは今度まとめる。
今日は一応更新しましたというだけの手抜き記事。本当に自分のメモ書き&備忘録的内容なので、他の方にはあんまり参考にならないと思う。
...
ここまで書いてから結局結構時間かかった。。ねむい。。すぐハマる。。
Unicorn
まずrails new
で生成されるGemfileの、unicornの行のコメントを解除。
gem 'unicorn'
でインストール。
$ bundle install
unicornの設定ファイルを用意する。
config/unicorn.rbに以下を保存。
listen '/tmp/unicorn.sock' pid '/tmp/unicorn.pid'
unicornを起動してみる。
$ unicorn_rails -c config/unicorn.rb
JavaScriptランタイムが無いっていうエラーが出た。
therubyracerの行のコメントを解除。
$ gem 'therubyracer', platforms: :ruby
インストール。
$ bundle install
unicornを起動してみる。
こんなエラーが出た。
Sorry, you can't use byebug without Readline. To solve this, you need to rebuild Ruby with Readline support. If using Ubuntu, try `sudo apt-get install libreadline-dev` and then reinstall your Ruby.
確認してみるとreadlineは既に入ってるように見える。なぞ。
ググったら以下の記事が見つかった。
以下を追加すればいいとのこと。神。
gem 'rb-readline'
言われた通り上記をGemfileに追加してインストール。
$ bundle install
unicornを起動してみる。
$ unicorn_rails -c config/unicorn.rb
今度はうまくいった。
Nginx
/etc/nginx/nginx.confを以下の通り編集した。(httpブロック内)
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; upstream unicorn_app { server unix:/tmp/unicorn.sock; } server { listen 80; server_name _; location / { proxy_pass http://unicorn_app; } } }
確認
unicorn起動して、nginx起動して、nginxのポートにアクセスしてRailsのデフォルトページが表示されればok。
まとめ
サザン最高!
(内容はちゃんとまとめ直します。。)
続き書いた
参考
Vagrant使ってCentOSにNginx入れた
至る所に情報は転がってるんだけど、一応備忘録としてメモ。
経緯
昨日はさくらのVPSを設定して遊んでたんだけど、ある程度設定に確信が持てるまでの試行錯誤は手元で気軽な環境でやった方が効率がよさそうだったので、前にインストールしてあったVagrantでやってみることにした。
Vagrant
インストールは以前に済んでたので、
今日は以下とかを読みながらいじくってみた。
Vagrant楽しい。いつでもぶっ壊してやり直せるという安心感がすごい。
Nginx
NginxのBeginner’s Guideを読みながら初期設定してみた。
/etc/nginx/nginx.conf にデフォルトで書いてあるhttp contextをコメントアウトして、代わりに以下を追加する。
http { server { location / { root /data/www; } location /images/ { root /data; } } }
んで /data を /vagrant へのシンボリックリンクとしておく。
sudo ln -s /vagrant /data
ゲストOSの/vagrantとホストOSのVagrantfileを置いてるディレクトリがデフォルトで同期されてるので、ホストOSで普段のエディタを使ってnginx.confで指定したディレクトリにhtmlファイルを作成することができる。
あとVagrantfileにポートフォワードの設定をしておく。(最初から書いてあるのをコメントアウトする)
agrant.configure(2) do |config| ... config.vm.network "forwarded_port", guest: 80, host: 8080 ... end
これで http://localhost:8080/ で保存したページが見れた。
/images/も同様に、同期されてるディレクトリに適当に画像を置いておくとブラウザで表示できる。大島優子の画像を使った。(関係ない)
まとめ
サーバいじり超楽しい。
Ansible使ってみたい。
さくらのVPSを借りた
昨日書いたHerokuでのClearDB利用は制限がきつくて、すぐにmax_questionエラーになるので、さくらのVPSを借りてみた。ClearDBのプランを有料のやつにすれば多少は制限がゆるくなるんだろうけど、いずれHerokuじゃないサーバも触ってみたかったのでこれを機にやってみることにした。
とはいえ今日はあんまりやってない。
やったのは以下くらい。
ドットインストール
何か始めるときにはいつもお世話になるドットインストール。
今回も例に洩れずお世話になった。
さくらのVPS入門 (全21回) - プログラミングならドットインストール
これの「#12 Webページを設定してみよう」までを見ながら、動画だけではわからない詳細とかは適宜ググりながら、設定した。#12以降は必要になったときに随時見ればいいかな、という感じ。
契約
プランは1GB 900円のやつにした。
以前にレンサバを借りたときのIDがあったので、それを使って契約。
ずっと使ってなかったのでIDがわからなくて苦労した。メールを大捜索した。
設定
ドットインストール師匠にならって、以下のような設定をした。
ソフトのインストール
上に書いた通りのソフトを入れた。
まだいろいろ追加する必要がある。
あとドットインストールの流れでApacheを入れたけど、Apacheは前に使ったことがあるので今度はNginxを使ってみたい。
まとめ
今日はこれだけ。
サーバいじり超たのしい。
HerokuでMySQLを使うためにいろいろした
いろいろしたのでメモしておく。
そこら中の有益な記事を参考にした。
ClearDBアドオンの追加
HerokuのデフォルトのDBはPostgreSQLなので、MySQLを使うためにClearDBアドオンを入れる。
$ heroku addons:create cleardb:ignite
環境変数を設定する。
$ heroku config | grep CLEARDB_DATABASE_URL CLEARDB_DATABASE_URL: mysql://<username>:<password>@<host>/<databse>?reconnect=true $ heroku config:set DATABASE_URL='mysql2://<username>:<password>@<host>/<database>?reconnect=true'
何をやってるかというと、ClearDBアドオンを入れると追加されるCLEARDB_DATABASE_URL
の値を、DATABASE_URL
の値にセットしている。その際、スキームをmysql://
からmysql2://
に変える。
できたらマイグレートとかする。
参考
- Heroku データベースの管理(ClearDB アドオンによる MySQL の利用) - 君の瞳はまるでルビー - Ruby 関連まとめサイト
- Heroku (Rails) で MySQL 使う。 - Qiita
Rails外からDBにアクセスする
以上の設定でRailsアプリからはMySQLにアクセスできた。(たしか)
しかし今回はDBにレコードを定期的に追加するスクリプトをHeroku Schedulerで走らせていて、そいつからもアクセスできるようにする必要がある。(スクリプトではActiveRecordを使ってる)
そのスクリプトに設定をハードコーディングしたり独自の設定ファイルを別に用意したくないので、Railsのdatabase.ymlを読み込んで使うことにする。
最初に自動生成されたdatabase.ymlにこう書いてある。
# On Heroku and other platform providers, you may have a full connection URL # available as an environment variable. For example: # # DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase" # # You can use this database configuration with: # # production: # url: <%= ENV['DATABASE_URL'] %>
ので、こうする。
production: <<: *default url: <%= ENV['DATABASE_URL'] %>
その上で、DBにアクセスしたいスクリプト側はこうした。
require 'active_record' require 'yaml' require 'erb' ... env = ENV['RAILS_ENV'] ||= 'development' CONFIG = YAML.load( ERB.new(File.read( File.expand_path('path/to/database.yml', __FILE__) )).result)[env] ActiveRecord::Base.establish_connection(CONFIG)
参考
文字コード
上で動かしはじめると、
Mysql2::Error: Incorrect string value:...
というエラーが出た。
絵文字を格納するには、MySQLのエンコードをutf8mb4にする必要があるとのこと。(デフォルトはutf8)
参考:ClearDB に文字コード utf8mb4 で保存する - xykのブログ
この記事に従って、まず環境変数の修正を行う。
$ heroku config:set DATABASE_URL="mysql2://<username>:<password>@<host>/<database>?reconnect=true&encoding=utf8mb4"
DATABASE_URL
の末尾に&encoding=utf8mb4
を付加。
次に、マイグレーションファイルを以下の通り修正する。
class CreateUsers < ActiveRecord::Migration def change create_table :users, options: 'DEFAULT CHARSET=utf8mb4' do |t| ... end end end
create_table
にoptions: 'DEFAULT CHARSET=utf8mb4'
を付加。
で、変更をコミット、プッシュ、マイグレートする。
まとめ
一挙手一投足ハマって大変。
プロフェッショナルのための 実践Heroku入門 プラットフォーム・クラウドを活用したアプリケーション開発と運用 (書籍)
- 作者: 相澤歩,arton,鳥井雪,織田敬子
- 出版社/メーカー: KADOKAWA/アスキー・メディアワークス
- 発売日: 2014/09/19
- メディア: 大型本
- この商品を含むブログ (2件) を見る