freeコマンドで確認するOSのメモリ情報

サーバーのメモリ情報はシステムの空きメモリと使用メモリの量を表示するfreeコマンドを使って確認することができます。

1
2
3
4
5
[shoyan@server01 ~]$ free
total used free shared buffers cached
Mem: 1922324 1716832 205492 0 197248 1055352
-/+ buffers/cache: 464232 1458092
Swap: 4194300 0 4194300

-mオプションを使うとMB単位で表示させることができます。

1
2
3
4
5
[shoyan@server01 ~]$ free -m
total used free shared buffers cached
Mem: 1877 1676 200 0 192 1030
-/+ buffers/cache: 453 1423
Swap: 4095 0 4095

まずどこを見るべきか

見るべきところは、3行目の -/+ buffers/cache: 453 1423 の部分です。
453MBが使用中で、1423MBは自由に使えるメモリがあります。

項目の説明

表示項目を確認していきます。

total: OSが認識している物理的なメモリサイズです。
1877MBなので、およそ1.8GBです。
RAIDカードやNICなどを装着しているときは、それらのためにメモリが使われるので実際の搭載メモリサイズよりも少なくなります。
ですので、物理メモリとしては2GBなのですが、RAIDカードやNICでメモリが使用されてOSが認識しているメモリは1.8GBとなります。

used: 使用しているメモリサイズです。
バッファキャッシュとページキャッシュが含まれています。
およそ1.6GBを使用しています。

free: 空きメモリサイズです。
この値にはバッファキャッシュとページキャッシュが含まれていません。
OSは使い続けるほどメモリにキャッシュを割り当てます。
そのため、使い続けるほどfreeの値は0に近づきます。
ですので、この値が少ないからといって空きメモリがないわけではありません。
200MBのメモリがfreeとして表示されています。

shared: 共有メモリに割り当てられたメモリです。
0なので共有メモリに割り当てられているメモリはありません。

buffers: バッファキャッシュに割り当てられたメモリです。
バッファキャッシュとはブロックデバイス用のキャッシュです。
192MBが割り当てられています。

cached: ページキャッシュに割り当てられたメモリです。
ページキャッシュはファイルに対するキャッシュです。
1030MBがページキャッシュとして割り当てられています。

バッファキャッシュとページキャッシュという2つのキャッシュがでてきました。
ここでは厳密にわけて考える必要はありません。
バッファキャッシュとページキャッシュを合計したものがキャッシュとして使用されているメモリと考えます。

-/+ buffers/cache: バッファキャッシュとページキャッシュを考慮したメモリです。
1つ目の値がused、2つめの値がfreeです。

used: 2行目のusedからページキャッシュとバッファキャッシュを引いた値です。
OSとアプリケーションが純粋に使用しているメモリサイズを表します。

実際に計算してみましょう。
1676 - 192 - 1030 = 454
ほぼあっていますね。

free: 2行目のfreeにページキャッシュとバッファキャッシュを足した値です。
キャッシュに割り当てられているメモリを自由に割り当て可能なメモリと考えれば、この値が空きメモリサイズになります。

実際に計算してみましょう。
200 + 192 + 1030 = 1422
こちらもほぼあっています。

Swap: スワップに割り当てたサイズです。
1つめの値がtotal、2つめの値がused、3つめの値がfreeです。

total: スワップに割り当てたディスクサイズです。
used: 割り当てた中で使用中のサイズです。
free: 割り当てた中で使用していないサイズです。

Swapのtotal値は4095MB、usedは0、freeは4095MBです。
usedが0なのでスワップ領域は使われていないことになります。

キャッシュはフリーメモリと考える

注意点として、freeの値がないからといってすぐにメモリ不足と判断することはできません。
なぜなら、OSは処理の高速化のためにキャッシュを使うようになっているからです。
時間の経過とともにキャッシュに割り当てられるメモリは増えていきます。
キャッシュはフリーメモリと考えて問題ないようです。

メモリの仕組みやキャッシュについて詳しく知りたい場合は以下の本をおすすめします。

参考文献

AllowGroupsの問題でsshログインできない

sshログインできないので /var/log/secure のログを見てみました。
以下のメッセージがでていました。

1
2
3
Apr 28 14:11:14 server01 sshd[31264]: User shoyan from example.jp not allowed because none of user's groups are listed in AllowGroups
Apr 28 14:11:14 server01 sshd[31265]: input_userauth_request: invalid user shoyan
Apr 28 14:11:14 server01 sshd[31265]: Connection closed by 192.168.1.1

none of user's groups are listed in AllowGroups と書いてあるので、groupの問題らしい。

/etc/ssh/sshd_configをみると、AllowGroups にいなかったのでユーザーのグループを追加しました。

sshd_configを変更したら、設定を反映させるためにreloadします。

1
2
# service sshd reload
sshd を再読み込み中: [ OK ]

AllowGroupsにユーザーのグループを追加することによってログインできるようになりました。

参考文献

勉強が楽しく続くようになるアプリ Studyplusのいいところ

Studyplusという勉強のSNSアプリを最近使い始めたのですが、よくできているので紹介したいと思います。

http://studyplus.jp/

Studyplusとは

勉強のSNSアプリです。
自分のした勉強の内容や時間を記録することができます。
また、他の人が書いたログを見ることができ、いいねをつけることができます。

Studyplusのいいところ

勉強したアプリや教材を登録できる

勉強したアプリや教材を登録できるのですが、種類が多く検索すればだいたい見つかります。

いいねでモチベーションアップ

いいねがつくとモチベーションがあがります。
けっこういいねをしてくれる人がいて、ありがたいことです。

勉強時間を把握できる

勉強時間を記録することができ、どの教材でどれくらい勉強したのかがグラフで表示されます。
1日の勉強時間、累計の勉強時間も記録されます。

ほかの人の勉強方法がわかる

ほかの人が勉強に使っている教材や勉強時間がわかります。

とりあえず使ってみる

インストールしたら、目標とアイコンを登録しましょう。
友達申請ができるので10人くらい申請しておきます。
そうするといいねをしてもらいやすくなるのでモチベーションを上げるのに役立ちます。

僕はおもに英語の勉強のログを残すために使っています。
Studyplusを使うようになってから英語の勉強時間を把握できるようになりました。
勉強時間が少ないことがわかったので、もっと勉強しなければと意識しだしました。
おかげで勉強時間が増えました。

RACK_ENVとUnicorn、SinatraでのRACK_ENVの扱いと注意点

RACK_ENVについて調べた内容とUnicorn、SinatraでのRACK_ENVの扱い方や注意点をまとめました。
RACK_ENVとはRACKの環境変数です。
何を設定するかによって使用するmiddlewareが変わります。
RACK_ENVには、developmentdeploymentnoneの3種類があります。

以下がそれぞれのRACK_ENVで使われるmiddlewareです。

1
2
3
#       - development: CommonLogger, ShowExceptions, and Lint
# - deployment: CommonLogger
# - none: なし

https://github.com/rack/rack/blob/028438ffffd95ce1f6197d38c04fa5ea6a034a85/lib/rack/server.rb#L157

developmentdeploymentに該当しない場合はmiddlewareは何も使われないようです。

https://github.com/rack/rack/blob/028438ffffd95ce1f6197d38c04fa5ea6a034a85/lib/rack/server.rb#L228

ここを間違えてproductionと設定する例を時々見るのですが、productionは存在しないので、noneと同じ挙動となります。
capistrano3-unicornのソースコードを見てみると、productionを指定した場合deploymentを設定するようになっていました。

1
set :unicorn_rack_env, -> { fetch(:rails_env) == "development" ? "development" : "deployment" }

https://github.com/tablexi/capistrano3-unicorn/blob/master/lib/capistrano3/tasks/unicorn.rake#L7

unicornはちょっと挙動を変えていて、developmentdeploymentのときは ShowExceptionsとLintは読み込まないようです。

1
2
3
4
5
6
7
8
case ENV["RACK_ENV"]
when "development"
when "deployment"
middleware.delete(:ShowExceptions)
middleware.delete(:Lint)
else
return inner_app
end

https://github.com/defunkt/unicorn/blob/master/lib/unicorn.rb#L79

Sinatraの環境変数

SinatraはRACK_ENVとenvironmentという環境変数が2つありややこしいです。
基本的には、environmentを定義して使います。
異なる環境で実行したい場合、RACK_ENVを指定することができます(これが混乱のもと)。

1
2
異なる環境を走らせるには、RACK_ENV環境変数を設定します。
RACK_ENV=production ruby my_app.rb

https://github.com/sinatra/sinatra/blob/4c7d38eb1b2cc02ce51029f28e0c3c34ca12ccfd/README.ja.md#%E7%92%B0%E5%A2%83%E8%A8%AD%E5%AE%9Aenvironments

set :environment, :production と定義して、RACK_ENV=development ruby my_app.rb を実行してみました。
このときの settings.production?の戻り値は何になるでしょうか。
trueとなり、productionと判定されます。
set :environmentで指定されたもので判定されるようです。

まとめると以下のような挙動になります。

  • set :environment が指定されているときは指定された値が使われる
  • set :environment が指定されていないときは RACK_ENVが使われる
  • set :environment も RACK_ENVも指定されていないときは developmentになる

ここで1つ気になることがでてきました。
capistrano3-unicornを使った場合は、RACK_ENVはdeploymentが指定されます。
Sinatraで set :environment を設定しなかった場合はRACK_ENVの値が優先されます。
ということは、本番環境でもsettings.production?がfalseとなってしまいます。
これは意図しない挙動ですね。
また、テンプレートのキャッシュについても効かなくなってしまいます。

まとめ

Sinatraではset :environment を明示的に指定しましょう。

1
set :environment, ENV["RACK_ENV"] == "deployment"? :production : ENV["RACK_ENV"].to_sym

参考文献

LaravelをMacにインストールして起動する手順

PHPで人気のフレームワーク、Laravelを手元のPCにインストールして起動するチュートリアルです。
冗長な説明を除きLaravelを動かすために重要な部分のみ解説することでスピーディにLaravelを動作できるようにしています。

Laravelのインストール

まずはcomposerでlaravelコマンドをインストールします。

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
26
27
28
29
30
31
32
33
34
35
⇒  composer global require "laravel/installer"
Changed current directory to /Users/PMAC025S/.composer

Using version ^1.3 for laravel/installer
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Installing symfony/process (v3.0.4)
Downloading: 100%

- Installing symfony/polyfill-mbstring (v1.1.1)
Loading from cache

- Installing symfony/console (v3.0.4)
Downloading: 100%

- Installing guzzlehttp/promises (1.1.0)
Downloading: 100%

- Installing psr/http-message (1.0)
Loading from cache

- Installing guzzlehttp/psr7 (1.3.0)
Downloading: 100%

- Installing guzzlehttp/guzzle (6.2.0)
Downloading: 100%

- Installing laravel/installer (v1.3.3)
Downloading: 100%

symfony/console suggests installing symfony/event-dispatcher ()
symfony/console suggests installing psr/log (For using the console logger)
Writing lock file
Generating autoload files

.bashrc.zshrc にパスを追加します。

1
export PATH="$PATH:/Users/PMAC025S/.composer/vendor/bin"

これでlaravelコマンドが実行できるようになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
⇒  laravel
Laravel Installer version 1.3.3

Usage:
command [options] [arguments]

Options:
-h, --help Display this help message
-q, --quiet Do not output any message
-V, --version Display this application version
--ansi Force ANSI output
--no-ansi Disable ANSI output
-n, --no-interaction Do not ask any interactive question
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
help Displays help for a command
list Lists commands
new Create a new Laravel application.

laravel new application_name でインストールします。

1
2
⇒  laravel new blog
Crafting application...

以下の構成で作成されています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
⇒  tree -L 1 blog
blog
├── app
├── artisan
├── bootstrap
├── composer.json
├── composer.lock
├── config
├── database
├── gulpfile.js
├── package.json
├── phpunit.xml
├── public
├── readme.md
├── resources
├── server.php
├── storage
├── tests
└── vendor

設定

設定情報はconfigディレクトリに保存します。
今回は設定を変更しません。

データベースを準備する

データベースのマイグレーション

Laravelに同梱されているartisanというツールを使って作成します。

1
2
⇒  php artisan make:migration create_tasks_table --create=tasks
Created Migration: 2016_04_28_011840_create_tasks_table

database/migrationsディレクトリに作成されます。
2016_04_28_011840_の部分はartisanが作成するので、makeするタイミングによって変わります。

2016_04_28_011840_create_tasks_table.phpを編集して、nameカラムを追加します。

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
26
27
28
29
30
31
<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateTasksTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('tasks', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('tasks');
}
}

.envファイルのデータベースの設定を自分のローカルのPCのmysqlに変更します。
デフォルトでは、HomesteadというLaravel開発用の仮想環境の設定です(今回は使いません)。

1
2
3
4
5
6
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=root
DB_PASSWORD=

マイグレーションを実行します。

1
2
3
4
5
  php artisan migrate
Migration table created successfully.
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
Migrated: 2016_04_28_011840_create_tasks_table

モデルを作成する

LaravelはEloquentというORMがデフォルトで使われるようになっています。

artisanでモデルを作成します。

1
2
⇒  php artisan make:model Task
Model created successfully.

モデルは app ディレクトリ配下に作成されます。

ルーティング

ルーティングの設定は、app/Http/routes.phpに定義します。
(ルーティングの設定はsinatraっぽい)

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
<?php

use App\Task;
use Illuminate\Http\Request;

/**
* Show Task Dashboard
*/
Route::get('/', function () {
return view('tasks');
});

/**
* Add New Task
*/
Route::post('/task', function (Request $request) {
//
});

/**
* Delete Task
*/
Route::delete('/task/{task}', function (Task $task) {
//
});

Viewの設定

LarvelはデフォルトでBladeというテンプレートエンジンを使います。
viewのディレクトリはresources/viewsです。

1
$ mkdir resources/views/layouts

全体のレイアウトのテンプレートとして使うapp.blade.phpを作成します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 <!-- resources/views/layouts/app.blade.php -->

<!DOCTYPE html>
<html lang="en">
<head>
<title>Laravel Quickstart - Basic</title>

<!-- CSS And JavaScript -->
</head>

<body>
<div class="container">
<nav class="navbar navbar-default">
<!-- Navbar Contents -->
</nav>
</div>

@yield('content')
</body>
</html>

tasks.blade.phpを作成します。

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
26
27
28
29
30
31
32
33
34
35
36
37
 <!-- resources/views/tasks.blade.php -->

@extends('layouts.app')

@section('content')

<!-- Bootstrap Boilerplate... -->

<div class="panel-body">
<!-- Display Validation Errors -->

<!-- New Task Form -->
<form action="{{ url('task') }}" method="POST" class="form-horizontal">
{!! csrf_field() !!}

<!-- Task Name -->
<div class="form-group">
<label for="task" class="col-sm-3 control-label">Task</label>

<div class="col-sm-6">
<input type="text" name="name" id="task-name" class="form-control">
</div>
</div>

<!-- Add Task Button -->
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">
<button type="submit" class="btn btn-default">
<i class="fa fa-plus"></i> Add Task
</button>
</div>
</div>
</form>
</div>

<!-- TODO: Current Tasks -->
@endsection

サーバーを起動する

さて、一通りの設定が整いました。
サーバーを起動してブラウザで確認してみましょう。
以下のコマンドでサーバーを起動します。

1
2
⇒  php artisan serve
Laravel development server started on http://localhost:8000/

http://localhost:8000/ にブラウザでアクセスします。

Taskという文字とフォームが表示されれば成功です!

参考文献