jqueryのplugin作るときに気を付けたこと

backbone.js大好きな僕が今更jqueryのplugin開発で気を付けたポイントをまとめてみた。

名前空間の乱用

jQueryの拡張ポイントはいくつかあり用途によって使い分けをする方になると思います。

jQuery自体への拡張なのか、jQueryインスタンスへの拡張なのか

・jQuery自体への拡張

1
2
3
4
5
6
jQuery.aaa = function () {
return 'aaa';
};
$.aaa(); // aaa

$().aaa(); // Uncaught TypeError

・jQueryインスタンスへの拡張

1
2
3
4
5
6
7
jQuery.fn.aaa = function () {
return 'aaa';
};

$().aaa(); // aaa

$.aaa(); // Uncaught TypeError

pluginで仕様する場合は後者のjQueryインスタンスへの拡張を行う形になると思います。

実行時のオプションの操作対象範囲

実行時にオプションを渡しでカスタマイズ性を向上させる方式をよく見られますが、どこまで拡張させるかは設計上重要になってきます。
自分のサイトに適合させるためにどこにカスタマイズを行わせるポイントをつくるか、pluginの責務を超えていないか、過度にパラメーターを渡さないと機能しないつくりになってしまっていないか、
など色々考える必要があります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$.fn.myPlugin = function (config) {
var defaults = {
speed: 100,
delay: 1000,
top: 0,
left: 0,
interval: 2000,
opacity: 1.0,
animate: true,
scale: 1.2
};
var options = $.extend(defaults, config);

return this.each(function (i) {
// 処理
});
};

プラグイン内メソッドの外部呼出し

ちょっとこれは意味が分かりませんし何のためにやるのかって話でもあるのですが、プラグインの中で使用してる処理を名前空間を汚さず呼び出したい場合に有効な方法です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var F = $.myPlugin = function () {
F.open.apply( this, arguments );
};
$.extend(F, {

// 公開用メソッド
testMethod: function () {
return 11;
}
});
$.fn.myPlugin = function (config) {
var defaults = {
scaleRate: 1.2,
speed: 300
};
var options = $.extend(defaults, config);

return this.each(function (i) {
// 処理
});
};

$.myPlugin.testMethod(); // 11

linuxのファイルのパーミッションの話

2016年一発目の記事はまさかのファイルパーミッションのお話!

なんとなくは分かっていたけど、具体的に説明できなかったのでこれまた備忘録になってしまいますがズラズラ書いてみます。

長いことweb開発やっていますが未だにそういえばパーミッション変更してねー!!みたいなことって結構あります(俺だけ)。

んでなんとなく、全員に書き込みも読み込みも実行もできるようにしちゃえばいんじゃね?みたいなことしゃいます(俺だけ)。

適切にパーミッションを設定しないと、ID・パスワードなどを設定してるファイルがみられちゃったり、ソースコードがみられてちゃったり、ファイルの一覧がみられちゃったり、プログラムが実行されちゃったり色々とリスクがあります。

では、用途に応じて適切なパーミッションを設定するにはどうしたらよいのか?

パーミッション関連の設定を一つずつ見ていきましょう。

パーミッション関連に必要設定項目概要

  1. 所有者と所属グループ
  2. 権限レベル
  3. 権限の適応範囲

1. 所有者と所属グループ

ファイル・ディレクトリには所有者と所属グループという権限が与えられている

【所有者】

・ファイルを所有してるユーザー
※基本的にはファイル・ディレクトリを作成したユーザーが所有者になる

【グループ】

・ファイルを所有しているグループ
※基本的にはファイル・ディレクトリを作成したユーザーが所属してるグループが所持しているグループになる

このようにファイル・ディレクトリに所有者・グループを割り当てることによって、
所有者ごとの権限・グループごとの権限など柔軟な権限レベルの設定を行うことが出来る。
グループのメリットとしては、特定のグループに所属してるユーザーにだけファイルの編集を行わせたい、閲覧をさせたいなどまとまった管理を行うことが出来る。


2. 権限レベル

r (読み込み) w (書き込み) x (実行)
ディレクトリの場合 ディレクトリの一覧の参照が可能 ディレクトリ内のファイルの削除、
名前変更が可能。新規作成が可能
ディレクトリにアクセス可能
ファイルの場合 ファイルをひらける ファイルを編集・更新できる プログラムを実行できる

よく見る755とか644とかの意味

r (読み込み) w (書き込み) x (実行)
2進数表記 100 010 001
8進数表記 4 2 1
  • 読み込みしかできない

    • r (読み込み) 4 = 4
  • 読み込みと書き込みができる

    • r (読み込み) 4 + w (書き込み) 2 = 6
  • なんでもできる

    • r (読み込み) 4 + w (書き込み) 2 + x (実行) 1 = 7

3. 権限の適応範囲

所有者

所有者の場合に適用される権限

グループ

所属してるグループの場合に適用される権限

他人

所有者でも所属グループでもない場合に適用される権限

表記例:(所有者権限)(グループ権限)(他人権限)

  • とりあえず所有者だけはなんでもできるようにしたい

    • 700
  • 所有者には書き込み/読み込みだけさせて、所属グループには読み込みだけさせたい

    • 644
  • 所有者にはなんでもさせて、所有者以外は書き込み/読み込みをさせたい

    • 755
  • 全員になんでもさせたい
    • 777

git 備忘録

用語整理

  • ワーキングツリー:実際に作業中のファイルたち
  • ローカルレポジトリ: ローカルのレポジトリ
  • ステージング:コミット準備がととのった状態にあるファイルたち
  • リモートレポジトリ: リモートにあるレポジトリ(みんなで使うことが多いから共有レポジトリって呼んだりもする!)

1. 表示系

コミット履歴とかを表示する系のやーつ

コミット履歴表示

1
git log

変更したファイルを表示

1
git log --name-status

過去の特定のファイルの変更内容を見る

1
git log -p {path}

commitメッセージからキーワードで検索

1
git log --grep hoge

あのファイルのあの行誰が更新したのか確認

1
git blame

2.git commit

コミットする際につかうやーつ

とりあえず状況確認

どのファイルがステージングにあがっていてーとか、どのファイルが追加になったやつでーとかがみれる。

1
git status

修正前と修正後の差分を見る

コミットする前にどのファイルが更新されたか確認できる。

1
2
git diff
git diff {path}

ステージングにあげる

1
2
git add .
git add {ファイル名}

ステージングにあげたやつをとりけす(アンステージング)

1
2
git reset HEAD
git reset HEAD -- <ファイル名>

部分的にステージングにあげる

1
git add -p ファイル名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Blog {
private $title;

function __construct() {
}
+
+ public function set_title($title) {
+ $this->title = $title;
+ }
+
- public function get_title() {
- return $this->title;
- }
}
Stage this hunk [y,n,q,a,d,/,K,g,s,e,?]?

ハンク(ある程度に区切られた変更範囲)ごとに対話形式でどう対処するか選べる

y: ハンクをまるごとステージングへ
n: ハンクをステージングへあげない
e: 編集モード(vi)で部分的にステージングへあげる

  • ‘-‘の行をaddしたくなければ、’-‘を’ ‘(空白)にする。
  • ‘+’の行をaddしたくなければ、’+’の行を消す。
  • 先頭に#と書かれている行はaddされない

ステージングにあがっているファイルの差分を見る

1
git diff --cached

ステージングにあがっていないファイルの差分を見る

1
git diff

ファイル名変更

1
git mv -f js/app.js js/App.js

3.過去改竄系。。。

一個前のコミットをなかったことに

HEADだけ一個前に戻す

ステージング・ワーキングツリーは維持される。

1
git reset --soft HEAD^

HEAD・ステージングだけ一個前に戻す

ワーキングツリーは維持される。
一個前のコミットでアンステージングされた状態。

1
git reset --mixed HEAD^

HEAD・ステージング・ワーキングツリーを一個前に戻す

一個前のコミットでまっさらな状態になる。

1
git reset --hard HEAD^

空コミット

1
git commit --allow-empty -m "first commit"

一個前のcommitを編集

1
git commit --amend

例1) ファイルを追加しわすれた

1
2
git add aaa.txt
git commit --amend

例2) ファイルを間違って追加してしまった

1
2
git rm aaa.txt
git commit --amend

二個以上前のcommitを編集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 一旦編集対象のコミット履歴を下記コマンドで表示

# 最新の3コミットを対象にする
# git rebase -i HEAD~3
# 特定のコミット以前を対象とする(git log --onelineで一覧表示すると便利)
# git rebase -i {revision}~

# 出力結果
pick <コミット1hash> test_1.htmlファイルを修正
pick <コミット2hash> test_2.htmlファイルを修正
pick <コミット3hash> test_3.htmlファイルを修正

# 編集漏れがあったコミットの「pick」の個所を「edit」に変更
pick <コミット1hash> test_1.htmlファイルを修正
edit <コミット2hash> test_2.htmlファイルを修正
pick <コミット3hash> test_3.htmlファイルを修正

# その後
git add test_2.html
git commit --amend
git rebase --continue

一番最初のコミットをrebaseする←普通にやるとできないの以下の方法で!

1
git rebase -i --root

4.stash

変更中に他のブランチへの追加・変更をしたいときに一旦退避するやーつ

一時退避!

1
git stash save {スタッシュ名}

一時退避してるリスト

1
git stash list

リスト

1
2
3
<stash名1>: WIP on <stashを行ったブランチ名>: <ハッシュ> <コミットコメント>
<stash名2>: WIP on <stashを行ったブランチ名>: <ハッシュ> <コミットコメント>
<stash名3>: WIP on <stashを行ったブランチ名>: <ハッシュ> <コミットコメント>

復活

1
git stash save {スタッシュ名}

削除

1
git stash drop {スタッシュ名}

復活しつつ削除

1
git stash pop {スタッシュ名}

5. branch

ブランチのやーつ

ブランチ作成

1
git branch {ブランチ名}

ブランチ一覧表示

1
git branch

リスト

1
2
develop
*master

ブランチをきりかえる(チェックアウト)

1
git branch {ブランチ名}

ブランチを作成しつつチェックアウト

1
git checkout -b {ブランチ名}

ブランチ削除

1
git branch -d {ブランチ名}

ブランチを結合(マージ)

1
2
git checkout {マージさせたいブランチ名}
git merge --no-ff {マージしたいブランチ名}

ローカルブランチとリモートブランチの関連づけ

git pull origin masterってやらなくてもgit pullだけでよくなる

1
git branch --set-upstream develop origin/develop

6. remote操作

リモートのレポジトリのやーつ

リモートリポジトリ表示

1
git branch -a

リモートリポジトリをチェックアウト

コメント「-b」はローカルにリモートブランチのデータをおとしつつ、ローカルブランチの切り替えも行ってくれる。

1
2
3
git checkout -b {ローカルブランチ名} {リモートブランチ名}

# 例: git checkout -b develop origin/develop

リモートリポジトリをローカルから削除

1
2
3
4
git remote remove {名前}

# 例
$ git remote remove origin

リモートリポジトリを変更

1
git remote set-url origin {リモートブランチレポジトリ}

アーカイブ

変更された差分ファイルを抽出するのに便利そう

とりあえず全ファイルをzipでアーカイブ

1
git archive --format=zip HEAD -o archive.zip

あるコミットからの差分をzipでアーカイブ

1
2
# 3つ前のコミットからの差分
git diff --name-only HEAD HEAD~3 | xargs tar czf ./ver_diff.tar.gz
1
2
# あるコミットからあるコミットの差分
git diff --name-only コミットA コミットB | xargs tar czf ./ver_diff.tar.gz

運用編

リモートブランチとローカルブランチ※1を同期
※1. リモートブランチを参照してるローカルブランチ

1
git fetch

リモートブランチとローカルブランチの差分を表示

1
2
3
4
# 差分があるファイル一覧を表示
git diff --name-status リモートブランチ
# ファイルの差分を表示
git diff リモートブランチ

リモートブランチとローカルブランチをマージ

1
git merge リモートブランチ

repository_image.png

mysqlのutf照合順序のメモ

utf8_bin

特徴

完全一致のみ

  • utf8…文字コードは UTF8 で判断しますよ!
  • bin…バイナリ判定(大文字と小文字は違う文字ですよ!全角と半角も違う文字ですよ!)

utf8_general_ci

特徴

拡張をサポートしない。

  • utf8…文字コードは UTF8 で判断する
  • general…大文字と小文字を同じ文字として扱い、全角と半角も区別する
  • ci…Case Insensitive(大文字と小文字を識別する)

utf8_unicode_ci

特徴

拡張をサポートする。
半角カタカナ=>全角カタカナやひらがな=>カタカナのマッチングが可能。

  • utf8…文字コードは UTF8 で判断する
  • unicode…大文字と小文字を同じ文字として扱い、全角と半角は区別しない
  • ci…Case Insensitive(大文字と小文字を識別しませんよ!)

濁音、半濁音、ひらがな、カタカナも区別しない。
「は」で検索すると「は」「ば」「ぱ」「ハ」「バ」「パ」「ハ」がヒットする。

utf8_unicode_ciのデメリット

日本語の検索で、「ひらがな」「カタカナ」が混在した形でヒットしてしまう。
ひらがなの「ほ」で条件を指定したのに、「ぼ」や「ボ」や「ホ」といったものに一致してしまう。

余談

select時だけ照合順序を区別する方法
SELECTする時に条件として大文字小文字を区別したいのであれば、BINARYオペレータを記述する方法もあります。

1
SELECT * FROM fish WHERE BINARY name = ‘KATSUO’

php.iniの文字コードまわりのおさらい

default_charset

  • HTTP header 文字コード
  • 出力時にHTTPヘッダとして送信する文字コード名のこと.
  • Content-Typeが固定されるため,default_charsetはnoneを指定してhtmlのmeta charasetで文字コードを指定するのがよさげ
  • 指定しない場合の注意点として同じドメインでページをまたいで複数の文字コードを使ってる場合は一旦読み込んだheaderの内容をキャッシュしてしまうので文字化けをおこす
    1
    php_value default_charset none
default_charset_none.gif
1
php_value default_charset utf-8
default_charset_utf8.gif

internal_encoding

  • 内部文字エンコーディング
  • internal_encodingはmbstring関数のデフォルトエンコードのこと.
  • mb_convert_kanaなどで変換元文字コードの指定がない場合に使用される.
  • 変換元文字コードを固定にするため,
  • internal_encodingはソースコードの文字コードと揃えておくと良い.
1
mbstring.internal_encoding = UTF-8

mbstring.detect_order

  • 文字コードの自動検出の優先順位
  • 規定値:auto
  • auto は “ASCII,JIS,UTF-8,EUC-JP,SJIS”の順
  • 精度がそんなによくないのでなるべくautoにしないで明示的に設定したほうがよさげ
1
mbstring.detect_order = UTF-8,SJIS,EUC-JP,JIS,ASCII

mbstring.encoding_translation

  • POSTデータの変数が内部文字エンコーディング(mbstring.internal_encodingの文字コード)に変換されます。
1
mbstring.encoding_translation = On

無効な文字な文字列の場合に表示される文字

1
mbstring.substitute_character = "?"

language

  • mb_send_mailを利用した際にのみ使用される
1
php_value mbstring.language Japanese

HTTPの入出力エンコーディング

  • これを指定しても,自動的に文字コードは変換されない。
  • ob_start(“mb_output_handler”)関数でしか有効にならない

HTTP 入力エンコーディング変換を UTF-8 に設定

1
php_value mbstring.http_input = UTF-8

HTTPレスポンスは変換しない

1
php_value mbstring.http_output pass

2014年よくつかったLINUXコマンド集

最近イオンめぐりがはまってる國井です。

2014年はインフラをいじってる時間がわりと多かったということもあり、よく使ったコマンドをご紹介します。

ネットワーク系

パケットキャプチャ

特定のデーモンやサービスにパケットがながれてるかとりあえず確認したいときに便利

1
$ tcpcump

httpのパケットキャプチャする

1
$ tcpcump port 80

LANのインターフェースを指定してキャプチャする

1
$ tcpcump -i eth0

キャプチャしたデータをファイルに保存する

保存したファイルをWireSharkとかで開くと見やすい

1
$ tcpcump -w packet.cap[ファイル名]

DNS確認

対話型nslookup

1
$ nslookup

ネームサーバーを問い合わせ

1
2
> set type=NS
> google.com

Aレコードを問い合わせ

1
2
> set type=A
> google.com

MXレコードを問い合わせ

1
2
> set type=MX
> google.com

NSを指定してドメインを正引き

1
2
> set type=A
> google.com {ネームサーバー名}

ルーティング

ルーティング・テーブルを表示

1
$ route

ルーティングを追加する

1
$ route add -net 192.168.1.0 netmask 255.255.255.0 eth0

I/O系

ファイル名でソートする

1
ls -l

ファイル名をバージョン順にソートする

1
ls -lv

タイムスタンプの新しいもの順にソートする

1
ls -lt

タイムスタンプの古いもの順にソートする

1
ls -lrt

ファイルをリネームする前に一旦確認

1
2
3
4
5
rename -n 's/$/.bak/' *

kuso.txt renamed as kuso.txt.bak
miso.txt renamed as miso.txt.bak
unko.txt renamed as unko.txt.bak

ディスク使用状況を確認

1
$ df -h

フォルダ毎にデータサイズをかえしてくれる

どのフォルダの容量が多いか特定する時便利

1
$ du -sh /*

ファイルサイズがちょうど1000バイトのファイルを見つける

1
$ find . -size 1000c

ファイルサイズが100MB以上のファイルを見つける

どのファイルが容量くってるのかを調べるとき便利

1
$ find . -size +100000000c

ファイルサイズが1000バイト以下のファイルを見つける

1
$ find . -size -1000c

ファイルをセキュアにアップロード

1
$ scp index.html admin@domain.com:/home/admin/htdocs/

ファイルをセキュアにダウンロード

1
$ scp admin@domain.com:/home/admin/htdocs/index.html ./

その他

コマンドを定期実行する

1
$ watch -n 秒数 コマンド

定期的にログ終端から5行目を表示するwatchコマンド

1
$ watch -n 5 tail -5 /var/log/messages

ファイルをロックしてるプロセスを特定する

1
$ fuser -va *

起動中のサービスを確認

余計なサービスが動いていないか確認するとき便利

1
$ netstat -tanp

watchコマンドと併用して定期実行するとさらに便利

1
$ watch -n 1 "netstat -tanp | grep :80"

プロセスの親子関係をツリー表示

1
$ pstree -p

プロセスの詳細を表示

1
$ lsof -p {プロセスID}

bashの履歴を検索

1
2
3
$ Ctlr + r
# 入力すると候補がでてくる
# 入力した状態で違う候補がみたい場合はさらに Ctlr + r を入力

基本的なコマンドだけですが今年も頻繁につかうであろうコマンド集でしたー

preventDefault()実行時のaタグhrefの挙動メモ

なんか気になったので個人的なメモ。

jQueryでイベント制御を行う際に、ブラウザのデフォルトの動作を無効にしたい時ってありますよね?
そんな時使用するのが preventDefault()関数なんですが、aタグ使用時の挙動が色々謎だったので整理したいと思います。

というかpreventDefault()関数って何?

例えば、サイトトップへみたいなリンクがあったとして、
これをこのままクリックしちゃうとページ上部にとんじゃうわけですよ。
アニメーションをいれてページ上部まで戻りたいっていう機能要求だったとすると、この動作を無効しなくちゃならないですよね?
そんな時に便利なのがこの preventDefault() です!
本来 Id=”body”までジャンプするはずの挙動を無かったことにできるのです。

使い方

1
2
3
$('a.link').on('click', function(e) {
e.preventDefault();
});


検証の前の予備知識

今回の検証を行うにあたってバブリングという現象を解説します。

1
2
3
4
5
6
7
8
9
10
<div class="parent-link">
<div class="child-link">リンク</div>
</div>

$('.parent-link').on('click', function(e){
console.log('parent');
});
$('.child-link').on('click', function(e){
console.log('child');
});

実行結果:

1
2
child
parent

このように子要素の.child-linkが先に実行され、その親要素である.parent-linkが後から実行される、この現象をバブリングといいます。
※下(子要素)から上(親要素)に伝播してく様が泡みたいだからバブリングというそうな

このバブリングだけを止めたいという場合は、stopPropagation()関数を使います。(今回はふれません)


検証

今回の検証内容はaタグのイベント無効時にバブリングがどう作用するかというものです。

検証1: aタグは本当に無効になるのか!?

動作検証

以下をクリック

1
2
3
4
5
<a class="link" href="http://kuniiskywalker.github.io/">リンク</a>

$('.link').on('click', function(e){
e.preventDefault();
});

結果: 無効

とりあえず、基本的なところから動作確認。無効になります。

検証2: 親要素のaタグを無効にした場合小要素のイベントは発火するのか!?

動作検証

以下をクリック

1
2
3
4
5
6
7
8
9
10
<a class="parent-link" href="http://kuniiskywalker.github.io/">
<div class="child-link" style="background-color: #FFFF00;">リンク</div>
</a>

$('.parent-link').on('click', function(e){
e.preventDefault();
});
$('.child-link').on('click', function(e){
alert('child');
});

実行結果:

1
child

結果: する

子要素からイベントが伝播してくるのだから当たり前といえば当たり前ですね。

検証3: バブリング時の影響範囲は!?

動作検証

以下をクリック

1
2
3
4
5
6
7
<a class="parent-link" href="http://kuniiskywalker.github.io/">
<div class="child-link">リンク</div>
</a>

$('.child-link').on('click', function(e){
e.preventDefault();
});

実行結果: 

この結果だけ予想と違いました。preventDefault()関数はバブリングを許可するはずなのになぜか、親要素のaタグが実行されない。。。

結果: バブルしない

考察

検証項目は徐々に増やしていきますが、とりあえずこんな感じで。

サーバーをchef-soloで一撃管理!

みなさんこんにちはメガーネです。

今回はchef-soloを使って夏バテに効きそうな清涼感あふれるサーバーの構築をご紹介いたします。

chef-soloができると何がうれしい!?

  • インストール作業が楽になる
    yum install httpd とか rpm -ivh mysql でインストールするルーチンワークから逃れられる

  • 設定ファイルもひな形を作成でき動的な値もマッピングできる
    httpd.conf とか php.iniとかvi開いて編集を繰り返えさなくてもよくなる

  • サーバーの技術的なナレッジを蓄積できそうな予感
    「前回設定したあれなんだっけあれ!あれやってくれるやつ!」みたいな会話が減る

  • 本番と同じ構成でローカル開発できる
    サーバーにあげたら何故か動きません!みたいな悲鳴が減る

今回の調理ポイント

  • centos6がうごくサーバー(今回はsakura vps)を使用
  • apacheをインストールします

Chef用語

Recipe(レシピ)

サーバーの設定手順書

Cookbook(クックブック)

Recipeをまとめとくやつ

Repository(レポジトリ)

CookbookとかをまとめたChef全体を管理する場所

難しい用語

Provisioning(プロビジョニング)

サーバー構築の自動化を行う

冪等性(べきとうせい)

引用(コピペ)
ある操作を1回行っても複数回行っても結果が同じであることをいう概念である。

Chefの基本的な動作として冪等性は保証されております。
ですが書き方によっては、1回目に実行した内容と2回目に実行した内容が変わってしまう可能性があるので
テストしっかり!

調理の前の下準備

chefをインストール!

http://chefsoloonwindowstutorial.readthedocs.org/en/latest/install-chef-solo.html

(インストール方法はまさかの割愛)

windowsユーザーは以下必読

chefファイルをサーバー上に送る際にrsyncを使っているですが、
こいつを使えるようにするためwindowsだと少し特殊なことをせねばなりませぬ。

若干面倒ですが以下の手順でrsync, sshを使えるようにする必要があります。
今回はcygwinを使います。

  1. cygwinのインストーラー起動
  2. Select Packageでrsync,opensshをインストール
  3. binフォルダにパスを通す(C:\cygwin\bin or C:\cygwin64\bin)
  4. cygwin ternimalを起動して

rsyncはcygwin経由で実行されるため/cygdriveが絶対パスになってしまうので、パスを通してあげる。

1
2
cd / 
ln -s /cygdrive/c c

調理開始!!

STEP1. Repositoryの作成

まずはRepositoryを作成しましょう

1
$ knife solo init chef-repo

こいうのができあがります(人´∀`).☆.。.:*・゚

1
2
3
4
5
6
7
chef-repo  ←Repository
├─.chef
├─cookbooks
├─data_bags
├─environments
├─roles
└─site-cookbooks

[cookbooks]

サードパティ製のCookbook
berkshelfというプラグインで管理するので手動ではいじらない

[site-cookbooks]

独自のCookbook
(基本ここにレシピを追加すればよさげ)

他のディレクトリは今回はふれません!

STEP2. Recipeの作成(献立を考える)

続いてRecipeの追加をしましょう

今回はsite-cookbooksにhttpdのRecipeを追加します

1
2
$ cd chef-repo
$ knife cookbook create httpd -o site-cookbooks

site-cookbooksにこいうRecipeができあがります(人´∀`).☆.。.:*・゚

1
2
3
4
5
6
7
8
9
10
11
12
13
14
site-cookbooks
└─httpd
├─attributes
│ └─default.rb
├─definitions
├─files
│ └─default
├─libraries
├─providers
├─recipes
│ └─default.rb
├─resources
└─templates
└─default

[attributes]

デフォルトの設定情報を定義

[files]

アップロードファイル

[templates]

設定ファイルのひな形
httpd.confなどの設定ファイルに値を動的にマッピングして利用する

[recipes]

実行内容を記述

他のディレクトリは今回はふれません!

STEP3. Recipeの編集

Recipeをいじっていきましょう!

file:

site-cookbooks/httpd/attributes/default.rb

1
2
3
default['httpd']['port'] = "80"
default['httpd']['documentroot'] = "/var/www/html"
default['httpd']['servername'] = "admin@localhost"

file:

site-cookbooks/httpd/templates/default/httpd-vhosts.conf.erb

attributes で設定した内容がマッピングされる

1
2
3
4
<VirtualHost *:<%= node[:httpd][:port] %>>
DocumentRoot <%= node[:httpd][:documentroot] %>
ServerName <%= node[:httpd][:servername] %>
</VirtualHost>

file:

site-cookbooks/httpd/templates/default/httpd-vhosts.conf.erb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 # apacheのインストール
package "httpd" do
action :install
end

service "httpd" do
supports :status => true, :restart => true, :reload => true
action [:start, :enable]
end

#共有のCookbook templatesで設定したhttpd-vhosts.confを適用
template "/etc/httpd/conf.d/httpd-vhosts.conf" do
source "httpd-vhosts.conf.erb"
notifies :restart, 'service[httpd]'
end

STEP4.サーバーにchefをインストール

サーバー上でプロビジョニングを行える環境を整えましょう。

1
$ knife solo prepare {ユーザー名}@{サーバーIP or HOST名}

上記を実行するとRepositoryにnodesというフォルダが作成されいて、その中に{HOST}.jsonというファイルが作成されています。
{HOST}.jsonにどのRecipeを実行するかとか、レシピの中で使いたい設定値(動的にマッピングする値)を書いていきます

1
2
3
4
5
{
"run_list": [
"httpd"
]
}

これでプロビジョニングできる環境が整いました!

STEP5. Let’s Cooking!!

1
$ knife solo cook {ユーザー名}@{HOST}

完了したらドキュメントルートにhtmlファイルを設置して確認してみよう!

コマンドラインでさくっとメール送っちゃおうぜ

・メールユーザーを追加した後に実際にそのアカウントでメールが送信できるかどうかの確認ができる
・いちいちメーラーに設定しなくてもコマンド(黒い画面)だけでさくっとメールが送信できちゃう

最初に言っておくとメールサーバーが暗号化必須(gmailとか)だと特殊なやり方が必要なので読まない方がいいです。

引用(コピペ)
Telnet は、アプリケーションを遠隔で実行する機能をユーザーに提供し、遠隔管理を支援します。

サーバー(対象PC)に違うPCから通信内容むき出しで色々操作できてしまうアプリケーション。
なのでサーバーとかいじるときはおとなしくSSHを使いましょう。

ところがこのtelnet、サーバーに接続して設定をあれこれする機能以外にも、SMTPやHTTPのようにテキストの入出力を行うアプリケーション層のプロトコルを実行することもできるです。

要はコマンドラインからサービスに接続できるぜってことです。

以下はtelnetでwebサービスに接続するデモです
※windowsのコマンドプロンプトだと何故かhttp接続したあと入力した内容が見れないのでmacかlinux使って検証してください。

1
2
3
4
5
6
7
8
$ telnet {HOST} 80 [Enter]

Trying 182.22.70.252...

$ GET / HTTP/1.1 [Enter]
$ [Enter]

レスポンス(HTML)が返ってくる

これと同じ要領でメール送信サーバーに接続して、メールを送信することができます。

SMTP認証を突破せよ

メールを送信する前に認証という大きな壁があります。
メーラーを設定する際にユーザー名・パスワードをいれると思いますが、それと同じことをコマンドラインでやります。

まずメール送信サーバーで使われるポートは25なので、25番に接続します。

1
2
3
$ telnet {HOST} 25 [Enter]

220 {HOST} ESMTP unknow

これが返ってきたらOKです。
続いて以下を入力しましょう。

1
2
3
4
5
$ AUTH LOGIN [Enter]
$ {base64encodeしたユーザー名} [Enter]
$ {base64encodeしたパスワード} [Enter]

Authentication successful

successfulとなりましたのでこれで認証成功です。

base64encodeは以下で行うと楽ちん
http://www.base64encode.org/

サーバーによっては25が使えない場合があるので、587を使いましょう。
それでもダメな場合はあきらめましょう;;

また、POP before SMTPなど他にも認証方式はありますが今回は割愛します。

送信元・送信先メールアドレスを設定しよう

送信元もメールサーバーに身元を認識させるために必須です。
ありえないドメインとかだとメールサーバーは送信してくれません。

【送信元メールアドレス】

1
2
MAIL FROM:kunii@cueplus.com
250 ok

当たり前ですが、送信先メールアドレスは必須ですよね。

【送信先メールアドレス】

1
2
RCPT TO:kuniiskywalker@gmail.com
250 ok

これらの情報を元にサーバーはメールを送信します。

送信してみよう!

では実際に送信する内容を入力していきます。

1
2
$ DATA [Enter]
354 go ahead

これで送信するデータの入力待ち状態になります。

さて件名・本文入力といきたいのですが、メールを送る上で重要な要素がもう一個あります。

↑で説明した送信元・送信先メールアドレスはあくまでサーバーが認識するところで、
受信ユーザーは誰が送ったのかが識別しにくいです。
送られてきたメールの送り元が誰なのか、誰宛に送った情報なのかがこれだと視覚的にわかりずらいですね。
手紙とか物を送るときも差出人情報・送り元情報が必要かとおもいますが、メールの場合もこれらをヘッダーに書いて送ります。

1
2
From: {相手のメーラに表示される差出人名} [Enter]
To: {相手のメーラに表示される送信先名} [Enter]

では件名・本文入力といきましょう!
入力終了時は「.」ENTERで!

1
2
3
4
5
6
7
8
9
Subject: {件名} [Enter]

{本文} [Enter]

. [Enter]

250 ok 1287476652 qp 11135
quit
221 i-3-i.info

実際に送信できたか確認しましょう。

考察

telnetで送信できてもメーラーによっては送信できない場合があるのでガチ検証したいときは実際のメーラーでご確認ください。

PHP出力バッファで進捗管理

∠( ゚Д゚)/イェェガァァ

どうもメガネです。

実行中のプログラムの進捗をクライアントで確認できるようにする仕組みをPHPで作成してみました。
とても簡易的なものなので汎用性とかあんま考えてないですw
最近ではフレームワークを使えば簡単に実装できる機能ではありますが、APCを使ってたり、細かいカスタマイズができそうにないので自作することにしました。
今回はリクエスト数を減らすという目的だけでhttp接続をポーリングして ob_start() と ob_flush() を使って処理を書きました。

ob_start ob_flushってなんぞ?

出力されるはずのデータを一旦内部バッファにためこむことができる関数。

何が便利なの?

これを使うと、echoで出力したデータを変数に代入したり、後の条件で出力させなかったりできます

例えば、以下のファイルのバッファリングをコントロールしてみます。

ファイル名: body.php

1
2
<?php
echo 'Hello ' . $test_text . '!';

【出力バッファリング無】

1
2
3
include('./body.php'); // テンプレートインクルード  

$test_text = 'world'; // テンプレート内で使う変数

出力結果:
Hello !

【出力バッファリング有】

1
2
3
4
5
6
7
8
ob_start(); // 自動出力無効  

include('./body.php'); // テンプレートインクルード

$test_text = 'world'; // テンプレート内で使う変数
$body = ob_get_contents(); // 出力内容を変数にいれる
ob_end_clean(); // 出力内容を削除 ※これやらないと二回出力されちゃう
echo $body; // 出力

出力結果:
Hello world!

出力のタイミングをプログラムで制御することが可能になる。
今回はこの関数を使って出力バッファを断片的にクライアントに送信して、結果を逐一jsで処理して進捗状況をブラウザに表示してやろうぜってとこまでやってみる。

javascriptで進捗状況のイベントをハンドリングする

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
名前空間: window.ProgressBar

window.ProgressBar = {
update: function (percent) {
// 進捗が更新されるたびに実行したいメソッド
},
successe: function () {
// 成功時に実行したいメソッド
},
error: function (error_message) {
// 失敗時に実行したいメソッド
},
cancel: function () {
// キャンセル時に実行したいメソッド
}
};

出力データのバッファリング/フラッシュ

ファイル名: index.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
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<form action="progress.php" enctype="multipart/form-data" method="post" target="progress">
<input id="file1" type="file" name="file1" />
<input type="submit" value="upload" />
<span id="progress">0%</span>
</form>
<iframe style="display: none;" name="progress" height="240" width="320"></iframe>

<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script>
var progress = document.getElementById('progress');
window.ProgressBar = {
update: function (percent) {
progress.text(percent + '%');
},
successe: function () {
},
error: function (error_message) {
alert(error_message);
}, cancel: function () {
}
};
</script>

</body>
</html>

ファイル名: progress.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
38
39
40
41
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<?php
try {
if (!isset($_FILES["upfile"]) || !is_uploaded_file($_FILES["upfile"]["tmp_name"])) {
throw new Exception('アップロード失敗。');
}
$handle = fopen($_FILES["upfile"]["tmp_name"], "rb+");
$proc_length = 0;
while (!feof($handle)) {
// 通信が切断されていたら処理を中断
if (connection_aborted()) {
echo '<script>'
echo 'parent.ProgressBar.cancel();';
echo '</script>';
break;
}
// ファイルの読み込み
$contents = fread($handle, 8192);
$proc_length += strlen($contents);
$data = '<script>';
$data = 'parent.ProgressBar.update(\'' . $proc_length . '\');'
$data = '</script>';
// ブラウザに応答を出力させる
flush();
ob_flush();
sleep(1);
}
} catch (Exception $e) {
echo '<script type="text/javascript">';
echo 'parent.ProgressBar.error("' . $e->getMessage() . '");';
echo '</script>';
}
fclose($handle);
?>
</body>
</html>

考察
リクエスト数は減るが、ポーリング状態だとコネクションが専有されてしまうのであまり使わないほうがいいかも。
プログラムの実行状況の管理にAPCを使わないのであれば、代わりにファイルもしくはDBで進捗理するようにして、定期的にクライアントから非同期で実行状況を確認しにいくような仕組みのほうがいいですね。