SHOYAN BLOG

I am a pragmatic programmer.

Chefのworkerが詰まって処理が進まなくなった

chefを実行したらこんなメッセージがでた。

1
WARN: Chef client 24431 is running, will wait for it to finish and then run.

前回実行したChefが途中で詰まってしまい、ウンともスンとも言わなくなったので Ctrl + Cでとめたが、プロセス自体は残ってしまっている。

こんな感じで2つchef-clientのworkerが立ち上がっている状態。

1
2
3
4
5
6
7
[shoyan@server01 ~]$ ps aux | grep chef
root     24373  0.0  0.1 178168  2992 ?        Ss   10:22   0:00 sudo -p knife sudo password:  chef-client -S http://127.0.0.1:18889
root     24426  0.0  3.1 262164 61072 ?        Sl   10:22   0:01 /opt/chef/embedded/bin/ruby /usr/bin/chef-client -S http://127.0.0.1:18889
root     24431  0.0  7.1 1078932 138052 ?      Sl   10:22   0:03 chef-client worker: ppid=24426;start=10:22:49;
root     26701  0.0  0.1 178168  2996 pts/3    Ss+  10:50   0:00 sudo -p knife sudo password:  chef-client -S http://127.0.0.1:18889
root     26754  0.0  3.1 261996 60896 pts/3    Sl+  10:50   0:01 /opt/chef/embedded/bin/ruby /usr/bin/chef-client -S http://127.0.0.1:18889
root     26759  0.0  3.0 261996 57760 pts/3    Sl+  10:50   0:00 chef-client worker: ppid=26754;start=10:50:38;

1時間ほど経過しても何も進まないので、プロセスをkillしてみた。

TERMシグナルを送ってみたが、反応なし。

1
# kill -s TERM 24431

killシグナルを送るとプロセスが終了し、ペンディング状態となっていたChefが実行された。

1
# kill -s KILL 24431

マカレルでサーバーを監視する

サーバーの監視にマカレルを導入してみました。
使ってみた感想としては、難しい設定もなく簡単に導入することができて、とてもよくできているなぁと関心しました。

マカレルエージェントのインストール

マカレルでサーバーを監視をするには監視対象のサーバーにマカレルエージェントをインストールする必要があります。
また、事前に申し込みをして、apikeyを発行しておく必要があります。

マカレルエージェントのインストールはChefを使って行います。
cookbook-mackerel-agentを使いました。

metadata.rb

1
depends 'mackerel-agent'

recipes/default.rb

1
2
3
include_recipe 'mackerel-agent'
include_recipe 'mackerel-agent::plugins'
yum_package 'mackerel-check-plugins'

cookbook-mackerel-agentだけだとcheckプラグインが入らなかったのでyum_packageリソースを使ってインストールしています。

attributes/default.rb

1
2
3
default['mackerel-agent']['package-action'] = 'upgrade'
default['mackerel-agent']['conf']['apikey'] = ‘API KEYをかく'
default['mackerel-agent']['conf']['plugins'] = true

サーバーにレシピを適用するとマカレルの管理画面にサーバーがでてくるのでロールを設定します。
これでサーバーのメトリクスを見ることができます。

プラグインを使う

マカレルには様々なプラグインが用意されています。
使い方はgithubのREADMEに書いてあります。
https://github.com/mackerelio/mackerel-agent-plugins

自分はプラグインを使って以下のことを行っています。

linuxマカレルプラグインを使って様々なメトリクスをだす

linuxマカレルプラグインを使えばswapやnetstat、Disk read time 等のグラフを表示することができます。

attributes/default.rb に以下を定義します。

1
default['mackerel-agent']['conf']['plugin.metrics.linux']['command'] = '/usr/local/bin/mackerel-plugin-linux'

Unicornマカレルプラグインを使ってUnicornのメトリクスをだす

Unicornマカレルプラグインを使えばダッシュボードにUnicornのメモリとワーカ数のグラフが表示されます。

attributes/default.rb に以下を定義します。

1
default['mackerel-agent']['conf']['plugin.metrics.unicorn']['command'] = "/usr/local/bin/mackerel-plugin-unicorn -pidfile=/var/www/app/shared/tmp/pids/unicorn.pid"

httpの監視

httpのレスポンスをチェックして監視を行います。
細かい設定を行いたい場合は、check-tcpがよいですが、単純なチェックでよいのであればhttpのほうが設定が簡単です。

attributes/default.rb に以下を定義します。

1
default['mackerel-agent']['conf']['plugin.checks.http']['command'] = "/usr/bin/check-http -u http://localhost"

ログファイルの監視

nginxのログファイルを監視し、500系のエラーが頻発したときは通知するようにします。

attributes/default.rb に以下を定義します。

1
/usr/bin/check-log --file /var/log/nginx/access.log --pattern 'HTTP/1\.[01]" [5][0-9][0-9] ' --warning-over 3 --critical-over 10 --return

監視ルールの設定

監視ルールを設定することで閾値を超えた際に通知をすることができます。
CPU、メモリ、ロードアベレージ、ディスク容量等の監視を管理画面より設定できます。
詳しい設定方法については以下を参照ください。

Slackに通知する

何か異常が起きた場合はSlackに通知をするようにします。
こちらも管理画面から設定できます。
具体的な設定方法については、ドキュメントを参照ください。

参考リンク

Google Spreadsheetsを使ってデータの分析をする

データの分析によく使われるエクセルですが、Google Spreadsheetsでも様々な関数が用意されています。
関数を使えば日付の差分を調べたり、特定の条件に一致するデータをカウントすることができます。
Google Spreadsheetsを使ってデータの集計、分析をするためのTipsの紹介をします。

日付の差分を調べる

例えばユーザーの契約日数を調べたいとしましょう。
DATEVALUEを使って以下のように計算できます。

1
=DATEVALUE("2016/05/17") - DATEVALUE("2016/05/01")

セルを指定することもできます。

1
=DATEVALUE(A2) - DATEVALUE(A1)

月で表示したい場合は30で割ります。
FLOORは小数点を切り捨てるために使っています。

1
=FLOOR((DATEVALUE("2016/05/17") - DATEVALUE("2015/05/01"))/30, 0.1)

特定の条件をカウントする

例えば、契約期間が1年未満のユーザーをカウントする場合はCOUNTIFSを使います。

1
=COUNTIFS(A1:A1000, "<365")

COUNTIFSは複数条件を指定できます。
契約期間が1年以上〜2年未満のユーザーをカウントするということができます。

1
=COUNTIFS(A1:A1000, ">=365", I3:I1009, "<730")

点数を分析する

平均点を求めることは AVERAGE を使えばできます。
平均だけでなくばらつきを求めると違った角度でデータを捉えることができます。
ばらつきは標準偏差を求める関数 STDEVPで求めることができます。

1
= STDEVP(A1:E1)

例えばそれぞれの項目にたいして点数をつけるアンケートがあるとします。
以下の2つの項目は平均点は同じですが、標準偏差を求めるとばらつきがあることがわかります。
標準偏差を使えばこのようなデータを見つけることができます。

点数         平均点 標準偏差
6 7 9 7 6 7 1.095445115
8 5 10 7 5 7 1.897366596

サンプルを用意しました。参考にどうぞ。
https://docs.google.com/spreadsheets/d/1bOc3s8ikFcbBPGuzxDbRzd8KVT00lgQUDz275TJAIoE/edit#gid=0

Expressのインストールと構成を把握する

Node.jsのフレームワーク、Expressを試してみました。
ExpressはNode.jsでwebアプリケーションを作成するためのフレームワークです。

インストール

まずは、Node.jsをインストールします。

以下のページからパッケージをダウンロードしてインストールします。
https://nodejs.org/en/

次にnpmを使ってexpress-generatorをインストールします。
express-generatorはExpressのスケルトンアプリケーションを作成するコマンドです。
npmはNode.jsをインストールした際にインストールされていると思います。

1
$ sudo npm install express-generator -g

スケルトンアプリケーションを作成する

expressコマンドでスケルトンアプリケーションを作成します。

1
2
3
$ express myapp
$ cd myapp
$ npm install

起動してみます。

1
2
3
4
5
6
7
8
9
⇒  DEBUG=myapp:* npm start

> myapp@0.0.0 start /Users/PMAC025S/Development/sample/nodejs/myapp
> node ./bin/www

  myapp:server Listening on port 3000 +0ms
GET / 200 659.865 ms - 170
GET /stylesheets/style.css 200 9.088 ms - 111
GET /favicon.ico 404 70.846 ms - 1285

http://localhost:3000 にアクセスしてみます。
Welcome to Express と表示されていれば正常に起動できています。

サーバーの停止はCtrl + Cです。

ルーティング

ルーティングの基本的な構造です。

1
app.METHOD(PATH, HANDLER)

app: expressのインスタンス
METHOD: HTTPメソッド(GET, POST, PUT, PATCH, DELETE等)
PATH: サーバーのパス
HANDLER: 実行する関数

Hello World!を返すルーティングのサンプルです。
/にGETリクエストを送ると、Hello World!が返却されます。

1
2
3
app.get('/', function (req, res) {
  res.send('Hello World!');
});

/にPOSTリクエストを送ると、Got a POST requestが返却されます。

1
2
3
app.post('/', function (req, res) {
  res.send('Got a POST request');
});

Expressの構造

express-generator で作成されたファイルを確認していきます。
ファイル構成は以下です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  tree -L 2
.
├── app.js
├── bin
   └── www
├── node_modules
   ├── body-parser
   ├── cookie-parser
   ├── debug
   ├── express
   ├── jade
   ├── morgan
   └── serve-favicon
├── package.json
├── public
   ├── images
   ├── javascripts
   └── stylesheets
├── routes
   ├── index.js
   └── users.js
└── views
    ├── error.jade
    ├── index.jade
    └── layout.jade

app.js

app.jsではアプリの設定やルーティングを定義します。
簡単なアプリであれば、ここに全て書いてしまってもよいでしょう。
express-generatorで作成されたファイル構成では、routes/views/ ディレクトリが作成されており、ルーティングやテンプレートは分離する構成となっています。

bin

実行ファイルが格納されます。

node_modules

Expressなどのモジュールが入っているディレクトリです。npmでインストールしたファイルが格納されます。

package.json

アプリの設定やメタ情報を定義するファイルです。

public

公開ディレクトリです、cssファイル、imageファイル、JavaScriptファイルを格納します。

routes

アプリケーションのルーティングと処理を定義したファイルを格納します。

viewsディレクトリ

テンプレートを定義したファイルを格納します。

Expressの構成は把握できました。
次はExpressを使ってチャットアプリケーションを作ってみたいと思います(次回へ続く)。

参考リンク

Rubyでスラッシュを意識せずにコーディングする方法

ファイルのパスを生成する際にセパレーターを意識しなくてはならず、どうにもいけていないコードがあります(ありますというか自分が量産していました)。
以下のようなコードです。

1
path = "#{path1}/{$path2}"

セパレーターを意識せずコーディングできないものかと調べたところ、File.joinを使えばよしなにやってくれることがわかりました。
File.joinを使えばセパレーターを指定する必要はありません。

1
2
File.join("hoge", "moge")
=> "hoge/moge"

File.joinは正しいであろうパスのフォーマットに補正してくれるため、//hogeのようなパスが生成されることもありません。

1
2
File.join("hoge", "moge/", "/fuga")
=> "hoge/moge/fuga"

パラメーターが配列でもよしなにやってくれます。

1
2
File.join(%w(hoge moge/ fuga))
=> "hoge/moge/fuga"

地味ですが、これでセパレーターの悩みから解放されて幸せになれます。

参考リンク