2011年12月17日土曜日

さくらVPSでOpenBSD (squidの設定)

squidをインストールして設定してみます。

squidはproxyサーバーですが、自分の場合「外出時にiphoneなどで何処かのサイトにアクセスしたいけど、不要な画像とかは表示したくないのでsquidでブロックしちゃうよ。」的な使い方になります。

このようなコンテンツフィルタリングにはsquidGuardなどがありますが、そこまでやる気はない(サーバーの物理メモリも少ないのでプロセスはあまり立ち上げたくない)ので、squidで出来る程度のフィルタリングになります。

設定ポリシーは

  • squidのバージョンは2.7(portsでインストール)
  • squidだけで、コンテンツフィルタリングするぞ。
  • ディスクがもったいないので、コンテンツのキャッシュは無効にします。
  • 外部からのアクセスなので、Proxy認証をかけます。
  • 画像をブロックしたときにエラーページを返すとレイアウトが崩れるのでなんとかする。

インストール

portsでインストールします。

# cd /usr/ports/www/squid/
# make install
# make clean=depends
#

/etc/rc.conf.localの設定

インストールが完了したら、/etc/rc.conf.localに下記の設定を追加します

squid_flags=""
pkg_scripts="postfix saslauthd …… 略 …… courier_imap_ssl squid"


アクセスコントロールの設定

最初にaclの設定をします。この辺はデフォルトの設定をコピペしただけです。

# Recommended minimum configuration:
#
acl all src all
acl manager proto cache_object
acl localhost src 127.0.0.1/32
acl to_localhost dst 127.0.0.0/8 0.0.0.0/32

# Example rule allowing access from your local networks.
# Adapt to list your (internal) IP networks from where browsing
# should be allowed
acl localnet src 10.0.0.0/8	    # RFC1918 possible internal network
acl localnet src 172.16.0.0/12	# RFC1918 possible internal network
acl localnet src 192.168.0.0/16	# RFC1918 possible internal network

acl SSL_ports  port 443
acl Safe_ports port 80		# http
acl Safe_ports port 21		# ftp
acl Safe_ports port 443		# https
acl Safe_ports port 70		# gopher
acl Safe_ports port 210		# wais
acl Safe_ports port 1025-65535	# unregistered ports
acl Safe_ports port 280		# http-mgmt
acl Safe_ports port 488		# gss-http
acl Safe_ports port 591		# filemaker
acl Safe_ports port 777		# multiling http
acl CONNECT method CONNECT

ブラックリストの設定とキャッシュの無効化

/etc/squidにコンテンツフィルタリングの設定ファイル、whitelist.txt blacklist.txt blackpath.txtを置く事にします。また全てのアクセスをキャッシュしない設定にします。

# blacklistとwhitelistの設定
acl whitelist url_regex -i     "/etc/squid/whitelist.txt"
acl blacklist url_regex        "/etc/squid/blacklist.txt"
acl blackpath urlpath_regex -i "/etc/squid/blackpath.txt"

# cacheを無効にする
no_cache deny all

squidアクセスの制限設定

aclのblacklist・blackpathで定義したコンテンツはブロックします。aclのwhitelistで定義したコンテンツはブロックしません。

# cachemgrアクセス(キャッシュされたオブジェクト情報へのアクセス)は
# ローカルホストからのみ許可する。
http_access allow manager localhost
http_access deny  manager
# acl名Safe_portsで定義したポート以外へのリクエストを拒否する。
http_access deny !Safe_ports
# SSLポート以外へのCONNECTメソッドのリクエストは拒否する。
http_access deny CONNECT !SSL_ports

# whitelistは許可 と blacklist拒否
http_access allow whitelist
http_access deny  blacklist
http_access deny  blackpath
deny_info http://blackhole.example.com/index.php?url=%s blacklist
deny_info http://blackhole.example.com/index.php?url=%s blackpath

# ローカルホスト ローカルネットからのアクセスは許可する。
http_access allow localnet
http_access allow localhost

画像をブロックするとリンク切れの状態なる問題

blacklistで画像をブロックすると、squidは空白のページを返してきます。するとsafariなどのブラウザは画像のリンクが切れていると判断して、はてなマークのアイコンを表示してしまい画面が見づらくなってしまいます。

画像link切れ

これを回避するために下記の設定を行い、ブロックした場合はhttp://blackhole.example.com/index.phpに飛ばします。index.phpでは引数に指定されたURLにより出力内容を変えてあげます。

deny_info http://blackhole.example.com/index.php?url=%s blacklist
deny_info http://blackhole.example.com/index.php?url=%s blackpath

index.phpは拡張子をみて、それに見合った1dotの白画像を出力するだけの簡単なプログラムです。

<?php
error_reporting(0);
if(preg_match('/\.(jpeg|jpg|jpe)$/',$_GET['url'])){
    $img = file_get_contents('./images/spacer.jpg') ;
    header('Content-type: image/jpeg') ;
    echo $img ;
}
elseif(preg_match('/\.(png)$/',$_GET['url'])){
    $img = file_get_contents('./images/spacer.png') ;
    header('Content-type: image/png') ;
    echo $img ;
}
elseif(preg_match('/\.(gif)$/',$_GET['url'])){
    $img = file_get_contents('./images/spacer.gif') ;
    header('Content-type: image/gif') ;
    echo $img ;
}
else{
    echo "" ;
}
?>

この設定をした後の画面は下記のようになりすっきりします。

画像link切れ対処

認証の設定

外部サイトのproxyなので他人に使用されないように認証をかけます。basic認証だと平文でパスワードが流れてしまうので、Digest認証を使うことにします。

## 認証設定
# digestを使用
auth_param digest program /usr/local/libexec/digest_pw_auth /etc/squid/digpass
# 認証プロセスの数を指定します。
auth_param digest children 5
# ダイジェスト認証の「ユーザ名・パスワード画面」に表示する文字
auth_param digest realm Squid proxy-caching web server
# クライアントエージェントの有効性をチェックする時間を指定します
auth_param digest nonce_garbage_interval 5 minutes
# nonce(臨時・その場限り)の有効性のチェックする時間を指定します
auth_param digest nonce_max_duration 30 minutes
# nonceの使用できる回数を指定します。
auth_param digest nonce_max_count 50
# Squidでnonceのカウンターを1づつ進めていきます。
auth_param digest nonce_strictness on
# このディレクティブはoffにセットされたならnonceのカウントチェックを無効
auth_param digest check_nonce_count off
auth_param digest post_workaround off

# 認証を要求
acl password proxy_auth REQUIRED
# 認証を通ったアクセスは許可
http_access allow password
# そのほかのアクセスはすべて拒否する
http_access deny all

設定値はsquid.confのコメントに書いてあったものをほぼコピーしただけです。但し、auth_param digest check_nonce_countはoffにしておかないと、iOSで認証ダイアログが繰り返し表示されてしまいました。原因を特定するのにえらい苦労しました。IDとパスワードは/etc/squid/digpassに平文でID:PASSWORDの形式で列記してあげれば良いです。

それ以外の設定

ヘッダ情報やキャッシュなどの設定を行います。

# ドットなしのホスト名にローカルなドメイン名を付加します。
append_domain .example.com

# squidが受け付けるhttpのポート番号
http_port 1234

## ヘッダー情報の設定
# 内部 IP アドレスが送られないようにする
forwarded_for off
# Proxyの存在を知らせない
header_access X-Forwarded-For deny all
header_access Cache-Control deny all

## キャッシュの設定
# 複数のsquidサーバで、お互いのキャッシュ情報を参照し、効率的に連携させることができる。
# 無効にするには "0"を設定する。
icp_port 0
# IPキャッシュの数
ipcache_size 5120
cache_mem 32 MB
# キャッシュは無効にしてあるので /dev/nullに設定
cache_dir null /dev/null
maximum_object_size 512 KB
maximum_object_size_in_memory 16 KB

## ログの設定
# ストレージ・マネージャーの活動を記録しない
cache_store_log none
# apache風ログで出力
emulate_httpd_log on
logformat common %>a %ui %un [%tl] "%rm %ru HTTP/%rv" %Hs %<st %Ss:%Sh
access_log /var/squid/logs/access.log common
# クライアントごとの統計を無効
client_db off

設定のチェックと起動

最初に設定した記述が正しいかチェックします。エラーメッセージが出なければ問題なしです。

# /usr/local/sbin/squid -k parse
#

設定に問題無ければキャッシュディレクトリを作成します。今回はキャッシュ無しなのでやらなくても問題ないと思うのですが一応… ディレクトリを作成したら起動させます。

# /usr/local/sbin/squid -z
2011/12/16 00:36:03| Creating Swap Directories
# /etc/rc.d/squid start
squid(ok)
# 

起動したら、ブラウザ側にproxyの設定を行い、接続および認証ができるか確認してみます。


blacklistの作成

blacklistは、頻繁に訪れるサイトの不要な画像やjavascript,iframe等のリンクを抽出して/etc/squid/blacklist.txtに正規表現で記述していきます。同様に不要なパスを/etc/squid/blackpath.txtに正規表現で記述します。

/etc/squid/whitelist.txtにはブロックしたくないコンテンツを記述していきます。特に

deny_info http://blackhole.example.com/index.php?url=%s blacklist
deny_info http://blackhole.example.com/index.php?url=%s blackpath

の設定では、"?url"にブラックリストのURLが入ってくるため、このプログラム自体がブラクックリストにマッチしてしまいフィルタリング処理がループしてしまいます。ですので上記で設定したドメインは必ずwhitelist.txtに指定します。

参考の為にブラックリストを晒しておきます。このリストは俺専用にカスタマズされているので、他の人が使用しても全く効果がないかもしれません。

フィルタリング適応前と適応後

フィルタリング適応前と適応後を比べてみます。比較するページがなんで「発言小町」なんだと言う突っ込みは無しの方向で(笑)

まずは適応前で、全体的に五月蠅い感じで、讀賣らしさが出ていますね。

適応前

そして適応後、素のHTML部分が残ってしまているのが悔しいですが、大分すっきりしました。「小町のiAppを入れろよ」と言ってくる、うざい広告のjavascriptもブロックしているのでイライラせずにブラウズする事が出来るようになりました。

適応後

2011年12月14日水曜日

さくらVPSでOpenBSD (postfix imapの設定)

さくらVPSにメールの設定を行います。ポリシーとしては下記の項目を設定してみます。

  • MTAはpostfiを使用
  • imapはcourier-imapを使用
  • メール送信にはsmtp認証を行う
  • smtp認証 imap認証にはauthdaemondを使用
  • smtp(STARTTLS)
  • Submission(STARTTLS)
  • smtps(SSL)
  • imaps(SSL)

postfix courier-authlib courier-imapをインストール

portsを使ってさくっとインストール。

インストール

# cd /usr/ports/mail/postfix/stable
# env FLAVOR="sasl2" make install
# cd /usr/ports/mail/courier-authlib
# env FLAVOR="no_ldap no_mysql no_pgsql" make install
# pkg_add /usr/ports/packages/amd64/all/courier-authlib-userdb-0.63.0p3.tgz
# cd /usr/ports/mail/courier-imap
# env FLAVOR="no_trashquota" make install
#

/etc/rc.conf.localの編集

/etc/rc.conf.localに下記の設定を追加

sendmail_flags=NO
syslogd_flags="-a /var/spool/postfix/dev/log"
postfix_flags=""
saslauthd_flags=NO
courier_authdaemond_flags=""
courier_imap_flags=NO
courier_imap_ssl_flags=""
pkg_scripts="postfix saslauthd courier_authdaemond courier_imap courier_imap_ssl"


postfixの一般的な設定

/etc/postfix/main.cfを編集して、メールの送受信テスト用に一般的な設定を行います。

/etc/postfix/main.cfの編集

myhostname  = foo.example.org
mydomain    = example.org
myorigin    = $mydomain

inet_interfaces = all
inet_protocols  = ipv4

mydestination    = $myhostname, localhost.$mydomain, $mydomain
mynetworks_style = host

alias_maps = hash:/etc/mail/aliases
alias_database = hash:/etc/mail/aliases

# postfixのversionは非表示
smtpd_banner = $myhostname ESMTP $mail_name
# 受信メールはMaildir形式で格納
home_mailbox = Maildir/

## for Blockking
##
# HELO または EHLO コマンドを要求
smtpd_helo_required = yes
# VRFYやEXPNコマンドを無効(お好みで有効に)
#disable_vrfy_command = yes
#RFC821違反のFROM:やRCPT TO:を拒否(お好みで有効に)
#strict_rfc821_envelopes = yes

# SMTPサーバがクライアントからSMTP接続の要求を受けた際に適用する制限
smtpd_client_restrictions =
	 permit_mynetworks,
	 # 逆引出来ないIPは拒否
	 reject_unknown_client,
	 # reject_listで定義されているものは拒否
	 check_client_access hash:/etc/postfix/reject_list, 
	 permit

# Fromによる制限
smtpd_sender_restrictions =
        # 送信者のアドレスのドメインにAレコードまたはMXレコードがないとき拒否
	 reject_unknown_sender_domain,
	 #アドレスがFQDNでなければ拒否
	 reject_non_fqdn_sender,
	 # sender_accessはで定義されているものは拒否
	 check_sender_access hash:/etc/postfix/sender_access
# アドレス検証状態の格納場所
address_verify_map = btree:/etc/postfix/verify


Maildirディレクトリを作成

自分のhomeディレクトリにMaildirを作成します。courier-imapがインストールされていれば、/usr/local/bin/にmaildirmakeコマンドがあると思いますのでこれを使います。

# su UserName -c '/usr/local/bin/maildirmake  /home/UserName/Maildir'
#

useraddコマンド実行時にMaildirが作成されるように/etc/skel/Maildirにも作成します。

# /usr/local/bin/maildirmake /etc/skel/Maildir
#

postfixを立ち上げます

# /etc/rc.d/postfix start
#

送受信と不正中継のチェック

送信と受信を行ってみて、正常に動作しているか確認します。受信の場合は正常に受信出来ていれば、/home/UserName/Maildir/newの下にファイルが出来ているはずです。

不正中継のチェックは第三者中継チェックなどを使えば良いでしょう。

authdaemondの設定


/usr/local/lib/sasl2にsmtpd.confを作成

smtpd.confはデフォルトでは存在しないので、新規作成して下記の設定をします。

pwcheck_method: authdaemond
authdaemond_path: /var/run/courier-auth/socket
mech_list: plain login

authdaemondにパスワードを登録

ユーザ情報を登録
# /usr/local/sbin/userdb UserName set home=/home/UserName mail=/home/UserName/Maildir uid=`id -u UserName` gid=`id -g UserName`
smtp認証時のパスワード
# /usr/local/sbin/userdbpw | userdb UserName set smtppw
Password: 
Reenter password:
imap認証時のパスワード(平文)
# /usr/local/sbin/userdbpw | userdb UserName set imappw
Password: 
Reenter password:

データベース作成
# /usr/local/sbin/makeuserdb

これで/etc/courier/以下に userdb userdb.dat userdbshadow.dat が作成されます。

/etc/courier/authdaemonrcを編集

メモリーがもったいないので立ち上がるプロセスを減らします。/etc/courier/authdaemonrcを開いて下記のように変更します。

# You may need to increase daemons if as your system load increases.  Symptoms
# include sporadic authentication failures.  If you start getting
# authentication failures, increase daemons.  However, the default of 5
# SHOULD be sufficient.  Bumping up daemon count is only a short-term
# solution.  The permanent solution is to add more resources: RAM, faster
# disks, faster CPUs...

#daemons=5
daemons=2

/etc/rc.d/courier_authdaemondを編集

OpenBSDのpostfixはchrootして動作しているので、/var/spool/postfixより上のディレクトリのファイルはアクセスは出来ません。しかしauthdaemondで認証をするためには、/var/run/courier-auth/socketにアクセスしなければならず、このままだと認証が失敗します。

これを回避するために、/var/spool/postfix/var/run/courier-auth/socket に /var/run/courier-auth/socketをハードリンクを作成して(シンボリックリンクでは認証NGになってしまいました)、postfixからもcourier-authのsocketをアクセス可能にします。

このハードリンクを作成する処理を /etc/rc.d/courier_authdaemondに追加します

rc_start() {
        mkdir -p /var/run/courier{,-auth}/
        ${rcexec} "${daemon} start"
        if [ -x /var/run/courier-auth/socket ]; then
                ln /var/run/courier-auth/socket /var/spool/postfix/var/run/courier-auth/socket
        fi
}

rc_stop() {
        ${daemon} stop
        if [ -x /var/spool/postfix/var/run/courier-auth/socket ]; then
                rm /var/spool/postfix/var/run/courier-auth/socket
        fi
}

SSLサーバ証明書の作成


サーバー秘密鍵の作成 (server.key)

# cd /etc/ssl/private/
# openssl genrsa  -out server.key -aes256 2048
Generating RSA private key, 2048 bit long modulus
.......................+++
..................................................................................................................................+++
e is 65537 (0x10001)
Enter pass phrase for server.key:   パスフレーズを入力します。
Verifying - Enter pass phrase for server.key:  パスフレーズを再度入力します。
#

パスフレーズを削除

# openssl rsa -in server.key -out server.key 
Enter pass phrase for server.key:  パスフレーズを入力します。
writing RSA key
#

証明書要求の作成(server.csr)

# openssl req -new -key server.key -out server.csr
Enter pass phrase for server.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) []:Sakura
Organization Name (eg, company) []:Example Com
Organizational Unit Name (eg, section) []:foo
Common Name (eg, fully qualified host name) []:foo.example.com
Email Address []:postmaster@example.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
#

自己署名の証明書の作成(server.crt)

個人使用のサーバーなので、ca署名でなく自己署名の証明書を作成します。そして、imap用の証明書imapd.pemとpostfix用の証明書postfix.pemを作成します。

# openssl x509 -in server.csr -out server.crt -req -signkey server.key -days 3650
Signature ok
subject=/C=JP/ST=Tokyo/L=Sakura/O=Example Com/OU=foo/CN=foo.example.com/emailAddress=postmaster@example.com
Getting Private key
# (cat server.crt ; cat server.key) > imapd.pem
# chmod 400 imapd.pem
# chown _courier imapd.pem
# (cat server.crt ; cat server.key) > postfix.pem
# chmod 400 postfix.pem
# chown _postfix postfix.pem
#
# ls -al
drwx------  2 root      wheel   512 Dec 10 16:11 .
drwxr-xr-x  4 root      wheel   512 Dec  3 17:10 ..
-rw-------  1 _courier  wheel  3021 Dec 10 15:51 imapd.pem
-rw-------  1 _postfix  wheel  3021 Dec 10 16:11 postfix.pem
-rw-------  1 root      wheel  1346 Dec 10 15:48 server.crt
-rw-------  1 root      wheel  1074 Dec 10 15:47 server.csr
-rw-------  1 root      wheel  1675 Dec 10 14:17 server.key
#

postfixの認証用の設定を追加

/etc/postfix/main.cfを編集して、postfixの認証用の設定を追加します。

/etc/postfix/main.cfの編集

## for Auth
##
# SASLによるSMTP認証を使用
smtpd_sasl_auth_enable = yes
# メールの配送や中継の制限を設定
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated,reject_unauth_destination
smtpd_sasl_local_domain = 
# noanonymous : 匿名での接続を拒否。
smtpd_sasl_security_options=noanonymous

## for SMPT over SSL
##
# STARTTLSサポートを案内するが、クライアントがTLS暗号化を使うことを強制はしない
mtpd_tls_security_level = may
# tlsのログレベル
smtpd_tls_loglevel = 1 
# 証明書の場所
smtpd_tls_cert_file = /etc/ssl/private/postfix.pem
smtpd_tls_key_file =  /etc/ssl/private/postfix.pem
tls_random_source = dev:/dev/urandom


/etc/postfix/master.cfを編集

/etc/postfix/master.cfを編集して、submission(port 587)とsmtpsを有効にします。smtpsがあるのでsubmissionは不要な気もするが一応設定しておきます。

設定前
#submission inet n       -       -       -       -       smtpd
#  -o smtpd_tls_security_level=encrypt
#  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING

設定後
submission inet n       -       -       -       -       smtpd
  -o smtpd_tls_security_level=may
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING

設定前
#smtps     inet  n       -       -       -       -       smtpd
#  -o smtpd_tls_wrappermode=yes
#  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING

smtps     inet  n       -       -       -       -       smtpd
    #smtpd_tls_wrappermode=yes を有効にしないとthunderbirdのsmtpsが動かなくてはまった
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING


接続・認証テスト


authdaemond imaps postfixの起動

テストの前にauthdaemond imapsを起動します。postfixは設定が変わったので再起動させます。

# /etc/rc.d/courier_authdaemond start
courier_authdaemond(ok)
# /etc/rc.d/courier_imap_ssl start
courier_imap_ssl(ok)
# /etc/rc.d/postfix restart
postfix(ok)
postfix(ok)
#

認証用データの作成

認証データはperlを使って簡単に作成できます。

perl -MMIME::Base64 -e 'print encode_base64("username\@domain\0username\@domain\0password");'

例えば、ユーザー名が"FOOBAR"でパスワードが"HOGEHOGE"の場合は、次のようにして作成します。

# perl -MMIME::Base64 -e 'print encode_base64("FOOBAR\0FOOBAR\0HOGEHOGE");'
Rk9PQkFSAEZPT0JBUgBIT0dFSE9HRQ==
#

作成したデータを確認したい場合は次のようにします。

# echo "Rk9PQkFSAEZPT0JBUgBIT0dFSE9HRQ==" | nkf -mB | perl -pe 's/\0/\n/g'
FOOBAR
FOOBAR
HOGEHOGE
#

smtp(port 25)への接続

最初は暗号化されていない(非STARTTLS)接続で通信してみます。

# telnet localhost smtp
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 foo.example.org ESMTP Postfix
EHLO localhost
250-mail.example.org
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
auth plain Rk9PQkFSAEZPT0JBUgBIT0dFSE9HRQ==
235 2.7.0 Authentication successful
quit
221 2.0.0 Bye
Connection closed by foreign host.
#

次は暗号化された(STARTTLS)接続で通信してみます。

# openssl s_client -crlf -starttls smtp -connect localhost:smtp
CONNECTED(00000003)
depth=0 C = JP, ST = Tokyo, L = Sakura, O = Example Com, OU = foo, CN = foo.example.com, emailAddress = postmaster@example.com
verify error:num=18:self signed certificate
verify return:1

---- 色々出力されるので略 ----

250 DSN
EHLO localhost
250-foo.example.org
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
auth plain Rk9PQkFSAEZPT0JBUgBIT0dFSE9HRQ==
235 2.7.0 Authentication successful
quit
221 2.0.0 Bye
closed
#

submission(port 587)への接続

smtpの時と同じように、非STARTTLSとSTARTTLSで接続してみます。

# telnet localhost submission
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 foo.example.org ESMTP Postfix

---- 色々出力されるので略 ----

250-8BITMIME
250 DSN
auth plain Rk9PQkFSAEZPT0JBUgBIT0dFSE9HRQ==
235 2.7.0 Authentication successful
quit
221 2.0.0 Bye
Connection closed by foreign host.
#
# openssl s_client -crlf -starttls smtp -connect localhost:submission
CONNECTED(00000003)
depth=0 C = JP, ST = Tokyo, L = Sakura, O = Example Com, OU = foo, CN = foo.example.com, emailAddress = postmaster@example.com

---- 色々出力されるので略 ----

250-8BITMIME
250 DSN
auth plain Rk9PQkFSAEZPT0JBUgBIT0dFSE9HRQ==
235 2.7.0 Authentication successful
quit
221 2.0.0 Bye
closed
#

smtps(port 465)への接続

smtpsの場合は最初からSSL通信するので、コマンドオプションが少し違います。

# openssl s_client -connect localhost:smtps
CONNECTED(00000003)
depth=0 C = JP, ST = Tokyo, L = Sakura, O = Example Com, OU = foo, CN = foo.example.com, emailAddress = postmaster@example.com

---- 色々出力されるので略 ----

250-8BITMIME
250 DSN
auth plain Rk9PQkFSAEZPT0JBUgBIT0dFSE9HRQ==
235 2.7.0 Authentication successful
quit
221 2.0.0 Bye
closed
#

imaps(port 465)への接続

smtpsの場合は最初からSSL通信するので、コマンドオプションが少し違います。

# openssl s_client -connect localhost:imaps
CONNECTED(00000003)
depth=0 C = JP, ST = Tokyo, L = Sakura, O = Example Com, OU = foo, CN = foo.example.com, emailAddress = postmaster@example.com

---- 色々出力されるので略 ----

* OK [CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE AUTH=PLAIN ACL ACL2=UNION] Courier-IMAP ready. Copyright 1998-2011 Double Precision, Inc.  See COPYING for distribution information.
0000 CAPABILITY
* CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE AUTH=PLAIN ACL ACL2=UNION
0000 OK CAPABILITY completed
0001 LOGIN "FOOBAR" "HOGEHOGE"
0001 OK LOGIN Ok.
0002 logout
* BYE Courier-IMAP server shutting down
0002 OK LOGOUT completed
closed
#

これでサーバーの設定は終了しました。

2011年12月6日火曜日

さくらVPSでOpenBSD (pfの設定)

さくらVPSにOpenBSDをインストールした訳だが、最初にフィルターリングの設定を行います。/etc/pf.confを下記のように設定しました。

########## Macro define
#ネットワークインターフェースの定義
ext_if="em0"

# 中継しないIPのテーブル
table <unroutable> const {127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 255.255.255.255/32}
# マルチキャストIPのテーブル
table <multicast>  const {224.0.0.1/32, 224.0.0.2/32}

# 許可するサービスの定義
services_udp="{ domain }"
services_tcp="{ ssh, smtp, domain, www, auth, imap, submission, smtps, imaps }"
icmp_types = "echoreq"

######## option
# ブロック時のポリシーは
# ブロックしたTCP パケットにTCP RST を返す
# ブロックしたUDP パケットに ICMP UNREACHABLEを返す
set block-policy return

########## normalize all packets
# パケットの正規化
match in all scrub (no-df)

########## Filtering rules
# 全てのパケットをブロック
block in log all
block out all 

# ループバックインタフェースはフィルター対象外
set  skip  on lo0

# 詐称されたパケットはブロック
antispoof quick for { lo0, $ext_if }

# URPFチェックに失敗するパケットはブロック
block in quick from urpf-failed

# 中継しないIPはブロック
block drop in  log quick on $ext_if from { <unroutable> <multicast> } to any
block drop out log quick on $ext_if from any to { <unroutable> <multicast> }

# 外向けパケット
pass out on $ext_if inet proto icmp all icmp-type 8 code 0 keep state
pass out on $ext_if proto tcp all modulate state flags S/SA
pass out on $ext_if proto udp all keep state

# 内向きパケット
pass in inet proto icmp all icmp-type $icmp_types keep state
pass in on $ext_if inet proto tcp from any to ($ext_if) port $services_tcp flags S/SA keep state
pass in on $ext_if inet proto udp from any to ($ext_if) port $services_udp keep state

pass in quick on $ext_if inet proto tcp from any to ($ext_if) port ssh flags S/SA synproxy state
pass in quick on $ext_if inet proto tcp from any to ($ext_if) port smtp flags S/SA synproxy state
pass in quick on $ext_if inet proto tcp from any to ($ext_if) port www flags S/SA synproxy state

設定したら、記述が正しいかチェックして、OKならばロードして終わり。

# pfctl -nf /etc/pf.conf   設定チェック
# pfctl -f  /etc/pf.conf   設定をロード

さくらVPSはコンソールからログイン出来るので、フィルタリングの設定に失敗してログイン出来なくなっても、コンソールから修正が出来るので安心ですね。

ついでに、SSHのブルートフォース攻撃が五月蠅いので/etc/hosts.denyと/etc/hosts.allowも設定しておく。

/etc/hosts.deny

sshd: ALL

/etc/hosts.allow

sshd : 127.0.0.1
sshd : .jp

取りあえず、jpドメイン以外からの攻撃は防御出来る。

2011年12月5日月曜日

さくらのVPSを契約したのでOpenBSDを入れてみた

現在使用しているサーバは自由度が低いので、もっと自由に弄くれる外部サーバーが欲しくなり、さくらのVPSを契約してみました。

OSはBSDがいいな。FreeBSDは再インストールメニューに出ているので簡単に変更出来そう。でも、FreeBSD3.x以降は使っていないのでちょっと不安。現在自宅で使っているのはNetBSDだけど、さくらのVPSではNetBSDは動かないぽい。

OpenBSDはどうよ?と検索してみると さくらのVPSにOpenBSDをインストールしてみた と言うサイトが見つかった。インストール手順を見た限りでは、結構簡単にインストールできそうだし、OpenBSDは4.3ぐらいまでは使っていたので、OpenBSDしかない!(キリッ と言うことでインストールしてみました。

リンク先に書いてある手順に従えば問題無くインストール出来るので書くことは殆どないのですが、違いといえばバージョンがOpenBSD5.0とパーティションが違う事ぐらいです。

パーティション構成は下記のように、"/usr/src" "/usr/port" "/usr/X11R6" を /usr パーティションにまとめ、大きめに領域をとりました。HDDの容量が20GBしかないので結構悩んだ。

# disklabel -E /dev/rwd0c
Label editor (enter '?' for help at any prompt)
> p m
OpenBSD area: 64-41942880; size: 20479.9M; free: 0.0M
#                size           offset  fstype [fsize bsize  cpg]
  a:           500.0M               64  4.2BSD   2048 16384    1 # /
  b:           800.3M          1024128    swap                   # none
  c:         20480.0M                0  unused                   
  d:          1024.2M          2663136  4.2BSD   2048 16384    1 # /tmp
  e:          4096.0M          4760768  4.2BSD   2048 16384    1 # /var
  f:          4607.9M         13149344  4.2BSD   2048 16384    1 # /usr
  g:          5119.7M         22586240  4.2BSD   2048 16384    1 # /home
  h:          4331.8M         33071456  4.2BSD   2048 16384    1 # /usr/local
> 

インストールが終了したら、src.tar.gz syssrc.tar.gz ports.tar.gzします。展開し終わったら、portsは最新版に更新します。

# cd /usr/ports
# cvs -d anoncvs@anoncvs.jp.openbsd.org:/cvs update -Pd
#

portsを最新版にしたら、依存関係のチェックがうまく働くなりコンパイルエラーになってしまったので、/usr/src/share/mkとpkg_addを最新版にしてみる。

# cd /usr/src/share/mk
# cvs -d anoncvs@anoncvs.jp.openbsd.org:/cvs update -Pd
# make install
# cd /usr/src/usr.sbin/pkg_add/
# cvs -d anoncvs@anoncvs.jp.openbsd.org:/cvs update -Pd
# make ; make install
#

再度コンパイルしてみると、正常にコンパイルできました。mercurial postgrsql mysql postfixなど、幾つかインストールした後のディスクの状態は下記の通りです。

# df -k
Filesystem  1K-blocks      Used     Avail Capacity  Mounted on
/dev/wd0a      501854     43384    433378     9%    /
/dev/wd0g     5157310     47372   4852074     1%    /home
/dev/wd0d     1029118        12    977652     0%    /tmp
/dev/wd0f     4642990   2003500   2407342    45%    /usr
/dev/wd0h     4363534    252150   3893208     6%    /usr/local
/dev/wd0e     4125390     64112   3855010     2%    /var

/dev/wd0fにportディレクトリがあるので、コンパイル途中にディスクが溢れるないか心配でしたが、こまめに "make clean=depends;make clean=dist"すれば問題なさげ。

ちょっとはまった所

その1。/etc/rc.conf.localに下記のように書いたのだけれども、指定したデーモンがが立ち上がらなくて悩んだ

sendmail_flags=NO
syslogd_flags="-a /var/spool/postfix/dev/log"
postfix_flags=NO
mysqld_flags=""

正解は、次のように書かないと駄目みたい(5.0からか?)

sendmail_flags=NO
syslogd_flags="-a /var/spool/postfix/dev/log"
postfix_flags=NO
mysqld_flags=""

pkg_scripts="postfix mysqld"

その2。topを表示させたらcpuが1つしか表示されていなかった、よく考えてみるとカーネルがシングルプロセッサ用だったので、マルチプロセッサ用のカーネルを取ってきてリブートで認識された。

# cd /
# wget ftp://ftp.jaist.ac.jp/pub/OpenBSD/5.0/amd64/bsd.mp
# mv bsd bsd.sp
# mv bsd.mp bsd
# sync;sync;sync;
# reboot
#

2011年11月30日水曜日

Bose SoundLink Wireless Mobile speaker を買おうと悩んでいたらApple TVを買っていた

BoseのSoundLink Wireless Mobile speakerが日本でも発売されると聞いて物欲指数上昇中でした。ipadではTuneIn Radio Proを、MacではRadiumを使ってjazz系のラジオを聴いているのですが、やはり内蔵のスピーカーではもの足らないので、ある程度音がよいスピーカーで聴きたいと思ったからです。このスピーカーはbluetooth対応なので実機のそばにスピーカを置かずに使えるので邪魔にならないと言うのも物欲指数上昇ポイントのひとつです。

SoundLink Wireless Mobile speaker

アメリカでの価格は$299、それに対して日本での価格は36,750円。1ドル70円代後半の時代にこの価格は高すぎるだろうと、個人輸入出来るショップを探してみるとSMARTHOMEと言うサイトが日本へ配送可能らしい。送料は$37.98で商品とあわせて$336.98となり1ドル=80円としても27,000円程度で買えることになる。

危うくポチりそうになったのだけれども結構高額なので、冷静になって既に持っているアンプとスピーカーを有効活用できないものかと調べてみました。すると"Apple TV"や"AirMac Express"を使えばairplayを使用して無線・有線経由で音声データを送れる事が出来るらしい。これだと1万円程度でワイヤレスなオーディオ環境を構築できるので、こちらに急遽変更することにしました。

airplay対応の機種は少ないながら幾つか出ていますが、サードパティ製のairplayのアンプやスピーカーなどは高いので却下w 一番安価な"Apple TV"か"AirMac Express"を選ぶことにします。

"AirMac Express"は無線ルータですが、付属機能としてairplayが使えるようです。アナログ出力もあるのでアナログアンプと接続も直接できます。しかし、無線ルータは既に持っている。発売時期が2008年と古いので、新しい製品が出ると悔しい思いをしそうな気がします。なにより、ネット上で評判をみると熱がこもりやすいので故障しやすいとの事なので、汎用性の高そうな(動画も見れるし)Apple TVの方が良さそうです。

AirMac Express

"Apple TV"の場合、出力がオプティカルのみでアナログアンプに接続するには、デジタル→アナログ変換するDCコンバータを別途買う必要があります。

Apple TV

ネット上で調べてみると同じ事を考える人がいるようで、"Apple TV"にDCコンバータをかましてアナログアンプに接続している方々がおられました。その中で評判が良かった ハイパーツールズ デジタル→アナログ音声変換器 DCT-3を選択してみます。

DCT-3

買うものは決まったので、最安値を検索して…と言っても"Apple TV"は値引きしている所がほとんどありません。2〜3日グダグダと安いところは無いかと探していると、なんとamazonのマーケットプレスで中古-新品同様のApple Tvが7,147円で出されています。出品者はwarehouse_deals_jp。なんか怪しそうだと思いつつ検索をかけてみると、アマゾンが商品を中古販売する時に使うIDらしい事がわかったので即注文w 同時にハイパーツールズのDCT-3と同等品と思われるランサーリンク DCT-3が安かったのでこちらも注文。合計して送料込みで11,127円と比較的安く買えました。

注文合計

届いたApple TVは箱の角が多少凹んでいる程度の未開封新品でしたので、お買い得だったと思います。

届いたApple TV

早速開封し、接続して使っています。そのうち感想でも書こうと思います。

開封したApple TV

2011年11月26日土曜日

回転させると機能が切り替わる多機能時計Löttorpを買って見た。

久々にIKEAに行ったら、面白そうなガジェットが安く売られていたので買ってみた。これです!

Löttorp

このLöttorpは、4辺に各機能を表すピクトグラムが描いてあり、上に来たピクトグラムの機能が有効になります。時計・温度計・アラーム・タイマー機能がありますが、 ピクトグラムわかりづらくないかい? 時計とアラームの区別がぱっと見てわからないのですけどw ひとつ349円なのでその辺は突っ込んではいけないのかもしれない。

回転させると、機能ごとに発行する色も変わってオシャレ。まずは時計。

時計

温度計

温度計

アラーム

アラーム

最後にタイマー

タイマー

自分はキッチンに置いてキッチンタイマーとして使っています。単四電池二本で駆動します。

2011年11月21日月曜日

MacPorts2.0で Binary Archivesを使用してコンパイルしないでインストール

以前にportarchivemodeが廃止されたので、コンパイルされたパッケージからコンパイルレスでインストール出来なくなったと書いたのですが、マニュアルを読んでみると'binary-only mode'と言うオプションがあり、「これを指定するとbinary archivesからインストールするよ。」との記述があったので試してみたら簡単にできましたので方法を書いておきます。

最初に、母艦側で必要なパッケージをコンパイルしておくのが大前提です。母艦側でportのコンパイルが終わると/opt/local/var/macports/software/ の下にbinary archives(デフォルトだと拡張子がtbz2のファイル群)が出来ていると思います。これをtarなどで一つのファイルにまとめておきます。

#母艦側
$ cd /opt/local/var/macports/
$ tar cvf ~/software.tar software
$

母艦側でまとめたファイルをサブ機にコピーして、/opt/local/var/macports/に展開します。

#サブ機側
$ cd /opt/local/var/macports/
$ sudo tar xvfp ~/software.tar
$

展開が終了したら、bオプション(binary-only mode)をつけてインストールします。

#サブ機側
$ sudo port -b install lv +lesslikeslash
--->  Computing dependencies for lv
--->  Dependencies to be installed: ncurses xz gettext expat libiconv
--->  Fetching archive for ncurses
--->  Installing ncurses @5.9_1
--->  Activating ncurses @5.9_1
--->  Cleaning ncurses
--->  Fetching archive for expat
--->  Installing expat @2.0.1_1
--->  Activating expat @2.0.1_1
--->  Cleaning expat
--->  Fetching archive for libiconv
--->  Installing libiconv @1.14_0
--->  Activating libiconv @1.14_0
--->  Cleaning libiconv
--->  Fetching archive for gettext
--->  Installing gettext @0.18.1.1_2
--->  Activating gettext @0.18.1.1_2
--->  Cleaning gettext
--->  Fetching archive for xz
--->  Installing xz @5.0.3_0
--->  Activating xz @5.0.3_0
--->  Cleaning xz
--->  Fetching archive for lv
--->  Installing lv @4.51_3+lesslikeslash+xz
--->  Activating lv @4.51_3+lesslikeslash+xz
--->  Cleaning lv
$

同様に他のパッケージもインストールします。

2011年10月27日木曜日

Emacs nxml-modeの設定

最近、スマフォ関係でhtml5で書くことが多くなってきました。今まで使用していたpsgml-modeはhtml5と相性が悪く、インデントやタグの補完がうまく動かないので、nxml-modeに変更してみることにしました。

nxml-modeはCarbon Emacsやemacs23以降には標準搭載されているので、インストールは特に不要ですが、別途hober/html5-elをインストールする必要があります。

nxml-modeの設定

最初にnxml-modeの設定を行って、正常に動作するかチェックします。下記のように設定しました。

(setq auto-mode-alist
      (append '(
                ;;("\\.\\(html\\|xhtml\\|shtml\\|tpl\\)\\'" . xml-mode)
                ("\\.\\(html\\|xhtml\\|shtml\\|tpl\\)\\'" . nxml-mode)
                ("\\.php\\'" . php-mode)
                )
              auto-mode-alist))

(load "rng-auto.el" 't)
(add-hook 'nxml-mode-hook
          (lambda ()
            ;; 更新タイムスタンプの自動挿入
            (setq time-stamp-line-limit 10000)
            (if (not (memq 'time-stamp write-file-hooks))
                (setq write-file-hooks
                      (cons 'time-stamp write-file-hooks)))
            (setq time-stamp-format "%3a %3b %02d %02H:%02M:%02S %:y %Z")
            (setq time-stamp-start "Last modified:[ \t]")
            (setq time-stamp-end "$")
            ;;
            (setq auto-fill-mode -1)
            (setq nxml-slash-auto-complete-flag t)      ; スラッシュの入力で終了タグを自動補完
            (setq nxml-child-indent 2)                  ; タグのインデント幅
            (setq nxml-attribute-indent 4)              ; 属性のインデント幅
            (setq indent-tabs-mode t)
            (setq nxml-bind-meta-tab-to-complete-flag t) 
            (setq nxml-slash-auto-complete-flag t)      ; </の入力で閉じタグを補完する
            (setq nxml-sexp-element-flag t)             ; C-M-kで下位を含む要素全体をkillする
            (setq nxml-char-ref-display-glyph-flag nil) ; グリフは非表示
            (setq tab-width 4)))

custom-set-faces
 '(nxml-comment-content-face
   ((t (:foreground "red"))))                            ; コメント
 '(nxml-comment-delimiter-face
   ((t (:foreground "red"))))                            ; <!-- -->
 '(nxml-delimited-data-face
   ((t (:foreground "DarkViolet"))))                     ; 属性値やDTD引数値など
 '(nxml-delimiter-face
   ((t (:foreground "blue"))))                           ; <> <? ?> ""
 '(nxml-element-local-name-face
   ((t (:inherit nxml-name-face :foreground "blue"))))   ; 要素名
 '(nxml-name-face
   ((t (:foreground "dark green"))))                     ; 属性名など
 '(nxml-element-colon-face
   ((t (:foreground "LightSteelBlue"))))                 ; :(xsl:paramなど)
 '(nxml-ref-face
   ((t (:foreground "DarkGoldenrod"))))                  ; &lt;など
 '(nxml-tag-slash-face
   ((t (:inherit nxml-name-face :foreground "blue")))))  ; /(終了タグ)

設定後htmlファイルを開くと、モードラインにnXMLと表示されます。そしてHTML構文に誤りが無ければValidと表示されます。

nxml-mode

また、"C-c C-s C-w"で現在どのスキーマを使用しているか表示してみると'/Applications/Emacs.app/Contents/Resources/site-lisp/nxml-mode/schema/xhtml.rnc'が使われているのがわかります。

hober/html5-elのインストール

次にDownloads for hober's html5-elのページからファイルをダウンロードして適当なディレクトリに展開します。

$ cd ~/.elisp
$ tarxvfz ~/hober-html5-el-934944b.tar.gz
$ cd html5-el
$ make relaxng
$ make webapps
$ 

インストールが完了したら、README.markdownに従って設定を行います。

(add-to-list 'load-path "~/.elisp/html5-el/")
(eval-after-load "rng-loc"
   '(add-to-list 'rng-schema-locating-files "~/.elisp/html5-el/schemas.xml"))
(require 'whattf-dt)

設定後、同じファイルを開いて使用されてるスキーマを調べると'~/.elisp/html5-el/relaxng/xhtml5.rnc'となりhtml5(xhtml5?)対応になります。

nxml-mode html5

上記の場合、xhtml1をxhtml5として解釈しているため、Invalidとなってしまっています。こういうときは"C-c C-s C-t"と打って明示的にDocument Typeを指定する事が出来ます。指定したDocument Typeはrng-schema-locating-filesに保存されるので、次回からは指定しなくてもセットされます。

Document Type

rng-schema-locating-filesを修正

まだ、xhtmlで書くことの方が多いから、デフォルトはxhtmlでhtml5を編集する場合は"C-c C-s C-t"で明示的に指定したいと言うときは、rng-schema-locating-filesに定義したファイルを修正すれば出来ると思います。rng-schema-locating-filesはhober/html5-elをインストールしたときに"~/.elisp/html5-el/schemas.xml"に設定しました。

(eval-after-load "rng-loc"
   '(add-to-list 'rng-schema-locating-files "~/.elisp/html5-el/schemas.xml"))

このファイルの中身をみると下記のように記述されています。

<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
  <uri pattern="*.html" typeId="XHTML5"/>
  <uri pattern="*.xhtml" typeId="XHTML5"/>
  <namespace ns="http://www.w3.org/1999/xhtml" typeId="XHTML5"/>
  <documentElement localName="html" typeId="XHTML5"/>
  <typeId id="XHTML5" uri="relaxng/xhtml5.rnc"/>
</locatingRules>

これを次のように記述すれば良いと思います。

<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
  <uri pattern="*.html" typeId="XHTML"/>
  <uri pattern="*.xhtml" typeId="XHTML"/>
  <namespace ns="http://www.w3.org/1999/xhtml" typeId="XHTML5"/>
  <documentElement localName="html" typeId="XHTML5"/>
  <typeId id="XHTML5" uri="relaxng/xhtml5.rnc"/>
</locatingRules>

使い方

最初使い方がわからなかったのですが、youtubeにチュートリアルな動画がありましたので、それを見て大体の使い方は理解出来ました。



主なキーアサイン

主なキーアサインをまとめておきました。

編集系のキーアサイン
キー 関数 機能
C-c C-x nxml-insert-xml-declaration xml宣言文を挿入
C-return nxml-complete タグ・属性の補完
/ nxml-electric-slash 直前の「開始タグ」に対応する「終了タグ」で補完する
C-c tab nxml-balanced-close-start-tag-inline 直前の「開始タグ」に対応する「終了タグ」を同じ行に挿入する
C-c C-b nxml-balanced-close-start-tag-block 直前の「開始タグ」に対応する「終了タグ」を改行して挿入する
C-c C-u nxml-insert-named-char HTML Character Entityを挿入する
C-c C-d nxml-dynamic-markup-word 選択文字列をカレントバッファから探し、同じタグで補完する
移動系のキーアサイン
キー 関数 機能
ESC h nxml-mark-paragraph 現在の段落を選択する
ESC } nxml-forward-paragraph 上の段落に移動する
ESC { nxml-backward-paragraph 下の段落に移動する
ESC C-p nxml-backward-element 1要素後ろに移動する
ESC C-n nxml-forward-element 1要素前に移動する
ESC C-d nxml-down-element 下の階層の要素に移動する。(下の階層があれば)
ESC C-u nxml-backward-up-element 上の階層の要素に移動する。(上の階層があれば)
検証系のキーアサイン
キー 関数 機能
C-c C-v rng-validate-mode 検証モードの切り替え
C-c C-n rng-next-error エラーが発生した箇所に移動する
C-c C-s C-w rng-what-schema 現在どのスキーマを使用しているか表示する
C-c C-s C-t rng-set-document-type-and-validate 現在開いている文章のDocument Typeをセットし検証を行う
セットしたDocument Typeはスキーマファイルに保存される
C-c C-s C-f rng-set-schema-file-and-validate 指定したスキーマファイルを読込み検証を行う
C-c C-s C-a rng-auto-set-schema-and-validate 現在開いている文章に最適なスキーマを読込み検証を行う
C-c C-s C-l rng-save-schema-location 現在使用しているスキーマファイルを保存する

2011年10月24日月曜日

MacPorts2.0 Xcode4.2でpostgreSQLがSegmentation Fault 11が起こり悶絶

先日、メインの開発マシンであるMac miniにLionをクリーンインストールしました。周辺ツールも、Xcode4.2・MacPorts2.0の最新版をインストールして、開発環境も順調に作成していました。

よく使うportsはコンパイルまでに正常に終わり、あとはDatabaseへデータのリストアをすれば完了だなと思っていたら、postgreSQLがデータのリストア時にSegmentation Fault 11で落ちてしまいます。やばい、これが動かないと仕事が出来ない。

...
Segmentation Fault 11
$

ちょっと焦りましたが、こういう時はgoogle先生に聞くのが一番です。ググってみるとMacPortsのバグトラッキングのページに「postgresql91 segfaults on OS X 10.7 when built with Xcode 4.2」と言う、今の状況そのまんまなバグ報告が見つかりました。

このバグ報告に付いているコメントをみると、「Xcode 4.2ではコンパイル時に/Developer/usr/bin/clangがデフォルトで使われるが、これが悪さをしているようなので/Developer/usr/bin/llvm-gcc-4.2を使った方が良い。」と書かれていたので、llvm-gcc-4.2を使ってコンパイルしてみます。

clangとはコンパイラのフロントエンドであり、llvmをバックエンドとして使用されるものらしいです。Xcode4になって、コンパイラがgccからllvmに移行したらしいので、他のポートでも色々不具合が出ているようです。

コンパイラをllvm-gcc-4.2に変更する方法は2つ有り、/opt/local/var/macports/sources/rsync.macports.org/release/tarballs/ports/databases/postgresql90/Portfileを変更する方法と、コマンドラインからコンパイラを指定する方法があります。Portfileを変更するより、コマンドラインから指定した方がお手軽なので、今回はコマンドラインで作業をしてみます。

コンパイラを変更するには下記のコマンドを実行します

$ sudo port -d install postgresql90 configure.compiler=llvm-gcc-4.2

configure.compilerには/opt/local/share/macports/Tcl/port1.0/portconfigure.tclに定義されている下記の文字列を指定できます(指定できても該当するコンパイラーがインストールされていないとエラーになりますよ。)

    switch -exact ${configure.compiler} {
        cc { set name "System cc" }
        gcc { set name "System gcc" }
        gcc-3.3 { set name "Mac OS X gcc 3.3" }
        gcc-4.0 { set name "Mac OS X gcc 4.0" }
        gcc-4.2 { set name "Mac OS X gcc 4.2" }
        llvm-gcc-4.2 { set name "Mac OS X llvm-gcc 4.2" }
        clang { set name "Mac OS X clang" }
        apple-gcc-3.3 { set name "MacPorts Apple gcc 3.3" }
        apple-gcc-4.0 { set name "MacPorts Apple gcc 4.0" }
        apple-gcc-4.2 { set name "MacPorts Apple gcc 4.2" }
        macports-gcc-4.0 { set name "MacPorts gcc 4.0" }
        macports-gcc-4.1 { set name "MacPorts gcc 4.1" }
        macports-gcc-4.2 { set name "MacPorts gcc 4.2" }
        macports-gcc-4.3 { set name "MacPorts gcc 4.3" }
        macports-gcc-4.4 { set name "MacPorts gcc 4.4" }
        macports-gcc-4.5 { set name "MacPorts gcc 4.5" }
        macports-gcc-4.6 { set name "MacPorts gcc 4.6" }
        macports-llvm-gcc-4.2 { set name "MacPorts llvm-gcc 4.2" }
        macports-clang { set name "MacPorts clang" }
        default { return -code error "Invalid value for configure.compiler" }
    }

ちなみに、コンパイルオプションを指定したい場合は、下記のようにconfigure.optflagsを追加します。

$ sudo port -d install postgresql90 configure.optflags="-O3 -pipe" configure.compiler=llvm-gcc-4.2

llvm-gcc-4.2でコンパイルしたpostgreSQLでリストアしたところ、無事に完了しました\(^O^)/ バグトラッキングでpatch fileも投稿されていたので、近々反映されるでしょう。

2011年10月11日火曜日

Glenn Gould on Television が届いた

来年は、グレン・グールドの生誕80年・没後30年と言うことで、SONY CLASSICALからCBCのアーカイヴに保管されていた19時間以上にわたるTVドキュメンタリー、演奏シーン、インタヴュー、対談などの全映像をまとめたDVD ボックスが発売されます。

Glenn Gould - The Complete Original Jacket Collectionも、以前ポッチとしてしてしまった身としては、これも買っておく他ないだろうと言うことで、amazonで予約をしました。

予定では9月末に発送の事でしたが、2週間ほど遅れて10/09に届きました。しかし、その日は仕事で修羅場の真っ最中、開けている暇も無かったのですが、ようやく一息ついたので、写真だけでもアップしておこうと思います。

まずは表紙。Import版のはずですが、何故か日本語のシールが貼ってあります。読んでみると簡単な紹介文と字幕は付いていませんと注意書きが書いてありました。

表紙

次は裏表紙

裏表紙

背表紙、薄型のケースを使っているので10枚組でもあまり場所を取りません。メディアをしまうスペースが無くなってきているので、薄型仕様は嬉しい。

背表紙

ブックレットは、最初に「Glenn Gould on Televisionの発売に寄せて」的な事が、英語・フランス語・ドイツ語(多分)で書かれています。それ以外は、各DVDの曲目が書かれているだけの簡単なものでした。

背表紙

DVD本体は至ってシンプルでした。

背表紙

今回は、記念リリースの第1弾らしいですが、2弾・3弾と出てくると財布が心配になってきます。しかし、限定版の場合は買い逃すと一生買えない可能性があるので、出たら買ってしまうのだろうな。

2011年8月2日火曜日

MacPortsのportarchivemodeが廃止された

MacPortsを再インストールでは、portarchivemodeを有効にして、複数のマシンに効率的にインストールする方法を書いたのですが、バージョンが2.0に変わってからportarchivemodeがなくなってしまいました。

portarchivemodeが無くなった代わりに、portはコンパイルする前にhttp://packages.macports.org/をチェックしてパッケージが存在する場合は、それを使うようになったみたいです。

$ sudo port install FDclone +autosort +emacs +lv
--->  Computing dependencies for FDclone
--->  Fetching archive for FDclone
パッケージを取得しているぽい。
--->  Attempting to fetch FDclone-3.00j_0+autosort+emacs+lv.darwin_10.x86_64.tbz2 from http://packages.macports.org/FDclone
--->  Fetching FDclone
--->  Verifying checksum(s) for FDclone
--->  Extracting FDclone
--->  Applying patches to FDclone
--->  Configuring FDclone
--->  Building FDclone
--->  Staging FDclone into destroot
--->  Installing FDclone @3.00j_0+autosort+emacs+lv
--->  Activating FDclone @3.00j_0+autosort+emacs+lv
--->  Cleaning FDclone

あらかじめコンパイルされたパッケージを使うようになって地球に優しくなったのですが、現状 http://packages.macports.org/ には、それほどパッケージが用意されていないので、結局はコンパイルする事になり、あまり役に立っていないのが現状です。

パッケージのFetchとportarchivemodeを両方サポートしてくれれば最高なんですけどね。今後に期待しましょう。

2011年7月31日日曜日

今年は蝉が少ない?

自分は田園都市線沿線に住んでいますが、例年よりも蝉の鳴き声が少ない気がします。毎年誰かが少ないと言っているような気もしますが、今年は地震の影響も多少あったのかなと思っています。原因として考える要因を、思いつくままにあげてみると

  1. 地震の揺れで圧縮された土に押しつぶされて圧死。
  2. 局部的な液状化で溺死。
  3. 寒いのでもう少し待っている。
  4. 8月から本気出す。
  5. 放射線の影響で巨大化している最中。
  6. 怒りの頂点に達していないので、サナギマンから脱皮できない。

例年だと、後半大量に羽化して五月蠅くなののですが、今年の8月は涼しいらしいので、少ないまま終わってしまうかも。

自分は、ミンミンゼミ・ツクツクボウシ・ひぐらし等のリズム系の鳴き声は好きなのですが、アブラゼミ等のノイズ系は嫌いなので、所々で聞こえる程度の方が返って良かったりします。

2011年7月28日木曜日

スニペットの管理ツールCodeBoxが85円だったので買ってみた。

以前から、スニペットを管理するアプリが欲しかったのですが、フリーなものだと機能が微妙な感じで、有料なものだと今度は価格面が微妙で買いあぐねていました。 今日、何となくApp Storeをのぞいてみると、CodeBoxと言うアプリが85円で売っていました(確か以前は850円だったと思うので90%off!!)。

CodeBox

CodeBoxは候補の一つに挙がっていたのですが、お試しができないのと最近作成されたアプリの様でしたので保留にしていました。でも、今回85円だったので失敗してもいい金額かなと思いポチッとしてしまいました。

まだ使い始めたばかりですが、基本的な機能は備えているようです。しばらくはこれで様子を見てみようと思います。

CodeBoxのサイトでは$9.99になっているようです。入力ミスなのかセール中なのかいまいち不明なので、欲しい人は今のうちに買っておいた方がよいかも。

2011年7月20日水曜日

64bit版emacsのwnn7eggがbackend timeoutになる件を調査してみた

emacsの64bit化を阻むもの

自宅サーバ(NetBSD 64bit)には、32bit Linux emulationでオムロンソフトウェアのWnn7が動作しています。そして、これを自宅サーバ(NetBSD)・開発マシン(Mac mini)・サブマシン(Macbook air)上のemacsから使用しています。この構成だと学習した情報をサーバー側で一元管理できるので、学習データを共有するための同期処理をどうしようかと悩む必要がなくて重宝しているのですが、以前、各マシンのemacsを64bit化しようと目論んだのだけれども、64bit化するとwnn7eggがbackend timeoutというエラーを吐いてしまい断念してしまいました。

デバッグ

まず64bit版 Emacsを"--debug"を付けて立ち上げてbackend timeoutするときのBacktraceを取って、不具合のありそうな関数に当たりをつけて32bit番の動きと違いがないか一個ずつ調べてみました。Elispのデバッグはしたことがかなったので、凄く効率が悪く面倒臭いデバッグ方法になってしまいました。

上記のやり方で調査していくと、 wnn7rpc-get-autolearning-dic関数で違いが出ることがわかりました。

  (defun wnn7rpc-get-autolearning-dic (env type)
  "Get id of auto learning dictionary on the server.
Return dictionary id + 1 on success, 0 on no dictionary, negate-encoded
error code on faiulure."
  (wnn7rpc-call-with-environment env (result)
    (comm-format (u u u) (wnn-const JS_GET_AUTOLEARNING_DIC)
                 env-id type)
    (wnn7rpc-get-result
      (comm-unpack (u) result)
      (print result)
      (1+ result))))

上記のソースのように(print result)を付加してresultの値を表示すると32bitと64bitで違いが発生します

;; 32bit Emacsで正常の場合
Wnn: connecting to jserver at foo.rfc2606.invalid.jp(22273)...done
ホスト foo.rfc2606.invalid.jp の Wnn を起動しました
Loading /Users/bar/.eggrc-wnn7...

-1

32

-1

34

Loading /Users/bar/.eggrc-wnn7...done

;; 64bit Emacsでbackend timeoutの場合
Wnn: connecting to jserver at foo.rfc2606.invalid.jp(22273)...done
ホスト foo.rfc2606.invalid.jp の Wnn を起動しました
Loading /Users/bar/.eggrc-wnn7...

4294967295

4294967295

もしかして変数のbit幅の問題?

32bit Emacsでは-1を取り、64bit Emacsでは4294967295を取る。これを16進数に直すと興味深い値が出てきます。

;; 32bit Emacs場合
(format "%x" -1)
1fffffff

(format "%x" 4294967295)
1fffffff

;; 64bit Emacs場合
(format "%x" -1)
3fffffffffffffff

(format "%x" 4294967295)
ffffffff

え〜っ!? 32bit Emacsの変数のbit幅って、29bitだったんですか! 長年Emacsを使用していたけれどしらなかった。しかも64bit Emacsは62bit? なんでこんなに中途半端なbit数なんでしょうね

上記の結果より処理結果が536870911(#x1fffffff)以上の値をとると32bit Emacsと64bit Emacsで評価内容が変わってしまう事がわかりました。

comm-unpack関数って何しているの?

次に、32bitと64bitで異なった値を返してくるcomm-unpack関数を調べてみました。comm-unpack自体は引数の値によって適切な関数を呼び出すディスパッチ処理を行い、呼び出した関数の値を返すだけの簡単な仕事しかしていませんでした。

(comm-unpack (u) result)のように引数に"u"をつけるとcomm-unpack-u32関数が呼ばれます。

comm-unpack-u32関数って何しているの?

EmacsはJServerと直接通信をしてコマンド/レスポンスのやりとりをしている訳ですが、受信したデータは*Wnn7*バッファに入ってきます。

Wnn7 バッファ

これを適切なbit長で読み出してコマンドを再構築するのが、comm-unpack関数で受信したレスポンスを32bitにアンパックしてする場合にcomm-unpack-u32関数が呼ばれます。

(defun comm-unpack-u32 ()
  (progn
    (comm-require-process-output 4)
    (+ (lsh (comm-following+forward-char) 24)
       (lsh (comm-following+forward-char) 16)
       (lsh (comm-following+forward-char) 8)
       (comm-following+forward-char))))

この時に、0xffffffffというデータを受信していると32bit Emacsと64bit Emacsで結果が変わってしまいます。

では、どんな値が*Wnn7*バッファ入ってきているのでしょう?ダンプしてみました

Wnn7 バッファ

はい、見事に0xffffffffを受信しています。ありがとうございました。

原因

  1. 32bit Emacsの整数bit幅は29bit
  2. 62bit Emacsの整数bit幅は62bit
  3. jserverから0xffffffffを受信すると
  4. 32bit Emacsは-1と評価する。
  5. 62bit Emacsは4294967295と評価する。
  6. 62bit Emacsの場合、不明なレスポンスしかこないので、backend timeoutで落ちる。

対策

原因が判明したので、comm-unpack-u32関数を修正して整数が29bit幅の以外の時は、変数の値を62bit幅に拡張する処理を入れてあげればよいと思われる。整数のbit幅が他の値をとることはあるのかな?考えないことにしておく。

wnn7egg-edep.el

Emacsの依存性があるコードはここに書かれるようなので、下記のコードを追加

(defconst interger_width_29bit (logxor (lsh (lsh 1 29) -29) 1))

interger_width_29bitは整数が29bit幅ならば1、29bit幅以上ならば0を取ります。

wnn7egg-com.el

comm-unpack-u32関数を下記のように修正。

(defun comm-unpack-u32 ()
  (progn
    (comm-require-process-output 4)
    (if (= interger_width_29bit 1)
        (+ (lsh (comm-following+forward-char) 24)
           (lsh (comm-following+forward-char) 16)
           (lsh (comm-following+forward-char) 8)
           (comm-following+forward-char))
      ;; for 62bit width
      (ash (lsh (+ (lsh (comm-following+forward-char) 24)
                   (lsh (comm-following+forward-char) 16)
                   (lsh (comm-following+forward-char) 8)
                   (comm-following+forward-char)) 30) -30))))

変数の値が62bit幅の場合は、31bit目のデータを符号ビットの場所までシフトしてから、算出シフトで元の位置まで戻してあげます。(ソースでは30bitシフトしていますが、33bitシフトの方がよいかもしれません。)

ソースとパッチ

ソースとパッチをおいておきます。ご自由にお使いください。

  1. wnn7egg-edep.el
  2. wnn7egg-com.el
  3. wnn7-egg-backend-timeout.patch

2011年6月20日月曜日

MacPortsを再インストール

古くなったMacPortsを再インストールという記事をみて、自分の環境も汚くなりつつあり整理しないといけないと思っていたので、再インストールしてみた。

MacPorts削除の前準備

MacPorts削除する前にDBのダンプやデーモンの停止をしておきます。最初にDBのダンプをとります。

# /opt/local/lib/postgresql/bin/pg_dumpall > /tmp/pgsql.dump
# /opt/local/bin/mysqldump5 -u root -x --all-databases > /tmp/mysql.dump
#

次にMacPortsでインストールしたデーモンのプロセスを停止させます。

# port unload apache2
# port unload postgresql90-server
# port unload mysql5-server
#

インストール時期がかなり前だと、どのデーモンをMacPortsでインストールしたか忘れてしまうこともあります。そんな時は、launchctl コマンドを使えば、 現在動いているデーモンからMacPortsでインストールしたものを抽出できます。

# launchctl list | grep macports
60083 - org.macports.postgresql90-server
59969 - org.macports.mysql5
59934 - org.macports.apache2
#

MacPortsを削除とインストール etc..

元記事と大体一緒なので簡単に..
一応最初に "port installed > /tmp/install.txt"として、現在インストールされているport一覧を取っておきます。

# port installed > /tmp/install.txt
# port deactivate active
# port -f uninstall installed
# port clean all
# sudo mv /opt/local /opt/local.old
#

macportをインストールして、最新版に更新。

# port selfupdate
# port upgrade outdated
#

macports.confの編集

最新版に更新後、/opt/local/etc/macports/macports.conf を編集してportarchivemodeをyesにします。これによって、コンパイル時にパッケージ アーカイブファイルが/opt/local/var/macports/packagesに作られます。またインストールする際にパッケージがあれば、再コンパイルせずにそのパッケージが使われるので、時間と電力の節約になります。

# vi macports.conf
portarchivemode         yes

sourceとpackageの移動

既にあるソースとパッケージは再利用したいので、新しいディレクトリに移動させます。

# mv /opt/local.old/var/macports/distfiles/* /opt/local/var/macports/distfiles/
# mv /opt/local.old/var/macports/packages/darwin /opt/local/var/macports/packages/
# 

インストール

パッケージが既にあるportをインストールすると、コンパイルせずにパッケージファイルを使用するので、面白いほどサクサクインストールが進みます。もちろんパッケージよりインストールするポートのバージョンが新しければ、コンパイルが行われ新しいパッケージが作成されます。

# port install lv +lesslikeslash
--->  Computing dependencies for lv
--->  Dependencies to be installed: ncurses ncursesw
--->  Unpacking tgz archive for ncursesw 5.8_0
--->  Installing ncursesw @5.8_0
--->  Activating ncursesw @5.8_0
--->  Cleaning ncursesw
--->  Unpacking tgz archive for ncurses 5.9_0
--->  Installing ncurses @5.9_0
--->  Activating ncurses @5.9_0
--->  Cleaning ncurses
--->  Unpacking tgz archive for lv 4.51_2+lesslikeslash
--->  Installing lv @4.51_2+lesslikeslash
--->  Activating lv @4.51_2+lesslikeslash
--->  Cleaning lv
#

mysqlのインストール

# port install mysql5 mysql5-server
# sudo -u _mysql mysql_install_db5
# cp /opt/local.old/etc/mysql5/my.cnf /opt/local/etc/mysql5/my.cnf
# port unload mysql5-server
# port load mysql5-server
# mysql5 -u root -p < /tmp/mysql.dump
#

postgresqlのインストール

# port install postgresql90 postgresql90-server
# mkdir -p /opt/local/var/db/postgresql/defaultdb
# chown -R postgres:postgres /opt/local/var/db/postgresql/defaultdb
# ln -s /opt/local/var/db/postgresql /opt/local/var/db/postgresql90
# ln -s /opt/local/lib/postgresql90 /opt/local/lib/postgresql
# su postgres -c ‘/opt/local/lib/postgresql90/bin/initdb -D /opt/local/var/db/postgresql90/defaultdb -E UTF8 --no-locale'
# vi /etc/sysctl.conf
kern.sysv.shmmax=167772160 
kern.sysv.shmmin=1
kern.sysv.shmmni=32
kern.sysv.shmseg=8
kern.sysv.shmall=65536
# port load postgresql90-server
# su postgres
$ psql -f /tmp/pgsql.dump template1
$

apacheのインストール

# port install apache2 +preforkmpm
# port install php5 +apache2 +pear
# port install php5-curl php5-mbstring php5-mysql php5-postgresql
# port install php5-gd +t1lib
# mv /opt/local/apache2/conf /opt/local/apache2/conf.org
# ln -s /var/www/conf /opt/local/apache2/conf
# cp /opt/local/apache2/conf.org/extra/mod_php.conf /opt/local/apache2/conf/extra/
# cp /opt/local/apache2/conf.org/mime.types /opt/local/apache2/conf/
# rm -r /opt/local/apache2/htdocs
# ln -s /Library/WebServer/Documents /opt/local/apache2/htdocs
# ln -s /var/www/conf/php/php.ini /opt/local/etc/php5/php.ini
# 
# port load apache2
#

それ以外のportも、最初に保存したinstall.txtを見ながら、抜けがないようにインストールしていきます。

他のマシンもMacPortsを再インストール

MacBook air 11インチにもMacPortsが入っているので、同じようにして再インストールしていきます。

ただしpackageファイルは先ほど再インストールが終了したマシンから移し替えます。このようにすれば、MacBook airには最新のパッケージが入るので、コンパイルレスでインストールができます。実際、実行すると爆速でインストールが終了します。

2011年6月10日金曜日

emacsのフレームサイズを画面解像度によって動的に変更する方法

メインの開発環境はmac mini+FlexScanL885なのだが、外出先などではMacbook air 11インチを使用している。emacsのデフォルト フレーム サイズをFlexScanL885にあわせるとMacbook airでは、はみ出てしまう。逆にMacbook airにあわせると、FlexScanL885では狭すぎて開くたびにリサイズするなんてことになる。

じゃあ解像度に合わせて、動的に開くフレームサイズを決めれば良いんじゃねぇ。ということで下記の設定を書いてみた。

;; 画面の解像度によりフレームサイズを変化させる
(when window-system
  (if (>= (x-display-pixel-width) 800) (setq width-gain 0.45) (setq width-gain 0.8))
  (if (>= (x-display-pixel-height) 1000) (setq height-gain 0.7) (setq height-gain 0.87))
  (set-frame-size (selected-frame)
                  (floor (/ (* (x-display-pixel-width) width-gain) (frame-char-width)))
                  (floor (/ (* (x-display-pixel-height) height-gain) (frame-char-height))))

横の解像度が800px以下の場合は、横のフレームサイズを ((横解像度*0.8)/1文字の横ピクセル数)、横の解像度が800px以上の場合は ((横解像度*0.45)/1文字の横ピクセル数) としている。

また、縦の解像度が1000px以下の場合は、縦のフレームサイズを ((縦解像度*0.87)/1文字の縦ピクセル数)、縦の解像度が1000px以上の場合は ((縦解像度*0.7)/1文字の縦ピクセル数) としている。

2011年6月9日木曜日

TotalFinderとcdtoを導入した。

先日、MacUpdate PromoTotalFinderを40% offセールを行っていた。通常$15の所を$9で購入できるというので、前々からよさげなツールだと思っていたので導入してみた。

TotalFinderの良いところは、今まで別々に開いていたFinderをタブとして開くことが出来るところでしょう。Finderを開きすぎて、画面がゴチャゴチャしてしまう事がなくなったので、買ってよかったと思う。

TotalFinder

ついでに、現在Finderで開いているディレクトリの場所をターミナルでひらいてくれる>cd to ...も導入してみた。この辺を参考にしてインストールする。

cd to..

自分はTerminal.appでなくiTermを使用しているのでiterm用のプラグインに入れ替える。

$ mv /Applications/\>cd\ to\ ....app/Contents/PlugIns/terminal.bundle /Applications/\>cd\ to\ ....app/Contents/PlugIns\ Disabled/
$ mv /Applications/\>cd\ to\ ....app/Contents/PlugIns\ Disabled/iterm.bundle /Applications/\>cd\ to\ ....app/Contents/PlugIns/

入れ替えてみたのだが、何故かiTermが立ち上がらない。Terminalに戻すとうまくいくので、iTermの問題らしいので、googleさんに聞いてみてたが他の人は動いているらしい。何故だ???としばらく考えていたところ、自分が使っているのはiTermでなくiTerm2だったことを思い出した。

改めてググってみると、Does not work with iTerm2というのが引っかかった。PlugIns/iterm.bundle/Contents/MacOS/itermはIDが”net.sourceforge.iTerm”となっているので"com.googlecode.iterm2"にバイナリエディタなどで書き換えてあげれば動くよとの事だった。 しかも、パッチ済みのプラグイン(iterm2.bundle.zip)も置いてあったので、それを使わせてもらいました。

$ mv /Applications/\>cd\ to\ ....app/Contents/PlugIns/iterm.bundle /Applications/\>cd\ to\ ....app/Contents/PlugIns\ Disabled/
$ unzip iterm2.bundle.zip
$ mv iterm2.bundle /Applications/\>cd\ to\ ....app/Contents/PlugIns/

これで、>cd to ...からiTerm2を立ち上げることができるようになりました。

2011年5月12日木曜日

IKEAでスタンドランプを買ってきた。

ゴールデンウイークも過ぎてIKEAも空いてきた頃だろうと思い、前からほしかったスタンドランプを買いに行ってきた。

SUNNAN

1つはSUNNANと言う太陽光で充電できるタイプのLEDライト。SUNNANは2台目なのだが、以前買ったときは2,500円程したと思ったのだけれど、今回は1,990円で買えた。電力不足で停電になりそうな昨今、こう言うランプが安く買えるのは有り難いです。

もう一つは、コンセントから供給するタイプのLEDライトJANSJO。意外に安くて1,490円!!組み立て式なのですが、台座が石だったのが驚いた。石にプラスチックのカバーを被せて下の部分をシールで固定して完成。早速、作業机に置いて使用してみました。

JANSJO

構造はちゃちだけれども、それなりに明るくて重宝しています。

2011年4月20日水曜日

デザインを変えてみた

一年以上放置してあったこのページだけど、また再開してみようかと思い開いてみると、”テンプレート デザイナー”という項目が増えていた。ちょっといじってみたら、いい感じに変更できた。

と、どうでも良い事をテストを兼ねて投稿してみる。