2008/01/30 (Wed)

setlockを用いてバッチ処理の排他制御を行う。

daemontools

ダウンロード

/package ディレクトリが必要なので作成しStickyビットを立てる

# mkdir -p /package
# chmod 1755 /package

http://cr.yp.to/daemontools/install.html から daemontools-0.76.tar.gz をダウンロード

# cd /package
# wget http://cr.yp.to/daemontools/daemontools-0.76.tar.gz

展開する

# tar xzvfp ./daemontools-0.76.tar.gz
# cd admin/daemontools-0.76

パッチを当てる

http://qmail.org/moni.csi.hu/pub/glibc-2.3.1/ からパッチ(daemontools-0.76.errno.patch)をダウンロード

# cd admin/daemontools-0.76
# wget http://qmail.org/moni.csi.hu/pub/glibc-2.3.1/daemontools-0.76.errno.patch

パッチを当てる。

# patch -p1 < ./daemontools-0.76.errno.patch

インストールする

# ./package/install

setlock の実行

setlock を用いて、排他制御を行う。http://cr.yp.to/daemontools/setlock.html

$ /usr/local/bin/setlock -nx /tmp/hoge.lock hogecommand

2008/01/29 (Tue)

Java Pretty Date

John Resig の記事のJavaScriptを移植した、ISO8601:2004の日付をParseするけれども、 commons-langを使うのが素直。

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

//import org.apache.commons.lang.time.DateFormatUtils

public class PrettyDate {
    public static String prettyDate(String dateString) throws ParseException {
        if (dateString == null)
            return null;

        // Date date = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(date);
        Date date = parse(dateString);
        return prettyDate(date);

    }

    public static String prettyDate(Date date) throws ParseException {
        if (date == null) return null;
        Calendar cal = Calendar.getInstance();
        long diff = (cal.getTime().getTime() - date.getTime()) / 1000;
        double dayDiff = Math.floor(diff / 86400);

        if (dayDiff < 0 || dayDiff >= 31)
            return null;

        if (dayDiff == 0) {
            if (diff < 60   ) return "just now";
            if (diff < 120  ) return "1 minute ago";
            if (diff < 3600 ) return (int) Math.floor(diff / 60) + " minutes ago";
            if (diff < 7200 ) return "1 hour ago";
            if (diff < 86400) return (int) Math.floor(diff / 3600) + " hours ago";
        } else if (dayDiff == 1) {
            return "Yesterday";
        } else if (dayDiff < 7) {
            return (int) dayDiff + " days ago";
        } else if (dayDiff < 31) {
            return (int) Math.ceil(dayDiff / 7) + " weeks ago";
        }
        return null;

    }

    private static final SimpleDateFormat DATE_FORMAT_MILLIS_ISO8601 
            = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
    private static final String        REGEX_DATE_FORMAT_MILLIS_ISO8601 
    = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}[-+]\\d{2}:\\d{2}";

    public static Date parse(String dateString) throws ParseException {
        Date date = null;
        if (dateString.matches(REGEX_DATE_FORMAT_MILLIS_ISO8601)) {
            int index = dateString.lastIndexOf(":");
            StringBuffer sb = new StringBuffer(dateString).deleteCharAt(index);
            date = DATE_FORMAT_MILLIS_ISO8601.parse(sb.toString());
        }
        return date;
    }

    public static void main(String[] args) {
        String[] dateStrings = { "2008-01-29T20:38:17.123+09:00",
                "2008-01-29T20:28:17.123+09:00",
                "2008-01-29T10:28:17.123+09:00",
                "2008-01-28T10:28:17.123+09:00",
                "2008-01-25T10:28:17.123+09:00",
                "2008-01-20T10:28:17.123+09:00", };
        try {
            for (String dateString : dateStrings) {
                System.out.println(PrettyDate.prettyDate(dateString));
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

以下実行結果

prettyDate("2008-01-29T20:38:17.123+09:00")// =>21 minutes ago
prettyDate("2008-01-29T20:28:17.123+09:00")// =>31 minutes ago
prettyDate("2008-01-29T10:28:17.123+09:00")// =>10 hours ago
prettyDate("2008-01-28T10:28:17.123+09:00")// =>Yesterday
prettyDate("2008-01-25T10:28:17.123+09:00")// =>4 days ago
prettyDate("2008-01-20T10:28:17.123+09:00")// =>2 weeks ago

Mark Up 2 Down

構造化テキスト記法

仕事で、インストールマニュアルを作ることが多々あるのだが、 バージョン管理に入れるものはなるべくテキストフォーマットでありたい。 しかし、Wiki記法などでは他人(プログラマ外の人間)にわかりづらいので 出来るだけシンプルなものがいい。そしてなるべく簡単に他のフォーマットへ 変換できるものが欲しい。
Markdown というのがいいらしいので、その記法を採用することにした。

コンバータの導入

早速、インストールマニュアル等を書き直して、HTML に変換することに。 まずは、Windows用に簡単に変換できるコンバータを探したところ、 Pandoc なるものを発見。早速導入する。LinuxなりMacOSなりはもっと簡単に導入できそう。 文字コードが UTF-8 しか通らないようなので KaoriYa.net で配布している Windows 版の iconv を使用させてもらうことに。

上記の二つを展開し、pandoc.exe, iconv.exe, iconv.dll をPATHの通ったディレクトリに。
(自分の場合は、c:\opt\bin に配置)

バッチファイルの作成

1つのファイルに全てを書いてしまうと、後々管理が面倒なので 表示順に番号を振り、バッチ処理で一気に変換することに。 かなり適当ですが、以下を mark2html.bat として c:\opt\bin に配置。

@ECHO OFF
IF (%1)==() GOTO NoParams
IF (%2)==() GOTO ConvertAll
:ConvertOne

iconv -t UTF-8 %2 | pandoc.exe -s -S --toc -A footer.html -c pandoc.css -o %1

GOTO Bottom

:ConvertAll
CD . > tmptmp
FOR %%B IN (*.txt) DO copy /A tmptmp + %%B tmptmp

iconv -t UTF-8 tmptmp | pandoc.exe -s -S --toc -A footer.html -c pandoc.css -o %1

DEL tmptmp

GOTO Bottom
:NoParams
ECHO 使用方法  mark2html [作成するファイル名] [入力するファイル名]
ECHO.
ECHO  例 - mark2html output.html
ECHO    カレントディレクトリにある全ての .txt ファイルを
ECHO    指定されたファイルに変換します。
ECHO  例 - mark2html output.html input.txt
ECHO    input.txt を 指定されたファイルに変換します。
ECHO.
:Bottom

Blosxomを導入

一通り回ってやっぱりBlosxomに返って来た。テキストで管理したいというのがやはり最大の理由。というわけで再度設定することに。

  1. hail2u.net - Archives - blosxom starter kit から blosxom starter kit 1.1.3 をダウンロードし、展開。config.cgiを変更する。
  2. blosxom :: the zen of blogging :: plugins/general/flavourdir.txt から flavourdirプラグインをダウンロード pluginsディレクトリに入れる。
  3. entries以下にflavoursというディレクトリを作り、フレーバーファイルを全てその中に移す。
  4. blosxom.cgiの名前をblogに変更する。
  5. .htaccess に以下の記述をする。

    <Files blog>
        SetHandler cgi-script
    </Files>
    
  6. Markdown からmarkdown.plダウンロードする。最新版はおそらく以下
    http://daringfireball.net/projects/downloads/Markdown_1.0.2b4.tar.gz

  7. markdown.pl を markdown に変更し、plugins フォルダに入れる。
  8. 投稿テキストはUTF-8、一行目がタイトル、あとはMarkdown記法で記述してアップロード
  9. 以上で http://www5.big.or.jp/~tex/blog にアクセスできるようになる。

追記

SPAM防止のために、story.rssから

(mailto:$rss10::email)

<trackback:ping rdf:resource="$url$path/$fn.trackback"/>

を削除した。

また、story.html, story.htm から Auto Trackback Discovery 用の記述も削除

<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <rdf:Description
    rdf:about="$url$path/$fn.htm"
    dc:identifier="$url$path/$fn.htm"
    dc:title="$title"
    trackback:ping="$url$path/$fn.trackback"/>
</rdf:RDF>
-->