<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>dTblog | design and programming</title>
<link>http://www.deftrash.com/blog/</link>
<description>デザインから開発まで色んな局面でWebと関わる人のよもやま話。</description>
<language>ja</language>
<copyright>Copyright 2008</copyright>
<lastBuildDate>Tue, 14 Oct 2008 23:36:22 +0900</lastBuildDate>
<generator>http://www.movabletype.org/?v=3.2-ja-2</generator>
<docs>http://blogs.law.harvard.edu/tech/rss</docs> 

<item>
<title>Excel 形式の帳票ツール</title>
<description><![CDATA[<p>Java で Excel 形式の帳票を作成するのに、いままでは <a href="http://poi.apache.org/">Jakarta POI </a> の HSSF でゴリゴリとコーディングしていたのだけど、レイアウトに対して決して直感的なソースじゃないし、フォーマット変更に対する保守性も低いので、何か別の方法はないかと思っていた。</p>

<p>とりあえず有名どころと思って、<a href="http://www.jasperforge.org/jaspersoft/opensource/business_intelligence/ireport/">iReport</a> と <a href="http://www.jasperforge.org/jaspersoft/opensource/business_intelligence/jasperreports/">JasperReport </a> を触ってみたんだけど、ダメ。</p>

<p>iReport は非常に優れた帳票デザイナーで、これがフリーだということに驚愕すること間違いなしなんだけど、いかんせん、出てくる Excel が使えない。見た目は確かにレイアウトどおりなんだろうけど、行と列がグチャグチャ。出力後に人間が加工するような感じではない。PDF 形式で出力するのであれば、かなり優秀なので、選択肢として検討する余地はあるけど。</p>

<p>やっぱり、HSSF でゴリゴリ行くしかないのかな。レイアウトした xls を読み込んで、データを書き出して出力するようにすれば、iReport のように直感的でないけど、そこそこレイアウト変更にも柔軟に対応できそうな気もする。（xlsとHSSFを結びつけるための、レイアウト情報をどう管理するかっていう問題は考えないといけないけど）</p>

<p><a href="http://www.eclipse.org/birt/phoenix/">BIRT </a>も Excel 出力ができるらしい。こちらは、どうなんだろう。今度さわってみよう。</p>]]></description>
<link>http://www.deftrash.com/blog/archives/2008/10/excel_report.html</link>
<guid>http://www.deftrash.com/blog/archives/2008/10/excel_report.html</guid>
<category>java</category>
<pubDate>Tue, 14 Oct 2008 23:36:22 +0900</pubDate>
</item>
<item>
<title>bashでヒアドキュメントをリダイレクト</title>
<description><![CDATA[<p>ヒアドキュメントを使って、ファイルに内容を書き出そうと思ったんだけど、どこにリダイレクトを書くのか分からなくて苦戦した。ううう。</p>

<p>正解はこちら。最初に指定しておくのか。なるほど。</p>

<pre class="code">
cat << HERE >> /tmp/hoge 2>&1
xxxxxx
yyyyyy
zzzzzz
HERE
</pre>

<p>bashのヒアドキュメントは、メール送信以外で使ったのは、これが初めてかもしれない。便利な仕組みだけど、あんまり用途が思いつかない。</p>]]></description>
<link>http://www.deftrash.com/blog/archives/2008/10/bash.html</link>
<guid>http://www.deftrash.com/blog/archives/2008/10/bash.html</guid>
<category>linux</category>
<pubDate>Sun, 05 Oct 2008 17:46:22 +0900</pubDate>
</item>
<item>
<title>validwhen では小数の大小比較が行えない</title>
<description><![CDATA[<p>struts の validwhen では、小数付きの数値比較が正しく行われない。</p>

<p>ソースを追ってみたところ、ValidWhenParser クラスで比較処理をしていたのだけど、これが int 型で比較できる場合は数値として比較、それ以外はすべて String で比較するという処理になっていた。えー、整数だけですか。全然かゆいところに手が届いていない！</p>

<p>これのタチ悪いところは、小数値であっても比較処理自体は行われる点。そう、文字列として比較して、その結果たまに正しい結果を返してしまう。厄介だ。</p>

<p>例えば、start と end という数値入力するフィールドがあって、その大小関係が逆転しないように入力チェックをするとき、</p>

<pre class="code">
((start == null) or (*this* <= end))
</pre>

<p>と validwhen 式を書いて、</p>

<pre class="code">
private String start = "9.5";
private String end = "11";
</pre>

<p>とすると、文字列での比較となり、1より9の方が後になるってんで、大小関係が正しいにも関わらずエラーとして検証に引っかかってしまう。</p>

<pre class="code">
private String start = "2.5";
private String end = "5";
</pre>

<p>という場合は、小数があっても正しい検証結果を返すので、問題なし。こんな感じで一見すると正しく動いているようにみえるので、むーって感じ。ハマリました。</p>

<p>そんなわけで、validwhen は整数の比較と、文字列の比較のときのみ使用するようにしなくちゃいけないです。いや、もう文字列に限定して使用するものだと捉えた方が良いかもしれない。そして数値比較用には、自前で検証メソッドを作成してしまった方が、間違いがなくて良さそう。（または ValidWhenParser の処理そのものを小数対応に直しちゃうのもアリ）</p>

<p>BigDecimal で比較、いやせめて Double で比較してくれれば良かったのに…。</p>]]></description>
<link>http://www.deftrash.com/blog/archives/2008/09/validwhen.html</link>
<guid>http://www.deftrash.com/blog/archives/2008/09/validwhen.html</guid>
<category>java</category>
<pubDate>Thu, 04 Sep 2008 16:31:46 +0900</pubDate>
</item>
<item>
<title>Tiles Hack のステップアップ</title>
<description><![CDATA[<p>Tiles Hack だなんて大げさだ。</p>

<p>Struts の Tiles プラグインの挙動を変更したくなった。動的に definition を追加したい。どこから手を付けて良いものか悩んでいたのだけど、DefinitionsFatory を自作のものに変更できることが判明したので、これで対応した。</p>

<p>struts-config.xml で Tiles プラグインを設定している箇所で、definitions-factory-class プロパティに、自作の Factory クラスを指定してあげるだけ。</p>

<pre class="code">
  &lt;plug-in className="org.apache.struts.tiles.TilesPlugin"&gt;
    &lt;set-property property="definitions-factory-class" value="com.deftrash.struts.OriginalI18nFactorySet" /&gt;
    &lt;set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml"/&gt;
    &lt;set-property property="moduleAware" value="true"/&gt;
  &lt;/plug-in&gt;
</pre>

<p>definitions-factory-class を指定しない場合は、デフォルトで、org.apache.struts.tiles.xmlDefinition.I18nFactorySet が使用される。tiles-defs.xml を読み込んで、ComponentDefinition を生成するクラスだ。</p>

<p>動的に definition を追加するために、自作 Factory を、この I18nFactorySet を継承して作成。createDefaultFactory メソッドをオーバーライドして改造することにした。</p>

<pre class="code">
    /* (非 Javadoc)
     * @see org.apache.struts.tiles.xmlDefinition.I18nFactorySet#createDefaultFactory(javax.servlet.ServletContext)
     */
    protected DefinitionsFactory createDefaultFactory(ServletContext servletContext)
            throws DefinitionsFactoryException, FileNotFoundException {
<br />
        DefinitionsFactory factory = super.createDefaultFactory(servletContext);
<br />
        // TODO 動的にComponentDefinitionを追加する処理をここに
<br />
        return factory;
</pre>

<p>たったこれだけで、望むべき動作が得られました。動的に definition を追加する以外のニーズがあっても、ここを起点にいくらでも改造できそうな感じ。まあ、I18nFactorySet クラスで xml を読み出すところが private になっているのが、扱いづらいけど。</p>

<p>すでに struts は枯れて細かいところまで見ずにいたけど、実際に手を入れていこうとすると、改造しやすいように窓口が開いていて、風の通しがすごい良いことに気付く。こういう懐の深いデザインは、見習っていきたいですね。</p>]]></description>
<link>http://www.deftrash.com/blog/archives/2008/08/tiles_hack.html</link>
<guid>http://www.deftrash.com/blog/archives/2008/08/tiles_hack.html</guid>
<category>java</category>
<pubDate>Tue, 12 Aug 2008 16:40:53 +0900</pubDate>
</item>
<item>
<title>Strutsで独自のModuleConfigFactoryを利用する方法</title>
<description><![CDATA[<p>struts-config.xml で定義した内容を動的に変更したくなって、ActionConfig を改造する方法を考えていたんだけど、大元の ModuleConfigFactory を切り替えて、独自の ModuleConfig を生成する Factory クラスを用意すれば良いことが分かった。なるほどー、よくできてるなー。</p>

<p>web.xml で configFactory パラメータに、独自の ModuleConfigFactory のクラスを指定してあげればOK。</p>

<pre class="code">
  &lt;servlet&gt;
    &lt;servlet-name&gt;action&lt;/servlet-name&gt;
    &lt;servlet-class&gt;org.apache.struts.action.ActionServlet&lt;/servlet-class&gt;
    &lt;init-param&gt;
      &lt;param-name&gt;config&lt;/param-name&gt;
      &lt;param-value&gt;/WEB-INF/struts-config.xml&lt;/param-value&gt;
    &lt;/init-param&gt;
    &lt;init-param&gt;
      &lt;param-name&gt;configFactory&lt;/param-name&gt;
      &lt;param-value&gt;com.deftrash.OriginalModuleConfigFactory&lt;/param-value&gt;      
    &lt;/init-param&gt;
    &lt;init-param&gt;
      &lt;param-name&gt;debug&lt;/param-name&gt;
      &lt;param-value&gt;2&lt;/param-value&gt;
    &lt;/init-param&gt;
    &lt;init-param&gt;
      &lt;param-name&gt;detail&lt;/param-name&gt;
      &lt;param-value&gt;2&lt;/param-value&gt;
    &lt;/init-param&gt;
    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
  &lt;/servlet&gt;
</pre>

<p>いろいろ調べてようやく分かったんだけど、よくよく考えてみると SAStruts の仕組みを見れば一発で分かったんだよなあ。ううう。</p>

<p>そして、もともとはフォワード先のパスを変えたいだけだったので、それなら Filter で ActionConfig を見てごにょごにょやった方がシンプルだったかも。この方法は、少し大げさな感じもする。こういう手段があるのが分かっただけで、前進ですが。</p>

<p>ActionServlet クラスのソースを見ると、他にも細かな制御ができるようになっているのが分かる。このあたりを押さえておくと、プロジェクトに応じて Struts をより柔軟にコントロールできる。知らないって、スゴイ損ですねえ。ふぅ。</p>]]></description>
<link>http://www.deftrash.com/blog/archives/2008/07/strutsmoduleconfigfactory.html</link>
<guid>http://www.deftrash.com/blog/archives/2008/07/strutsmoduleconfigfactory.html</guid>
<category>java</category>
<pubDate>Thu, 24 Jul 2008 23:35:59 +0900</pubDate>
</item>
<item>
<title>PostgreSQLで半角カナを全角カナに変換する関数</title>
<description><![CDATA[<p>半角カナでの登録を拒否するために、自動で全角カナに変換したいときってあるじゃないですか。アプリケーション側で、AOPやFilterといった仕組みで変換してあげる方がスマートだと思ってるんだけど、DB側でやらないといけないケースもあるでしょう。</p>

<p>ということで、こんな関数を用意してみました。</p>

<pre class="code">
CREATE OR REPLACE FUNCTION h2z_kana(text) 
  RETURNS text AS
$BODY$
    DECLARE
        zenkaku alias FOR $1;
        result text;
        i int;
<br />
        zt varchar[] = ARRAY['ガ', 'ギ', 'グ', 'ゲ', 'ゴ', 'ザ', 'ジ', 'ズ', 'ゼ', 'ゾ', 'ダ', 'ヂ', 'ヅ', 'デ', 'ド', 'バ', 'ビ', 'ブ', 'ベ', 'ボ', 'パ', 'ピ', 'プ', 'ペ', 'ポ', 'ヴ'];
        ht varchar[] = ARRAY['ｶﾞ', 'ｷﾞ', 'ｸﾞ', 'ｹﾞ', 'ｺﾞ', 'ｻﾞ', 'ｼﾞ', 'ｽﾞ', 'ｾﾞ', 'ｿﾞ', 'ﾀﾞ', 'ﾁﾞ', 'ﾂﾞ', 'ﾃﾞ', 'ﾄﾞ', 'ﾊﾞ', 'ﾋﾞ', 'ﾌﾞ', 'ﾍﾞ', 'ﾎﾞ', 'ﾊﾟ', 'ﾋﾟ', 'ﾌﾟ', 'ﾍﾟ', 'ﾎﾟ', 'ｳﾞ'];
    BEGIN
<br />
        result = zenkaku;
<br />
        -- 2バイトで変換
        FOR i IN 1..26 LOOP
            result = replace(result, ht[i], zt[i]);
        END LOOP;
<br />
        -- 1バイトで変換
        result = translate(result,
                   ' ｱｲｳｴｵｶｷｸｹｺｻｼｽｾｿﾀﾁﾂﾃﾄﾅﾆﾇﾈﾉﾊﾋﾌﾍﾎﾏﾐﾑﾒﾓﾔﾕﾖﾗﾘﾙﾚﾛﾜｦﾝｧｨｩｪｫｯｬｭｮﾜｲｴｶｹｰ､｡･｣｢ﾞ,<.>/?_}]*:+;{[~@|\\`^=-)(&%$#"!',
                   '　アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォッャュョヮヰヱヵヶー、。・」「゛，＜．＞／？＿｝］＊：＋；｛［￣＠｜￥｀＾＝－）（＆％＄＃”！'
              );
<br />
        RETURN result;
    END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE;
</pre>

<p>ガやザのような濁音のものは、半角カナになるとカと濁点の合計2バイトになる。まずはじめに変換テーブルを用いてそれらを置換してから、残る半角カナを一括して置換してます。記号の置換処理のところは、不要なら除けばOK。でも、大体のケースであっても困らないと思いますけど。</p>

<p>あとは、この関数を使って UPDATE するトリガーを、INSERT と UPDATE 時に発動するように定義してあげれば、冒頭の件は対応できると思います。</p>

<p>DBから値を引っ張ってきて、そのままメール送信するようなケースで、半角カナが含まれてたらイヤンなときにも活用できるかな。そのケースでは、機種依存文字全般の対応もあるので、送信プログラム側でもろもろを処理した方が、スッキリするかしら？</p>

<p>ま、ひとつの参考までに。</p>]]></description>
<link>http://www.deftrash.com/blog/archives/2008/07/h2z_kana.html</link>
<guid>http://www.deftrash.com/blog/archives/2008/07/h2z_kana.html</guid>
<category>db</category>
<pubDate>Tue, 15 Jul 2008 22:49:41 +0900</pubDate>
</item>
<item>
<title>NULL文字を削除する</title>
<description><![CDATA[<p>csvデータをpostgresqlにインポートしようとしたら、エラーが。</p>

<pre class="code">
ERROR:  invalid byte sequence for encoding "SJIS": 0x00
</pre>

<p>NULL文字が含まれているのが、納得いかないようす。NULL文字は目で見えない制御文字なので、どうやって削除したもんかなーと思ったら、trコマンドで簡単に除去できました。</p>

<pre class="code">
$ cat src.csv | tr -d "\000" > dest.csv
</pre>

<p>これでインポートはバッチリでした。</p>]]></description>
<link>http://www.deftrash.com/blog/archives/2008/07/trnullchar.html</link>
<guid>http://www.deftrash.com/blog/archives/2008/07/trnullchar.html</guid>
<category>linux</category>
<pubDate>Wed, 09 Jul 2008 12:56:43 +0900</pubDate>
</item>
<item>
<title>PostgreSQLの配列を使って文字列を集約をする方法</title>
<description><![CDATA[<p>1対N（OneToMany）の関係にある2つのエンティティについて、N個の文字列を集約する必要があって、方法を考えてみた。</p>

<p>次のような部署マスタと社員マスタを例にとって、説明します。</p>

<p><img alt="20080703_ER.png" src="http://www.deftrash.com/blog/archives/contents/20080703_ER.png" width="374" height="97" /></p>

<p>これに対して、次のような表を出すという要件。</p>

<table class="basic">
 <colgroup><col width="150" /><col width="150" /></colgroup>
 <thead>
  <th>部署</th>
  <th>所属社員</th>
 </thead>
 <tbody>
  <tr>
   <th>営業1課</th>
   <td>佐藤<br />山下<br />高山</td>
  </tr>
  <tr>
   <th>営業2課</th>
   <td>大野<br />池本<br />野崎</td>
  </tr>
 </tbody>
</table>

<p>「2つのエンティティを JOIN すれば良いじゃん」という声もあるけど、単純に結合しちゃうと、結果セットから取り出すとき、もしくは表示時点でプログラムでごにょごにょやらないと、うまくいかない。所属社員の一覧を、改行区切りの文字列として、ひとつの変数に格納できれば、らくちん。要するに、DBから値を取得する時点で、表示するときの形まで持っていきたいという話。</p>

<p>ここの方法については賛否両論あるかもしれないけど、SQLはプログラムが最もシンプルで済むような結果が得られるように書くべきだと思ってます。</p>

<p>話が逸れたけど、じゃあ、それをどうやってやるか、という話ですよ。</p>]]></description>
<link>http://www.deftrash.com/blog/archives/2008/07/postgresql.html</link>
<guid>http://www.deftrash.com/blog/archives/2008/07/postgresql.html</guid>
<category>db</category>
<pubDate>Thu, 03 Jul 2008 23:30:17 +0900</pubDate>
</item>
<item>
<title>FreeBSDのJVMでエラーが起きる</title>
<description><![CDATA[<p>FreeBSD のサーバに、Java5 と Tomcat5.5 を乗っけて起動したら、OOME で落ちてしまった。ログを見ると、かつて見たことのない内容が。</p>

<pre class="code">
Exception in thread "CompilerThread0" java.lang.OutOfMemoryError: 
requested 1168080 bytes for Chunk::new. Out of swap space?
</pre>

<p>スワップ領域って何のことだろうか。JVMのなかの話だと思うのだけど。</p>

<p>メモリ関連ということで、-Xmx や -Xss などのパラメータをいじるものの状況は改善せず。んで、ひとつひとつ除いていったら分かりました。</p>

<pre class="code">
CATALINA_OPTS="-server"
</pre>

<p>というように、サーバクラスを指定していたのだけど、これが原因だった。FreeBSD全部がそうなのか分からないけど、今回のケースではクライアントVMでしか起動できないという罠。うー、しびれるなあ。</p>

<p><a href="http://sdc.sun.co.jp/java/docs/j2se/1.5.0/ja/docs/ja/guide/vm/server-class.html" target="_blank">サーバクラスマシンの検出</a>にあるとおり、Java5からはサーバ環境に応じて自動でVMを切り替えてくれるということで、下手に指定なんてしなくても良かったんですね。（まあ、FreeBSDのJVMでも互換性があるのかは分かりませんが…）</p>

<p>Linux の方が上だとか言うつもりは毛頭ないけど、個人的には FreeBSD より Linux の方が良いなあ。習慣もあるんだろうけども、エンタープライズ用途だと何かと情報が得やすい Linux や Solaris でないと、ちょっとひるんでしまいますねえ。</p>]]></description>
<link>http://www.deftrash.com/blog/archives/2008/07/freebsdjvm.html</link>
<guid>http://www.deftrash.com/blog/archives/2008/07/freebsdjvm.html</guid>
<category>java</category>
<pubDate>Tue, 01 Jul 2008 14:05:25 +0900</pubDate>
</item>
<item>
<title>ロープ・データ構造</title>
<description><![CDATA[<p><a href="http://www.ibm.com/developerworks/jp/java/library/j-ropes/">ロープ： 理論と実践</a></p>

<p>String や StringBuilder に代わる効率的なデータ構造「ロープ」。java で大量文字列を処理する場合の、新しい解だ。ストリングに対してロープとな。なるほど。</p>

<p>意味が理解できたところで、さて何に使ったら良いもんか。「顕著なパフォーマンスの改善が期待できるのは、大規模なストリングを大々的に変更するような場合のみです」と言われても、それこそ例として挙げられているテキスト・エディタのようなものしか思い浮かばない。そもそも、単一のストリングがそこまで大規模になったケースを知らない。うーん。</p>

<p>ま、アイデアとしてストックしておけば、他でも使えるかな。</p>

<p>ちなみに、「O(n)」とか「O(log n)」とかをビッグオー記法と呼ぶのを、この記事で初めて知りました。これ、意味は分かるんだけど、どのくらいのオーダーの差があるのか直感的に分かりづらい…。早く自然数と対数がサラッと比較できるようなビジネスマンになりたいです。</p>]]></description>
<link>http://www.deftrash.com/blog/archives/2008/06/java_rope.html</link>
<guid>http://www.deftrash.com/blog/archives/2008/06/java_rope.html</guid>
<category>java</category>
<pubDate>Wed, 04 Jun 2008 14:15:24 +0900</pubDate>
</item>
<item>
<title>tomcat6 のログ出力を Log4j で行う方法</title>
<description><![CDATA[<p>これで、かなり快適なロギング環境を構築することができました。すごい便利。</p>

<p>事の始まりは、tomcat6 のログローテションを自前で行おうとしたことだった。tomcat6 では、デフォルトで日付付きのログファイルを出力するのだけど、それだと自前のローテーション処理とぶつかってしまう。これはどげんかせんといかん、と言うわけで、<a href="http://www.oki.com/jp/oss/document/tomcat/tomcat-6.0.14/build/tomcat-docs/logging.html" target="_blank">公式マニュアル</a>を見たら、Log4J を使う方法が書いてあったので、「これだ！」と。</p>

<p>しかし、Log4J の効果はローテーションに留まらず。ログ出力内容の細かなコントロールも可能になったことで、運用上必要なログのみを出力するようにできたり、かなり嬉しいことに。やってて良かった公文式。（違う）</p>

<p>以下、Log4J 導入までの流れ。（ほとんどマニュアルと同じですが）</p>]]></description>
<link>http://www.deftrash.com/blog/archives/2008/06/tomcat6_log4j.html</link>
<guid>http://www.deftrash.com/blog/archives/2008/06/tomcat6_log4j.html</guid>
<category>java</category>
<pubDate>Sun, 01 Jun 2008 22:25:40 +0900</pubDate>
</item>
<item>
<title>Linuxの圧縮/解凍コマンドまとめ</title>
<description><![CDATA[<p>マイナーな圧縮形式になるとコマンドを忘れがちなので、まとめのメモ。</p>

<p>まずは基本の gz 形式から。（さすがに忘れないけど）</p>

<pre class="code">
圧縮
$ gzip filename
解凍
$ gunzip filename.gz
</pre>

<p>続いて、tar.gz (tgz) 形式。（これも忘れないなあ）</p>

<pre class="code">
圧縮
$ tar cvfz dirname.tar.gz dirname
解凍
$ tar xvfz dirname.tar.gz
</pre>

<p>bzip2 (bz2) 形式。</p>

<pre class="code">
圧縮
$ bzip2 filename
解凍
$ bzip2 -d filename.bz2
</pre>

<p>tar.bz2 形式。</p>

<pre class="code">
圧縮
$ tar cvfj dirname.tar.bz2 dirname
解凍
$ tar xvfj dirname.tar.bz2
</pre>

<p>Windowsとのデータやり取りの基本、ZIP形式。</p>

<pre class="code">
圧縮
$ zip filename.zip file1 file2
解凍
$ unzip filename.zip
</pre>

<p>これまたWindowsとデータ交換するとよく出てくるLZH形式。</p>

<pre class="code">
圧縮
$ lha -a filename.lzh file1 file2
解凍
$ lha -e filename.lzh
</pre>

<p>こんなところでしょうか。個人的には、tar.bz2形式とLZH形式の解凍が、いつも一発でいきません。あうあう。どうもオプションが覚えられないんだよなあ。チートシート、チートシート、と。</p>]]></description>
<link>http://www.deftrash.com/blog/archives/2008/05/linux_commands.html</link>
<guid>http://www.deftrash.com/blog/archives/2008/05/linux_commands.html</guid>
<category>linux</category>
<pubDate>Sat, 31 May 2008 18:44:45 +0900</pubDate>
</item>
<item>
<title>FTP専用ユーザーを作ってみる</title>
<description><![CDATA[<p>年に1回くらい需要があることが分かったので、ここらへんでメモしてみる。</p>

<pre class="code">
# useradd -s /sbin/nologin -M ftpuser
# passwd ftpuser
# mkdir -p /ftp/userdir
# usermod -d /ftp/userdir ftpuser
# chown ftpuser:ftpuser /ftp/userdir
# chmod 705 /ftp/userdir
</pre>

<p>useradd で /sbin/nologin を指定することで、telnet などでログインできないユーザを作成できる。また、-M オプションを付けると、ホームディレクトリを作成せずにユーザを作成するので、不要なメールボックスが作成されないで済む。FTP先のディレクトリは、usermod で後から設定してあげればOK。</p>

<p>ざっくりこんな感じ。</p>

<p>ただ、qmail が動いていると、メールボックスは無いんだけれども、/etc/passwd にエントリされるだけで、有効なアカウントと判断してしまう。だもんで、例えば ftpuser 宛にメールをすると、ローカル配送してしまう。まあ、メールボックスが無くてエラーになるので、目的を達成してはいるんだけど、"no mailbox" なエラーじゃないので、いただけない。</p>

<p>ここらへん、厳密に対処するのであれば、<a href="http://www.deftrash.com/blog/archives/2005/09/qmail.html">qmail でメールアカウントだけを削除する方法</a>のように、ごにょごにょしてやらないといけない。ちょっと大げさ。</p>

<p>色んなサービスが動いていると、細かいところで厄介になるなー。</p>]]></description>
<link>http://www.deftrash.com/blog/archives/2008/05/ftpuser.html</link>
<guid>http://www.deftrash.com/blog/archives/2008/05/ftpuser.html</guid>
<category>linux</category>
<pubDate>Wed, 21 May 2008 23:52:14 +0900</pubDate>
</item>
<item>
<title>SSLのパスフレーズ入力を回避する方法</title>
<description><![CDATA[<p>SSLを設定してApacheを立ち上げようとすると、秘密鍵のパスフレーズを問合せてくる。</p>

<p>手動で運用している分には問題ないのだけれども、スクリプトで起動するような操作をする場合に面倒くさいことになる。そこで、パスフレーズの入力を回避してみる。</p>

<pre class="code">
# openssl rsa -in server.key -out server.key.nopass
</pre>

<p>これで、元の秘密鍵からパスフレーズ抜きの鍵を生成して、これを SSLCertificateKeyFile に指定してあげれば、次回の起動からはパスフレーズの入力なしで、Apacheを起動できます。わーい、便利。</p>

<p>ただし当然ながら、これはセキュリティ上、好ましくないので、単純に「めんどくせえなあ」ということなら、やめておいた方が良いと思います。そういう意味では、裏技ですね。</p>

<p>ちなみに、</p>

<pre class="code">
# apachectl startssl
</pre>

<p>として起動しようとしたら、怒られてしまった。</p>

<p>Apache2.2からは、startssl などと書かずに、普通に start や graceful でSSL起動ができるようになったとのこと。ほう、こりゃまた便利な世の中ですなあ。</p>

<p>ということで、</p>

<pre class="code">
# apachectl start
</pre>

<p>のコマンド一発で、パスフレーズ入力もなく、SSLを意識せずにApacheの運用が出来るようになりました。お疲れさまでした。</p>]]></description>
<link>http://www.deftrash.com/blog/archives/2008/05/apache_ssl.html</link>
<guid>http://www.deftrash.com/blog/archives/2008/05/apache_ssl.html</guid>
<category>linux</category>
<pubDate>Mon, 19 May 2008 23:19:59 +0900</pubDate>
</item>
<item>
<title>複数トリガーの実行順序</title>
<description><![CDATA[<p>PostgreSQLで、同一イベントに複数のトリガーがある場合に、どういう順番で実行されるのか気になったので調べてみた。</p>

<blockquote>
<div class="quote">
<a href="http://www.postgresql.jp/document/pg824doc/html/trigger-definition.html">トリガ動作の概要</a>
同一リレーション、同一イベントに対して1つ以上のトリガが定義された場合、トリガはその名前のアルファベット順に発生します。 BEFOREトリガの場合では、各トリガで返される、変更された可能性がある行が次のトリガの入力となります。もし、あるBEFOREトリガがNULLを返したら、操作はその行で中断し、残りのトリガは発生しません。 
</div>
</blockquote>

<p>アルファベット順、これは予想外だった。以前は順番を保証することさえなかったみたいだから、それに比べたら方法があるだけマシなのかもしれないけど、トリガ名を考えないといけないということか。なんか明示的な制御の方法はないのかな。</p>]]></description>
<link>http://www.deftrash.com/blog/archives/2008/05/multi_trigger.html</link>
<guid>http://www.deftrash.com/blog/archives/2008/05/multi_trigger.html</guid>
<category>db</category>
<pubDate>Fri, 16 May 2008 12:30:14 +0900</pubDate>
</item>


</channel>
</rss>