symfonyのproject:deployがやたらと遅い
最近symfony1.4.9を使っていてproject:deployコマンドがやたら遅くて、rsyncってこんな遅かったかな?と思ったらsfFileSystem::execute()が、出力バッファを読み込む度に0.1秒sleepしている。
lib/task/sfFilesystem.class.php <?php public function execute($cmd, $stdoutCallback = null, $stderrCallback = null) { $this->logSection('exec ', $cmd); $descriptorspec = array( 1 => array('pipe', 'w'), // stdout 2 => array('pipe', 'w'), // stderr ); $process = proc_open($cmd, $descriptorspec, $pipes); if (!is_resource($process)) { throw new RuntimeException('Unable to execute the command.'); } stream_set_blocking($pipes[1], false); stream_set_blocking($pipes[2], false); $output = ''; $err = ''; while (!feof($pipes[1]) || !feof($pipes[2])) { foreach ($pipes as $key => $pipe) { if (!$line = fread($pipe, 128)) { continue; } if (1 == $key) { // stdout $output .= $line; if ($stdoutCallback) { call_user_func($stdoutCallback, $line); } } else { // stderr $err .= $line; if ($stderrCallback) { call_user_func($stderrCallback, $line); } } } usleep(100000); } fclose($pipes[1]); fclose($pipes[2]); if (($return = proc_close($process)) > 0) { throw new RuntimeException('Problem executing command.', $return); } return array($output, $err); }
元々は、sleep(0.1)となっていたが、実際sleepは効いていなかったバグがあり、
ミリ秒ならusleepでしょ、という修正が入ったときに遅くなった模様。
deploy遅すぎるよ!とreopenしてpatchが添付されているが、特に対応されていない。
- http://forum.symfony-project.org/viewtopic.php?f=22&t=30457
- http://trac.symfony-project.org/ticket/8877
取り敢えず添付のpatchを適用すると速度改善されました。直前のfreadで読込めた場合はusleepしなくなります。deployのような出力が多いものだと結構変わりますね。
array_chunkって便利ですよね
http://jp.php.net/array_chunk
例: 要素数Nの配列を、テーブルで1行2列ずつ表示したいようなときとか。
コード
<?php $fruits = array( 'apple', 'orange', 'strawberry', 'banana', 'cherry', ); ?> <table border="1"> <?php foreach (array_chunk($fruits, 2) as $chunk): ?> <tr> <?php foreach (array_pad($chunk, 2, null) as $fruit): // 2より少ない場合はnullで埋める ?> <td><?php if ($fruit === null): ?> <?php else: ?><?php echo $fruit ?><?php endif ?></td> <?php endforeach ?> </tr> <?php endforeach ?> </table>
出力
<table border="1"> <tr> <td>apple</td> <td>orange</td> </tr> <tr> <td>strawberry</td> <td>banana</td> </tr> <tr> <td>cherry</td> <td> </td> </tr> </table>
と、いった感じでテンプレート等でよく使ってます。(HTMLのエスケープは省略してます)
Apache VirtualHostの効率的な管理方法
ってどうするのが良いのでしょうか。今回の条件は下記として...
とりあえず最近は、開発環境向けにこんな感じで設定している。
設定が変わるたびにいろいろな箇所を修正するのが大変なので、可能な限り共通部分は別ファイルに切りだしてIncludeするように。
conf/ httpd.conf conf.d/ vhost/ example.com.conf _example.com.conf _ssl.conf
- サーバ全体に対する設定はhttpd.confとconf.d/*.confに記述。
- httpd.confの末尾で、VirtualHostの設定ファイルをInclude。
- conf.d/vhost 以下に example.com.conf のようなドメイン別ファイルを用意。
- 80番,443番で共通の設定は _example.com.confのようにドメイン内の共通ファイルを作成し、ドメイン別ファイルからIncludeする。
- SSLでの共通設定はドメインを超えて _ssl.conf に記述し、各ドメイン別ファイルからIncludeする。
いろいろ端折ってるけどファイルの中身はこんな感じ。
conf/httpd.conf
# ...上部でサーバ全体向けの設定 NameVirtualHost *:80 NameVirtualHost *:443 Include conf.d/vhost/example.com
conf.d/vhost/example.com.conf
<VirtualHost *:80> Include conf.d/vhost/_example.com.conf </VirtualHost> <VirtualHost *:443> Include conf.d/vhost/_example.com.conf Include conf.d/vhost/_ssl.conf </VirtualHost>
conf.d/vhost/_example.com.conf
ServerName example.com ServerAlias www.example.com DirectoryIndex index.php DocumentRoot "/path/to/example.com/www" <Directory "/path/to/example.com/www"> AllowOverride All Allow from All </Directory> CustomLog logs/example.com/access_log combined ErrorLog logs/example.com/error_log
conf.d/vhost/_ssl.conf
SSLEngine on SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL SSLCertificateFile /etc/pki/tls/certs/localhost.crt SSLCertificateKeyFile /etc/pki/tls/private/localhost.key SetEnvIf User-Agent ".*MSIE.*" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0
で、サービスのVirtualHostを追加するごとに、example.com.conf, _example.com.confが増えていく感じ。
mod_rewriteでリダイレクトあれこれ
ドメインの正規化
wwwあり・なしをどちらか片方に寄せたい場合。
今回はwww.example.comなど、example.com以外でアクセスされたらexample.comにリダイレクトする設定。
<VirtualHost *:80> # (1) ServerName example.com ServerAlias www.example.com RewriteEngine On # (2) RewriteCond %{HTTP_HOST} !^example\.com # (3) RewriteRule .* http://example.com$0 [QSA,NE,R=301,L] </VirtualHost>
(1)で、どちらのホスト名でもVirtualHostが動くようにする。
(2)は正規表現の末尾に$を付けないようにする。Hostリクエストヘッダは
Host = "Host" ":" host [ ":" port ] ; Section 3.2.2
http://www.studyinghttp.net/header#Host
と定義されているように、host名の後に「:ポート番号」が付与される形式がある。
例えば http://www.example.com:80/ にアクセスした場合に
Host: www.example.com:80
と送ってくるクライアントに対応できないので、前方一致で比較する。
(3)で
にアクセスした場合
にリダイレクトする。
リダイレクト時の各オプションは、
QSA
QueryString append。QSAを付与しないとQueryStringを上書いてします。詳しくは後述。
R=301
Moved Permanently
L
ここでルールの適用を終了する。
QSAはこの場合不要だけど、定義変更時に忘れがちなので付けておく。
HTTPSを強制
HTTPでアクセスされたらHTTPSにリダイレクトする。
RewriteEngine On # (1) RewriteCond %{HTTPS} !=on RewriteRule .* https://example.com$0 [QSA,NE,R=301,L]
DoCoMo機種の場合、強制的にguid=ONを付与
強制するのはどうなの?って感じですが。
RewriteEngine On # (1) RewriteCond %{HTTP_USER_AGENT} ^DoCoMo [NC] # (2) RewriteCond %{QUERY_STRING} !^(.*&)?guid=ON(&.*)?$ [NC] # (3) RewriteCond %{HTTPS} !=on # (4) RewriteRule .* http://example.com$0?guid=ON [QSA,NE,R=302,L]
(1) UserAgentがDoCoMoから始まるもの かつ
(2) QueryStringにguid=ONが含まれていない場合 かつ
(3) HTTPS接続で無い場合
(4) guid=ONを付与してリダイレクトする
ただし、アクセスする度にguid=ON付きURLにリダイレクトしたり、POSTのリクエストがリダイレクトされても困るので、
別途、アプリケーション側で内部リンクに自動的にguid=ONを付与するような仕組みを設けること。
(4)でR=302な理由は、DoCoMo端末のみのリダイレクト(!= Moved Permanently)であるのと、
301リダイレクトだと「サイトが移動しました(301)」のメッセージがでるので302を返すように。
(4)で「QSA」がついていないと、
にアクセスした場合に、Query Stringが書き換えられ
になってしまう。「QSA」が付与されていると
となる。
参考にさせていただいたリンク
最近
github始めてみました。たいしたものを置いておりませんが。。。http://github.com/tetsujin
iTermかTerminal.appか
先日MacBookPro 13インチ 2.53GHzを購入してMacデビューしました。ちなみにまだLeopardです。
いろいろインストールしたり、dotファイルを整理したりと開発環境を整えているのですが、一番躓いたのがターミナルの選定でした。
Terminal.appとiTermを行ったり来たりしていて、自分の周りにはTerminal.app派が多かったのですが、最終的にiTermに落ち着きました。以下が理由です。
- 256色表示できる。
- キーマップ設定でCtrl-,やCtrl-.に独自コードを割り当てれる。
2つ目の理由の方が大きくて、元々、puttyでscreenの切り替えを下記のような感じでCtrl-カーソルキーで操作していたのですが、
.screenrc
# for putty bindkey "^[OA" stuff "\015exit\012" # ctrl-up bindkey "^[OC" next # ctrl-right bindkey "^[OD" prev # ctrl-left
途中からiceiv+puttyを知って移行し、プライベートキー定義でCtrl-,で^[OD、Ctrl-.で^[OCを送信するように設定して以来、Ctrl-, Ctrl-.でのscreen切り替えに慣れ親しんでいたので、使えないとかな〜り不便でした。
で、Terminal.appの設定ではできなさそうで、iTermでは設定できたのでiTermに落ち着きました。
iTermの設定は、「プロファイルの管理」->「キーボード設定」から
- Ctrl-,
- キー: hex code 0x2c
- 修飾キー: Control
- 動作: send escape sequence
- 送信コード: OD
- Ctrl-.
- キー: hex code 0x2e
- 修飾キー: Control
- 動作: send escape sequence
- 送信コード: OC
としてます。Ctrl-カーソルキーもputtyの送信するキーコードにあわせて設定。Ctrl-; Ctrl-:とかもEmacs用に独自のコードを設定してたけど、EmacsはGUIに移行したからまあ良いかなと。
とりあえずiTermでこのまま進めてみよう。でも時間があったらrxvtも一度試してみようかな。。
追記 2009-09-11
なんか、iTermの通常のカーソルキー入力も奪っていて困ったり、ほかの設定も追加したりしたのでメモ。
.screenrc
bindkey "^[[5A" stuff "\015exit\012" # up bindkey "^[[5B" screen # down bindkey "^[[5C" next # right bindkey "^[[5D" prev # left
- Ctrl-,
- キー: hex code 0x2c
- 修飾キー: Control
- 動作: send escape sequence
- 送信コード: [5D
- Ctrl-.
- キー: hex code 0x2e
- 修飾キー: Control
- 動作: send escape sequence
- 送信コード: [5C
- Ctrl-↑
- キー: cursor up
- 修飾キー: Control
- 動作: send escape sequence
- 送信コード: [5A
- Ctrl-↓
- キー: cursor down
- 修飾キー: Control
- 動作: send escape sequence
- 送信コード: [5B
- 割り込み優先度高
- Ctrl-→
- キー: cursor right
- 修飾キー: Control
- 動作: send escape sequence
- 送信コード: [5C
- 割り込み優先度高
- Ctrl-←
- キー: cursor left
- 修飾キー: Control
- 動作: send escape sequence
- 送信コード: [5D
- 割り込み優先度高
ターミナル上のEmacsにペーストしたい
普段、PuTTY上でEmacsを使っているのですが、そのEmacsにコード等をペーストしたいときに、
S-Insert等でそのままペーストしても、キー入力として送られるので、自分の環境だといろいろ問題が起きてました。
- global-mapのC-mに'newline-and-indentを設定してるので、コードを貼り付けたときに階段状に余計なインデントがされてしまう。
- key-chordで設定したキーの文字列が含まれるとkey-chordが起動してしまう。("jk"とか)
- undo一発で元の状態に戻せるようにしたい。
いろいろ調べてみたのですが、良い解決方法が見つけられなかったので
今までは我慢するか、vimを起動して:set pasteをしてたのですが、
やっぱりEmacsにペーストしたい!!ってことで、ちまちま調べながらelispを書いてみました。
undoの部分はundo-groupを使うようにしました。load-path上に置いておきます。
http://www.mahalito.net/~harley/elisp/undo-group.el
term-paste-mode.el
;; http://www.mahalito.net/~harley/elisp/undo-group.el (require 'undo-group) (defvar term-paste-mode-map (let ((map (make-keymap)) (i ? )) (while (< i ?~) ;; 取りあえずスペース 〜 ~までself-insert-commandをセットして上書く (define-key map (char-to-string i) 'self-insert-command) (setq i (1+ i))) (define-key map "\C-m" 'newline) map)) (defcustom term-paste-mode-on-hook nil "Hook to run when term-paste-mode is activated." :group 'term-paste :type 'hook) (defcustom term-paste-mode-off-hook nil "Hook to run when term-paste-mode is deactivated." :group 'term-paste :type 'hook) (define-minor-mode term-paste-mode "Minor mode for pasting from any terminal applications." :lighter " Paste" :group 'term-paste (cond (term-paste-mode ;; minor-mode-mapの優先順位を上げる (setq minor-mode-map-alist (cons (cons 'term-paste-mode term-paste-mode-map) (delete (assq 'term-paste-mode minor-mode-map-alist) minor-mode-map-alist))) (undo-group-boundary) (run-hooks 'term-paste-mode-on-hook)) (t (run-hooks 'term-paste-mode-off-hook) ))) (provide 'term-paste-mode)
(require 'term-paste-mode) (add-hook 'term-paste-mode-on-hook (lambda () (key-chord-mode 0) )) (add-hook 'term-paste-mode-off-hook (lambda () (key-chord-mode 1) )) (defalias 'p 'term-paste-mode)
M-x pでterm-paste-modeをtoggleさせます。
- M-x p でterm-paste-modeをonに
- S-Insertで貼り付け
- M-x p でterm-paste-modeをoffに
元に戻す場合は
M-x undo-group
ちゃんと動かなかったらすみません。もっと良い方法あるかなあ。