さくらVPSを借りて思うことは、「自分の手元にサーバーがないから何が起きているのか把握できない」ということ。だからログって大事なんだと気づかされた。

初歩的なことで申し訳ないが、運用系ミドルウェアの構築などが普段のお仕事なので、自分で作成したスクリプトなりなんなりが、どのように動くのかを把握したいというニーズにはあんまり大した意識を払ったことがなかったのですよ。えぇ。もちろん、ミドルウェアのログはいつも確認しているわけですが、自分がログを出力するという意識はなく、ログは出力されているものだと思っていたわけです。えぇ。

というわけで、ログファイルを出力するための関数を作成してみました。スクリプトファイルが存在するディレクトリ配下のlogディレクトリに、ログファイルを出力します:

#!/usr/bin/env gosh
;;; =========
;;; Variables
;;; =========
;;; ログファイルの名前をここで指定するよ
(define *logfile* "test.log")
;;; =========
;;; Libraries
;;; =========
(use srfi-19)
(use file.util)
;;; =========
;;; Functions
;;; =========
;;; ログに書き込むための日時文字列を生成
;;; フォーマットは「[YYYY-MM-DD HH:MM:SS]」
(define (date-string)
(date->string (current-date)
"[~1 ~3] "))
;;; ログ出力用関数を生成するための関数
(define (logger-make filename)
(lambda (msg)
(call-with-output-file filename
(lambda (port)
(display
(string-append (date-string)
msg
"\n")
port))
:if-exists :append)))
;;; スクリプトが存在するディレクトリ配下に
;;; logディレクトリが存在するかを確認する
;;; 引数はスクリプトが存在するディレクトリ
(define (is-log-directory-exists? script-directory)
(file-is-directory? (string-append
script-directory
"/log/")))
;;; ログファイルの名前を返す関数
(define (logname script-directory)
(string-append script-directory
"/log/"
*logfile*))
;;; 引数としてスクリプトファイル名(つまり(car *argv*)です)
;;; を受け取り、スクリプトファイルが存在するディレクトリを
;;; 返す関数
(define (script-directory script-name)
(receive (path . rest)
(decompose-path script-name)
(if (absolute-path? path)
path
(string-append (current-directory)
"/"
path))))
;;; ====
;;; Main
;;; ====
(define (main *argv*)
(let* ((filename (car *argv*))
(directory (script-directory filename)))
(if (is-log-directory-exists? directory)
(let ((logger (logger-make (logname directory))))
(logger "test"))
(display "Log directory does not exist.")))
)

実行例

kazu634@kazu634% cat 2010-11-01-225103.scm                                            ~/junk [3624]
#!/usr/bin/env gosh
;;; =========
;;; Variables
;;; =========
(define *logfile* "test.log")
;;; =========
;;; Libraries
;;; =========
(use srfi-19)
(use file.util)
;;; =========
;;; Functions
;;; =========
;;; ログに書き込むための日時文字列を生成
;;; フォーマットは「[YYYY-MM-DD HH:MM:SS」
(define (date-string)
(date->string (current-date)
"[~1 ~3] "))
;;; ログ出力用関数を生成するための関数
(define (logger-make filename)
(lambda (msg)
(call-with-output-file filename
(lambda (port)
(display
(string-append (date-string)
msg
"\n")
port))
:if-exists :append)))
;;; スクリプトが存在するディレクトリ配下に
;;; logディレクトリが存在するかを確認する
;;; 引数はスクリプトが存在するディレクトリ
(define (is-log-directory-exists? script-directory)
(file-is-directory? (string-append
script-directory
"/log/")))
;;; ログファイルの名前を返す関数
(define (logname script-directory)
(string-append script-directory
"/log/"
*logfile*))
;;; 引数としてスクリプトファイル名(つまり(car *argv*)です)
;;; を受け取り、スクリプトファイルが存在するディレクトリを
;;; 返す関数
(define (script-directory script-name)
(receive (path . rest)
(decompose-path script-name)
(if (absolute-path? path)
path
(string-append (current-directory)
"/"
path))))
;;; ====
;;; Main
;;; ====
(define (main *argv*)
(let* ((filename (car *argv*))
(directory (script-directory filename)))
(if (is-log-directory-exists? directory)
(let ((logger (logger-make (logname directory))))
(logger "test"))
(display "Log directory does not exist.")))
)
kazu634@kazu634% gosh 2010-11-01-225103.scm                                           ~/junk [3625]
kazu634@kazu634% ll log/                                                              ~/junk [3626]
total 8
-rw-r--r--  1 kazu634  staff   172B 11 13 22:52 test.log
kazu634@kazu634% cat log/test.log                                                     ~/junk [3627]
test
test
[2010-11-13 15:30:38] test
[2010-11-13 15:31:05] test
[2010-11-13 22:28:17] test
[2010-11-13 22:28:31] test
[2010-11-13 22:49:29] test
[2010-11-13 22:52:38] test
kazu634@kazu634% date                                                                 ~/junk [3628]
20101113日 土曜日 225250秒 JST

うまく動いているようです。gaucheでログを書き込むときって、皆さんどうしているんですかね。自分で作るんでしょうね。たぶん。