RoadMovie

write down memos or something I found about tech things

Supervisorでamon2アプリのデーモン化 with plenv

使用ツールなど

amon2(flavor=Basic)

perl 5.16.3(plenv 使用)

carton

Supervisor

 (一般ユーザー名をhomepageとしている)

 

今回はデプロイのためにamon2で作ったアプリをデーモン化しようとしたが、-Dオプションでデーモン化ができなかったため、supervisorを導入することにした。

(※概要などはこちらのブログを参考にしてみてください → http://blog.hakutoitoi.com/?p=343) 

 

Supervisorのインストール

# yum install python-setuptools
# easy_install pip
# pip install supervisor

 

必要なディレクトリを作成

# mkdir /var/log/supervisord
# mkdir /etc/supervisord.d

 

# vi /etc/supervisord.conf

[unix_http_server]
file=/var/run/supervisor.sock

[supervisord]
logfile=/var/log/supervisord.log
loglevel=debug
pidfile=/var/run/supervisord.pid
nodaemon=false
minfds=1024
minprocs=200
environment=SHELL="/bin/sh"

[supervisorctl]
serverurl=unix:///var/run/supervisor.sock
history_file=~/.sc_history

[include]
files=/etc/supervisord.d/*.ini

[rpcinterface:supervisor]
supervisor.rpcinterface_factory=supervisor.rpcinterface:make_main_rpcinterface
# vi /etc/supervisord.d/supervisord.ini

[group:supervisord]
programs=サービス名(カンマ区切りでいくつも追加可能)

[program:サービス名]
command=bash アプリルートまでの絶対path/hoge.sh
numprocs=1
autostart=true
autorestart=true
startsecs=5
user=homepage
redirect_stderr=true
stdout_logfile=/var/log/supervisord/サービス名_out.log
stdout_logfile_maxbytes=0
stdout_logfile_backups=0
stderr_logfile=/var/log/supervisord/サービス名_err.log
stderr_logfile_maxbytes=0
stderr_logfile_backups=0
environment=HOME="/home/homepage",USER="homepage", PATH="$HOME/.plenv/bin:$PATH"
directory=アプリルートまでの絶対path

今回はplenvを使っているので普通に起動するとシステムのperlを見に行ってplenvでの設定が適用されず、エラーになりまくる。なのでまずはパスを設定しておくことが重要。

[program:サービス名]以下のcommand=の部分は実際に実行するコマンドを設定するのだが、この時にそのコマンド自体のパスを指定してやらなければならない。今回はそこをshellスクリプトでまとめてアプリのルートディレクトリに置いている。

 

# アプリのルートディレクトリ/hoge.sh
#!/bin/bash
export PATH="$HOME/.plenv/bin:$PATH"
eval "$(plenv init -)"
exec plenv exec carton exec plackup app.psgi

このhoge.shに設定を色々書いているのだがここでplenvのパスを通しておく(設定しておく)ことが超重要!

3行目に起動コマンドを記述している。

"plenv exec"でplenvのperlを使うことを指定、"carton exec"でcartonのcpanを使用することを指定している。1行目のexecは全体の実行。これがないとsupervisorをリスタートさせた時にうまくいかない。

 

Upstart経由でsupervisorを起動

# vi /etc/init/supervisord.conf

description "supervisord"

start on runlevel [2345]
stop on runlevel [!2345]

respawn
exec /usr/bin/supervisord -n

 

Supervisorのイニシャルスタート

# initctl start supervisord

 

エラーが出た後は基本的には、supervisorctl reload → supervisorctl statusしてエラーログみての繰り返しで解決しましょう。

下記、簡単にですがこの作業途中に使ったsupervisorのコマンド一覧

☁  ~homepage  supervisorctl reload
☁  ~homepage  supervisorctl status
☁  ~homepage  supervisorctl restart グループ名:サービス名

 

僕の場合、start出来たもののrestartをかけるとうまくプロセスを殺してくれないというエラーにも遭遇しました。

☁  ~homepage  supervisorctl restart supervisord:サービス名
  supervisord:サービス名: stopped
  supervisord:サービス名: ERROR (abnormal termination)

これは上のhoge.shの3行目に書いてある起動コマンドの先頭にexecをつけていないために起こったようです。なので上のとおりやっていれば起こらないと思いますが一応念の為にメモ。

 

☁  ~homepage  supervisorctl restart supervisord:サービス名
supervisord:サービス名: stopped
supervisord:サービス名: started

これで成功です。ブラウザからアクセスしてみてください。(plackだと5000番ポートがデフォルトなのでlocalhost:5000などで。)

-----------------------------------

Supervisor導入途中でいろいろ出たエラー(・∀・)

hoge.sh: line 2: carton: command not found
hoge.sh: line 1: plenv: command not found
hoge.sh: line 2: carton: command not found
hoge.sh: line 1: plenv: command not found
hoge.sh: line 2: carton: command not found
hoge.sh: line 1: plenv: command not found
hoge.sh: line 2: carton: command not found

これはcartonとplenvのパスが通っていないため。上述したように、これらのパスを指定することがまず重要。plenvを使っている際はcrontabなどでも同じようなエラーにぶち当たることがあるようなので注意。(※自戒も込めて)

 

 

/usr/bin/env: bash: No such file or directory
/usr/bin/env: bash: No such file or directory
/usr/bin/env: bash: No such file or directory
/usr/bin/env: bash: No such file or directory
/usr/bin/env: bash: No such file or directory
/usr/bin/env: bash: No such file or directory
/usr/bin/env: bash: No such file or directory

これは僕の環境ではoh-my-zshを使用しているため、zshを使っているのですが、supervisorの設定をbashとしていたことを失念していたことによりエラー。ということで、command=bash ~~とした。

 

以上です。導入するのは大変ですが、一度入れてしまうと超便利かと。先輩に教わりながら進めていったのですが、自分の知識不足と能力不足がまた改めて顕になりました。。。引き続きがんばります!

CSVファイルをmysqlにインポートした時のエラー対応 ーー Incorrect integer value: '1' for column 'num' at row 1

mysqlCSVファイルをインポートしようとした時にエラーがでまくったところから解決までのメモメモ。。

CSVを普通に入れてみた

mysql> load data local infile '/home/user/Category.csv' into table categories fields terminated by ',' (num, name);

エラーでまくったのでエラー文言みてみると・・

mysql> show warnings; Incorrect integer value: '1' for column 'num' at row 1


半角数字の1が入っているはずなのにintegerじゃないと怒られる。
(数字やろなんやねんふざけんなとか言いながらすすめる・・・)

なんか一応データは入ってるみたい。

mysql> select * from categories;
+----+------+---------------------+
| id | num  | name                |
+----+------+---------------------+
           || ラーメン
               |肉
         |3 | ハンバーグ
               |食
               |華
               |ば
               |司
             |喫茶店
             |カレー
             |親子丼
       | 11 | うどん・そば
             |うどん
         |3 | イタリアン
           || ラーメン
               |肉
         |3 | ハンバーグ
               |食
               |華
               |ば
               |司
             |喫茶店
             |カレー
             |親子丼
       | 11 | うどん・そば
             |うどん
         |3 | イタリアン
+----+------+---------------------+
26 rows in set (0.00 sec)


でもぐちゃぐちゃ。。

mysql> select * from categories\G;


でやると綺麗にデータが見えるという謎。。

文字コードの問題かと思ったので調べてみた。

➜  ~  nkf --guess RestaurantCategory.csv
UTF-8 (CR)


大丈夫そう。

改行コードとか?

➜  ~  file Category.csv
Category.csv: UTF-8 Unicode (with BOM) text, with CRLF line terminators



お?CRLFってWindowsの改行コードだよな。ってことでUnixの改行コードに変更する。

➜  ~  tr -d \\r 
<Category.csv> LF_Category.csv



でもまだできず・・・。で、もう無理かと思ったところ
BOMありが原因になることあるよねーという記事を何処かで見つけて
あれ?確かwith BOMって、、

ってことでみてみると

➜  ~  file LF_Category.csv
LF_Category.csv: UTF-8 Unicode (with BOM) text



やっぱり。
ってことでuconvコマンドで変更できるみたいなので
コマンドがあるか確認。

➜  ~  uconv
zsh: correct 'uconv' to 'ujconv' [nyae]? n
zsh: command not found: uconv

ない。

入れてみる。

➜  ~  sudo yum install uconv -y

そんなのない

なんかicuで全部入ってくるみたいなので入れてみる

➜  ~  sudo yum install icu -y



➜  ~  uconv -f utf-8 -t utf-8 --remove-signature LF_Category.csv > no_bom_Category.csv
➜  ~  file no_bom_RestaurantCategory.csv
no_bom_RestaurantCategory.csv: UTF-8 Unicode text


うまくいった。

で、あとは

mysql> load data local infile '/home/user/Category.csv' into table categories fields terminated by ',' (num, name);

mysql> select * from categories;
+----+------+--------------------+
| id | num  | name               |
+----+------+--------------------+
|  1 |    1 | ラーメン             |
|  2 |    2 | 焼肉                   |
|  3 |    3 | ハンバーグ         |
|  4 |    4 | 定食                   |
|  5 |    5 | 中華                   |
|  6 |    6 | そば                   |
|  7 |    7 | 寿司                   |
|  8 |    8 | 喫茶店                |
|  9 |    9 | カレー                |
| 10 |   10 | 親子丼             |
| 11 |   11 | うどん・そば   |
| 12 |   12 | うどん             |
| 13 |   13 | イタリアン       |
+----+------+--------------------+
13 rows in set (0.00 sec)



きれいにできました。
この辺の知識なくてかなり手こずりましたが無事完了(・∀・)

【CentOS6.4】はじめの環境構築 ... plenv, rbenv, tmux, oh-my-zsh

サーバーをいちからやり直さなければならない機会があったのでメモ。

いつもやってる自分の設定をとりあえず入れようかなという感じです。

 

まず最低限必要な物をyumで入れちゃう。

# yum install -y gcc make wget git zsh openssl-devel
# useradd homepage
# passwd homepage
# su homepage
$ chsh
homepage のシェルを変更します。
パスワード:
新しいシェル [/bin/bash]: /bin/zsh
シェルを変更しました。

 

oh-my-zshのインストール

これは補完機能とかが優れていて便利です。ちなみにさっきシェルを変更したのはoh-my-zshを使用するためです。

# curl -L https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh | sh
# exec $SHELL

 

plenvでperl環境構築

ここからはperlの環境を作る。普段perlbrewよりもplenvを使っているのでそちらで。 

$ git clone git://github.com/tokuhirom/plenv.git ~/.plenv
$ echo 'export PATH="$HOME/.plenv/bin:$PATH"' >> ~/.zshrc
$ echo 'eval "$(plenv init -)"' >> ~/.zshrc
$ exec $SHELL
$ plenv available
$ plenv install 5.16.3
$ plenv global 5.16.3
$ plenv local 5.16.3

一回再起動したら反映されてるはず。

 

cpanmもついでに入れちゃう。

$ plenv install-cpanm

 

tmux

下記の記事の通りに。screenみたいなやつですね。

http://tech-mr-myself.hatenablog.com/entry/2013/04/13/235458

 

rbenvでruby環境構築

ruby環境を整える。rbenvはこの辺を参考に。

 http://qiita.com/items/1cb882b48b1a827a420d

私の場合、この後rbenv -v, ruby -v, gem -vはきちんと表示されたのですが、

gem install railsとした際に、

# gem install rails
ERROR:  Loading command: install (LoadError)
    cannot load such file -- zlib
ERROR:  While executing gem ... (NameError)
    uninitialized constant Gem::Commands::InstallCommand

というエラーが出ました。

なので、

# yum install readline-devel
# wget http://pyyaml.org/download/libyaml/yaml-0.1.4.tar.gz

 yamlは./configure→make→make install→make cleanでインストール。

その後、rbenv install 1.9.3-p396という感じでもう一度インストール。

# gem install rails
....
file 'lib' not found

またエラーがでました。うぅぅ・・・。萎えますがあとひと踏ん張り。

# gem install rdoc
# gem install rails
# rails -v
Rails 3.2.13

成功です!

 

以上、駆け足でしたが最低限の環境構築。また何か追加があれば記述します。

サーバーの内容確認コマンド

エンジニア研修が始まったのでメモ程度に。

kernel/osのバージョン
➜  ~  uname -a

OS
➜  ~  cat /etc/redhat-release
CentOS release 6.4 (Final)

CPU数
➜  ~  cat /proc/cpuinfo

メモリ
➜  ~  cat /proc/meminfo

ディスク全体の容量
➜  ~  df

tmuxインストール

OS... CentOS_6.4(32bit)

 

 とりあえずmakeコマンドも無かったのでyumで入れちゃう

# yum install  -y make

 

tmuxインストールのためにlibeventが必要なのだがCentOSのlibeventのバージョンは1で、tmuxはバージョン2を要求してくるため、ソースからmakeする。

http://libevent.org/

# wget https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz
# tar zxvf libevent-2.0.21-stable.tar.gz
# cd libevent-2.0.21-stable
# ./configure
# make
# make install

 

pathを指定する必要があるためlibevent.confをつくる

# vim /etc/ld.so.conf.d/libevent.conf

そのなかにhttp://libevent-2.0.so .5のインストールされた場所のパスを書く。

/usr/local/libなど

 

tmuxをインストール

# wget http://downloads.sourceforge.net/tmux/tmux-1.8.tar.gz
# tar zxvf tmux-1.8.tar.gz
# cd tmux-1.8
# ./configure
# make
# make install

 

さきほどのlibeventの設定を活かすためにldconfigコマンドを。

# ldconfig

 

以上でtmuxコマンドでtmuxが立ち上がるようになるかと思います。

「勝負」について。

 

少し前に「勝ち続ける意志力」という本を読みました。

著者は一般的には少し変わった職業と思われる「プロ・ゲーマー」である梅原大吾さんという方です。私はこの方を本を読むまだ知りませんでしたし、ゲームもまったくしないのですが、非常に感銘を受けました。

 

読み終えてひとつ思ったことが、「自分は高校卒業までサッカーを真剣にやってきた。振り返って辛かったり、苦労したり、感極まる思いをしたり、栄光を掴んだ瞬間を味わったり。だから、この“勝負の世界”というものが何たるかは、彼と同じレベルではないにしても理解することが出来る。頭ではなく全身で。ただ、そういう経験のない人にとてはどうなのだろう?」と。

 

ふたパターンあると思います。

真剣な勝負をしてきた人生。そうでない人生。

 

そうでない人生というとマイナスイメージがつくかもしれませんが、真剣勝負が起こらなかった人生といってもいいかもしれません。

 

そしてこれから書くことは後者を否定することではなくて、ただ前者を選んできて良かったなというだけのお話です。

 

私はプログラマーの端くれなのでたまに思うことがあるのです。小さい頃からプログラミングばかりしておけば技術が高くなるからそっちのほうが良かったのかなと。でもそうばかりではないと。

 

ITの世界というのは他産業とは比べ物にならないくらい開けた世界だと思います。オープンソースが前提のような考えであり、大小様々な勉強会やコミュニティーがあり、相互に様々な人が助けあい、教え合っています。

そんな中でずっと育っていけば、確かに楽しいかもしれません。でもその中にギリギリの真剣勝負というのは生まれないと思うのです。

プログラマーとしての仕事もまさにそうだと思います。日々技術を磨いたり、良いサービスをつくるための努力というのはもちろんあります。非常にそれが大変だったり苦労が伴うというのはわかっています。でもその中に勝負はない。

 

 

 

梅原さんの幼少期の回想部分の記述で、秀才のお姉さんに絶望感にも似た感情を抱いた後の場面、

 

先に鉄棒から手を離せば、先にプールから顔を上げれば、この先の人生で姉のような人物に出会ったとき、いつも頭を下げなくてはいけない。それは絶対に嫌だった。死んでも先に音を上げるわけにはいかなかった。

 

というシーン。こういう気持ちって限界の勝負をしてきた人にしか真に感じることができなくて、例えばビジネス上の複雑な利害関係であったり駆け引きであったり、はたまたみんなでいいもの作ろうよ!というような場所では経験できないのではないかと思うのです。別にそれが悪いとか良いとかと言っているのではありません。

 

“勝負”について思うこと。

上で挙げたような場面では真剣勝負はあまり起こり得ないといいましたが、日常の中ではそれが“自分との戦い”として何度も何度も訪れます。

それは日々幾度と無く訪れる決断の場面、自分のチャレンジの過程の中でです。

例えば、何かを選択する際に自分の限界よりちょっと低めのうまくいきそうなものを選びそうになる、自分で選択したもののうまくいかず外部要因のせいにしてしまいそうになる。つまり負の思考が生まれる瞬間です。

 

この“負の思考が生まれる瞬間”は人が本当に弱くなる瞬間です。そうした場面で最終的にどうできるかはそれが生まれた瞬間の自分との真剣勝負に勝てるかどうかにかかっています。そして今までの人生でそうした真剣勝負をしてきた人間はその最も難しい勝負に勝てる可能性が高いと思うのです。

 

 

 

最後に。私が一番感動し、心に留めておきたいと思った一文です。

 

険しい道を選べるかどうかは、打ち込んでいるものが本人にとってどれだけ大事かに掛かっていると思う。

 

ゲーマーという特殊な、時には周りの人から嘲笑されるような立場であった梅原さんの言葉だからこそ、心が動かされました。