技術メモ: 2008年3月アーカイブ

いいめものように、メールを受け取ってアレコレするメールアプリケーションを書くことはよくあるかと思います。

メールサーバとしてpostfixを使うと、こんな具合で実現できます。

#cat /etc/aliases
:
test:"|/var/mailApp/test.rb"
test@example.comでメールを受け取ったら/var/mailApp/test.rbを起動する、という具合です。

それはいいのですけど、この状態でtest.rbでエラーが起きると、メール送信者宛にバウンスメッセージというのが送付されます。

This is the Postfix program at host snares.example.com.
:
                       The Postfix program

>test@example.com< : Command died with
   status 1: "/var/MailApp/mailserver/test.rb". Command output:
   /usr/lib/ruby/1.8/logger.rb:518:in `initialize': Permission denied -
   /var/MailApp/mailserver/../log/MailServer.log (Errno::EACCES)
   from /usr/lib/ruby/1.8/logger.rb:518:in `open'  from
   /usr/lib/ruby/1.8/logger.rb:518:in `open_logfile'  from
   /usr/lib/ruby/1.8/logger.rb:487:in `initialize'  from
   /usr/lib/ruby/1.8/logger.rb:263:in `new'  from
   /usr/lib/ruby/1.8/logger.rb:263:in `initialize'  from
   /var/MailApp/mailserver/../common.rb:42:in `new'  from
   /var/MailApp/mailserver/../common.rb:42  from
!!!エンジニアにとっては背筋の凍り付くような内容です。メールアプリケーションのファイル構成から使っているモジュール、自分がどんなミスをしたかまで送信者に筒抜けになってしまいます。

とりあえず、test.rbの内容をこうしましょう。

begin
 元のコード
rescue => e
	exit(-1)
end

これで、test.rbがエラーを外にはくことはなくなるので、バウンスメールの内容も、ずいぶん穏当なものになります。

>test@example.com< : Command died with
   status 255: "/var/MailApp/mailserver/test.rb"

Action: failed
Status: 5.0.0
Diagnostic-Code: X-Postfix; Command died with status 255:
   "/var/MailApp/mailserver/test.rb"

ちなみに、posfix 2.3から、バウンスメールの内容をカスタマイズできるようになるらしいです。
Postfix manual - bounce(8)

メールサーバのバージョンアップが待ち遠しいなんて、久しく味わっていない感覚です。



expressionEngine、ツールとしてはいいのだけれど、UIが英語なのでそのうち訳さないとね、と思っていたら、日本語ランゲージパックを作ってくださった方がおられました。

Expression Engine Japanese language pack (日本語版)

早速インストール...
EE_JP.png
すばらしいです。これはありがたい。ビールでもコーヒーでもおごりますよ!

#といったってどこに住んでいる方かもわからないので^^; とりあえずpaypal donateしておきました。

一応インストールのやり方を説明させて頂くと。

 ダウンロードしてきて。
[daisuke@snares ~/tmp] $ wget http://expression-engine.jp/uploads/files/ee_strings_jp.tgz
--10:51:24-- http://expression-engine.jp/uploads/files/ee_strings_jp.tgz
=> `ee_strings_jp.tgz'
Resolving expression-engine.jp... 72.51.37.167
Connecting to expression-engine.jp|72.51.37.167|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 77,973 (76K) [application/x-gzip]

0% [ ] 0 --.--K/s
12% [====> ] 9,851 39.92K/s
57% [=========================> ] 44,603 90.37K/s
100%[=============================================>] 77,973 149.24K/s

10:51:25 (148.85 KB/s) - `ee_strings_jp.tgz' saved [77973/77973]
[daisuke@snares ~/tmp] $ tar xzf ee_strings_jp.tgz
[daisuke@snares ~/tmp] $ ls
ee_strings_jp.tgz japanese
 expressionEngineをインストールしたディレクトリにあるlanguageディレクトリにコピーします。
[daisuke@snares ~/tmp] $ cp -r japanese /var/www/html/ee/language/
[daisuke@snares ~/tmp] $ ls /var/www/root/html/ee/language/
english index.html japanese
この状態で、EEにログインしてCP Home › My Account › Localization Settings を見ると、Japaneseが選択できるようになっていますので、これを選択してupdateすればできあがりです。

EE_JP_install.png


サーバをさわるときは、常に信用できない人間が約一名(自分だ!)いるので、どんな作業でも取り返しがつくようにするのが大切です。

ssh上で行った作業のログをとる - もぎゃろぐ
という具合にしてログをとることで、いざというとき何をしていたか振り返ることができるようになるのですが、設定ファイルに変なことを書いた場合、emacsの修正内容はログに残らないので、まだ若干不安が残ります。

そういえば、masuidriveさんは、「コマンドも含め全てのファイルはSubversionで管理」しているのだそうで。

masuidrive on rails » Blog Archive » masuidrive的プロジェクトの方針

こうしておけば、ファイルに変なこと書いても最悪ロールバックできますので、これは大変いいアイデアだと思います。

具体的にどうやるのか今ひとつわからなかったので躊躇していたのですが、今やってみたら簡単にできたので、ご紹介を。
svnは普通に使いこなせる方が対象ですので、そうでない方は勉強してから試してくださいませ。
Subversionの基礎練習

前提:自分の場合、/usr/local/bin/に自作のミニスクリプトをおいています。ファイル名の後ろに日付をつけたバックアップを用意するbkとか、複数ファイルをいっぺんにcatできるcatsとか。

とりあえず、ホームディレクトリあたりにそういうファイルを一式用意してsvnにインポートします。

 [daisuke@snares ~/tmp/mogyalet] $ ls
 bk  cats  ddiff
 [daisuke@snares ~/tmp/mogyalet]$ svn import file:///var/svn/repos/mogyalet -m "initial import"
 Adding         cats
 Adding         bk
 Adding         ddiff

で、/usr/local/bin/に移動してチェックアウトします。

 [daisuke@snares ~/tmp] $ cd /usr/local/bin/
 [daisuke@snares /usr/local/bin] $ sudo svn co file:///var/svn/repos/mogyalet ./
 A  cats
 A  bk
 A  ddiff
 Checked out revision 2.
 [daisuke@snares /usr/local/bin] $ ls
 addcr  cats   delcr    http@        rblsmtpd  tcpclient      tcpserver
 argv0  date@  finger@  mconnect     recordio  tcprules       who@
 bk     ddiff  fixcrio  mconnect-io  tcpcat    tcprulescheck
できあがり。bkコマンドをアップデートしたいときには、適当な位置で修正したものをチェックインしたあと、/usr/local/bin/でsudo svn updateとしてやればいいわけです。

以前この話を聞いたときには

 疑問なのは、全部のファイルを1モジュールにぶっこむのでしょうか?1コマンド1モジュール?
 前者だと取ってくる人がエライことになるので、後者かと思うのですが。そうするとものすごい数のモジュールを 登録することになりますよね。構わないのかなぁ。
 あと、適当に名前をつけているとあとで何物かわからないモジュールがたくさんでてきそう。
Re:プロジェクトの始まりはTracから - もぎゃんだいあり。 
と思ったのですが、今考えると、リポジトリのパスなんて意識するのはチェックアウトするときだけで。
普段はsvn update しかしないのだから、そんなこと気にする必要がないんですよね。
わからなくなったら、既存のディレクトリに移行してsvn infoで見ることができます。
というわけで、リポジトリ名なんて、file:///var/svn/repos/etc/httpd/conf/とかでいいような気がしてきました。

おまけ:

 実行ファイルをsvnに入れるときは、下記を参考に実行ビットつけておくと便利です。
【CGI・Perl】実行可能な属性をファイルに付加する(svn:executable)

 [daisuke@snares ~/tmp/mogyalet]$ svn propset svn:executable ON bk cats ddiff
 property 'svn:executable' set on 'bk'
 property 'svn:executable' set on 'cats'
 property 'svn:executable' set on 'ddiff'
 [daisuke@snares ~/tmp/mogyalet]$ svn commit -m "set executable bits"
 Sending        bk
 Sending        cats
 Sending        ddiff
 
 Committed revision 2.

2008-05-10 18:44:44追記  設定ファイルも管理する方法は、こちらをご覧くださいませ。

[linux]なんでもsvnで管理する2 - もぎゃろぐ


 他のブログツール同様、EEも、カテゴリに属する記事を書いたら勝手にカテゴリページを生成してくれます。
で、これ一応カスタマイズできるみたいなのですが、その挙動がどうもわかりにくいので、まとめてみました。

カテゴリへのリンクの生成

 トップページのサイドバーあたりでカテゴリへのリンクを出したいときは、
{exp:weblog:categories weblog="test" style="linear" }
<a href="{path=main/test}">{category_name}</a>
{/exp:weblog:categories}
という具合にすれば、カテゴリごとに <a href="{path=main/test}">{category_name}</a>
を呼び出してくれます。
Weblog Categories Tag - ExpressionEngine Documentation

通常、これで生成されるリンクは、
http://www.example.com/index.php/main/C1
という具合に、URLの後ろにテンプレートIDがついた物になりますが、
CP Home › Admin › Weblog Administration › Global Weblog Preferences
にある Use Category URL Titles In Links?
をYesにすると、
http://www.example.com//index.php/main/category/Blogging/
というような、カテゴリ名を使ったURLを生成してくれるようになります。

カテゴリページの内容

 上記URLで表示されるページはどういう内容になっているのでしょう?
別に特別なテンプレートがあるわけではなくて、
http://www.example.com/index.php/main/
用のテンプレートで生成されます。

ただ、
{exp:weblog:entries}
で取得できるブログの記事は、該当カテゴリの物だけに制限されます。
結果として、{exp:weblog:entries}を使って普通にindexページを生成しておけば、該当カテゴリの記事だけが表示される、というわけです。

一見便利そうなこの仕組みですが、普通のブログツールを使い慣れたデザイナさんが、「カテゴリページのデザインです♪」とか言ってトップページと異なるデザインを持ってきたとたん、破綻します。
つまりトップページと同じテンプレートがカテゴリページにも適応されちゃうので、両方に対応したテンプレートを書かないといけなくなるわけです。

べつにデザイナーさんが悪いわけではなくて、カテゴリーページにはそのカテゴリの概要を書きたいとか、ごく普通の要望だと思います。

{if segment_2 == "category"}
を使って切り分けながら書いていけば、同じテンプレートを使い分けることも不可能ではないですが、本来全然別のページとしてデザインしている物を同じテンプレートにつっこむのはかなり大変です。

で、どうするかというと、いっそindexテンプレートをこんな内容にしてしまいます。

{if segment_2 == "category"}
{embed="main/.category"}
{if:else}
{embed="main/.top"}
{/if}
カテゴリページの時は.categoryを呼び出す、そうでないときは.topページを呼び出します。

こうすれば、カテゴリページ用の内容は.categoryに、トップページ用の内容は.topに書くことができて、シンプルなテンプレートにすることができます。


expressionEngineのweblogでは、タイトルの長さ上限が100byteとなっています。
This field contains the title of your weblog entry. Titles can be up to 100 characters in length.
Publish Page - ExpressionEngine Documentation

実際には、日本語35文字を超えたあたりからおかしなことになるようです。
WS000.JPG

英語圏では十分なのでしょうけど、一文字に2byte3byteを消費するマルチバイト圏を考えると、ちょっと微妙な数字です。
実際、movabletypeでは255byte確保していますし、こんなところケチったって仕方なかろうと思うのですけど。

EEフォーラムを探してみると、同じことを考えている人がいました。
Change title maxlength | ExpressionEngine Community Forums

詳しいやり方を教えて頂いたので、ここでご紹介しておきます。
Be Like Water : Changing the Title Maxlength in Expression Engine

ExpressionEngineのテーブル定義を変更します。

[daisuke@snares /var/www/root/html] $ mysql -u expressionengine -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 193 to server version: 4.1.20

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use expressionengine
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed

mysql> show tables;
+----------------------------+
| Tables_in_expressionengine |
+----------------------------+
| exp_actions |
:
| exp_weblog_member_groups |
| exp_weblog_titles |
| exp_weblogs |
+----------------------------+
68 rows in set (0.00 sec)

mysql> show create table exp_weblog_titles;
:
`ip_address` varchar(16) NOT NULL default '',
`title` varchar(100) NOT NULL default '',
`url_title` varchar(75) NOT NULL default '',
:
1 row in set (0.00 sec)

mysql> alter table exp_weblog_titles modify title varchar(255);
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0

mysql> show create table exp_weblog_titles;
:
`ip_address` varchar(16) NOT NULL default '',
`title` varchar(255) default NULL,
`url_title` varchar(75) NOT NULL default '',
:

mysql> exit
Bye
[daisuke@snares /var/www/root/html] $
で、ソースコード側も変更。
[daisuke@snares /var/www/root/html] $ emacs ee/cp/cp.publish.php
[daisuke@snares /var/www/root/html] $ diff ee/cp/cp.publish.php ee/cp/cp.publish.php~
670c670
< $DSP->input_text('title', $title, '20', '256', 'input', '100%', ($which == 'new' OR $which == 'preview') ? 'onkeyup="liveUrlTitle();"' : '', $convert_ascii)
---
> $DSP->input_text('title', $title, '20', '100', 'input', '100%', ($which == 'new' OR $which == 'preview') ? 'onkeyup="liveUrlTitle();"' : '', $convert_ascii)
以上。とくに再起動とか不要です。
WS002.JPG

動作中のシステムを変更しても大丈夫(変更後は256byteまでの長さが使えるようになります)が、非公式なやり方ですので、どうしても必要なときだけにするのがよいかと思います。

それにしても。

For example, one of my client wanted to write an article in Lao, but it turns out that they needed more than 100 characters for their title.

世界にはラオス語のブログを作る需要なんて存在するんですねぇ。



*expressionEngineのアップグレード  無償のCore版だと、EメールモジュールやQueryモジュールが使えないので、ビジネス用途であればCommercial Licenseにアップグレードしたくなるかもしれません。 というわけで、自分がアップグレードしたときの作業記録です。 英語版の手順はこちら。 -[[Upgrading from ExpressionEngine Core to Full Version - ExpressionEngine Documentation:http://expressionengine.com/docs/installation/update_from_core.html]] -[[Updating to New Version of ExpressionEngine - ExpressionEngine Documentation:http://expressionengine.com/docs/installation/update.html]] 自分の場合、1.6.1Coreを使っていたのですが、1.6.2FullVersionを上書きしました。 この場合、ヘルプにも書かれているとおり、upgrade→updateという手順をとります。 **やり方 ライセンスを購入すると、ExpressionEngine Receipt というメールが送られてきます。 これが届いたら、https://secure.expressionengine.com/download.phpから、ExpressionEngine Commercial Licenseがダウンロードできます。 ということで、適当なディレクトリに、ダウンロードしたExpressionEngine Full Versionを配置します。 [furukawa@www tmp]$ unzip ExpressionEngine1.6.2.zip Archive: ExpressionEngine1.6.2.zip creating: ExpressionEngine1.6.2/ inflating: ExpressionEngine1.6.2/build_log.txt : inflating: ExpressionEngine1.6.2/themes/wiki_themes/default/images/bg_page_topbar.jpg inflating: ExpressionEngine1.6.2/themes/wiki_themes/index.html [furukawa@www tmp]$ cd ExpressionEngine1.6.2 [furukawa@www ExpressionEngine1.6.2]$ ls READ_THIS_FIRST.txt images install.php path.php themes build_log.txt index.php license.txt system  念のため、古いファイルをバックアップ [furukawa@www ExpressionEngine1.6.2]$ pushd /var/www/ /var/www ~/tmp/ExpressionEngine1.6.2 [furukawa@www www]$ sudo tar czf html_080303.tgz html Password: [furukawa@www www]$ ls cgi-bin error html html_080303.tgz icons manual usage [furukawa@www www]$ popd ~/tmp/ExpressionEngine1.6.2 ヘルプに書かれているとおり、ファイルを上書きします。 [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf system/language/* /var/www/html/ee/language/ [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf system/modules/* /var/www/html/ee/modules/ [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf themes/profile_themes/* /var/www/html/themes/profile_themes/ [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf themes/wiki_themes/* /var/www/html/themes/wiki_themes/ [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf images/member_photos/* /var/www/html/images/member_photos/ [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf images/pm_attachments/* /var/www/html/images/pm_attachments/ [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf images/signature_attachments/* /var/www/html/images/signature_attachments/ systemディレクトリの名前を変えている人は、コピー先も名前を変えないといけないところに注意です。 これでファイルのアップグレードは完了。 ブラウザからexpressionEngineのsystemにアクセスして、P Home › Admin › System Preferences › General Configuration にあるLicense Numberを入力したらできあがりです。 *システムのupdate  ファイルをコピーして.. [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf system/core/* /var/www/html/ee/core/ [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf system/cp/* /var/www/html/ee/cp/ [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf system/db/* /var/www/html/ee/db/ [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf system/language/* /var/www/html/ee/language/ [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf system/lib/* /var/www/html/ee/lib/ [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf system/modules/* /var/www/html/ee/modules/ [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf system/plugins/* /var/www/html/ee/plugins/ [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf system/updates /var/www/html/ee/ [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf system/update.php* /var/www/html/ee/update.php [furukawa@www ExpressionEngine1.6.2]$ sudo cp -rf system/utilities/* /var/www/html/ee/utilities/ ブラウザでupdate.phpにアクセスします。http://www.example.com/system/update.php というようなパスになるはずです。 サイトの指示に従ってアップデートしたら、update用のファイルを削除してできあがりです。 [furukawa@www ExpressionEngine1.6.2]$ rm /var/www/html/ee/update.php rm: remove write-protected regular file `/var/www/html/ee/update.php'? y rm: cannot remove `/var/www/html/ee/update.php': Permission denied [furukawa@www ExpressionEngine1.6.2]$ sudo rm /var/www/html/ee/update.php [furukawa@www ExpressionEngine1.6.2]$ sudo rm -rf /var/www/html/ee/updates/