2018/05/23

全体主義的な組織が持つ危険性



2018/09/24
冷静に書いたつもりでしたが、誤りや理由の不足が多いので大幅に修正しました。


大学組織に属する人間が学生個人の後々の人生にまで影響するような犯罪的行為に関与しているという報道に憤りを感じています。
また大学が事後に学生を十分に守れなかったという点にも強い憤りを感じると同時に、勇気ある行動を取った学生に救いがあることを心から望んでいます。


報道ではまだ事実関係と感情的な表現が混り合い、必ずしも客観的な報道が行なわれているとはいえないと感じています。
しかし複数の関係者から得たと思われる事実関係から、これは強いチームを作ることを目的・大義名分として引き起された組織的な犯罪的行為だと考えています。
この問題の構造上、大学・監督側に罪の意識がない事は当然だと思いますが、同時に決して社会的に容認してはならない行為が含まれていると確信したため、この記事を残しておきたいと思います。



日大アメフト関連のニュースをみて、カルト的な性質を持つ組織の危険性を十分に指摘できていないと感じています。
これまでの報道から、ここで指摘したいポイントは以下のとおりです。


  1. 監督側が坊主頭にするよう指示した点 (私生活への関与)
  2. 監督側が試合だけでなく練習にも参加させなかった点 (無気力感の付与)
  3. 試合に参加させる条件として、違反行為を指示した点 (組織への帰属意識の醸成)
  4. 罪の意識を感じている当人に、優しいのがいけない・指示した監督の責任である、と、罪の意識を感じなくてもよい旨の言葉をかけている点 (許しと信念の強化)
  5. 記者会見で行為を犯した当人が、自分の弱さであったと自分を責めた点 (権威である監督側を責めないのは、打ちひしがれ無気力感を強く感じている被害者が取る行動の典型)

これらを読んで、チームスポーツではままあることである、本人が判断して実行したのだから本人にも一定の責任がある、と考えることは非常に危険です。


これは監督側が悪意なく・無意識に立場の弱い若い人間をコントロールし、組織に隷属させようとした行為である、と捉えるべきです。
強いチームを作る大義名分の元では過激な指導が正当化されてきた雰囲気はこれまで日本社会にあったと思います。
しかし日常生活にも関与され、練習にも参加が許されず、十分に自分を責める環境に置かれた学生には、反動として監督側の期待に応えたいという気持ちが大きくなるでしょう。
怒りを感じるのではないか、と疑問を持つかもしれませんが、監督側への反抗は学生の利益になりません。
今回は真面目な学生であったが故に、自分を強く責め、怒りの感情を持つこともなかったのではないでしょうか。
これはテロ組織の構成員が指導者や神が喜ぶこととして指示以上の過激な行為を行なったり、虐待を受けた子供達が、怒りよりも親の期待に応えたいという気持ちを持つ事と同じ構図です。


個々の課題

監督が、論理的に考えて懲罰以外のなにものでもない、坊主頭にするよう指示した点は、少し前であれば中学や高校でもあったと思います。
しかし、これは管理上生み出された手法であり、個性を消し組織への隷属を進める上での重要な第一歩です。

まず私生活面に指示を出すことは、権威を強化するために良くみられます。
こういった行為を繰り返すことで、当人から反論したり、反発する気力を奪う効果があります。


客観的に考えて不合理な理由の元で、試合だけでなく練習にも参加させない、という行為は、無気力感を付与する上で、非常に強力な手法です。

暴力行為など部内の風紀を乱した分けでもない者を、練習にも参加させないという事は、有り得ないことで、学生は混乱します。
おそらく監督・コーチは雰囲気を壊していると考え、監督側としては合理的な理由があったのだと思います。
しかし、本人が正しいと思ってることを理由を与えずに否定することが、無気力感を付与する上で非常に効果的に働いています。
合理的な理由の裏にある無意識が真の理由であり、学生を心理的に束縛し、監督側が意図した雰囲気・動きを生み出すことに利用されています。


そして、徹底的に存在価値を否定した人間に対して、試合に出る条件として犯罪的行為を求めることは、取引として正当ではないことは当然ですが、組織に留まるために与えた唯一の選択肢であり、その瞬間の学生にはこれ以外の選択肢があるとは思えないでしょう。
これはメンバーがあたかも自発的に犯罪行為を犯しているかのように見えるカルト的組織の犯罪と似ています。

この先の展開としては、犯罪的行為を行なった学生に対して、監督側が許しを与え、組織の中での地位を高めるなどの手法により、より組織への帰属意識を強める効果が埋まれるはずでした。
しかし、ここで手順を間違えたので、今回は、むしろ組織から離れるという選択をさせてしまった点が監督側としての失敗で、社会にとっての幸いでした。


このように荒削りですが、学生の自主性を奪った後に犯罪的行為に勧誘するという環境を作る監督側の行為は人間の尊厳に対する挑戦です。
一連のニュースへのリアクションとして、日本を代表するカルト的組織である、ヤクザとの類似点を指摘する声があることは極めて正しいリアクションだと思います。


しかも、最後に罪の意識を強く感じている当人に許しを与えるかのような監督の行為は、まさに成功しなかったことが幸いですが、うまくいっていれば、監督・コーチを神と崇め隷属する学生が一人増えたことでしょう。
今回の件では、監督の許しに続いてコーチの叱責があったといわれていて、これにより効果が弱くなり、学生の帰属意識を深めなかったと思われます。


記者会見で学生本人は自分の弱さが理由であったと述べていますが、一連の行為により判断能力や抵抗する力を奪われている状態だった点を指摘するような報道はあまりなかったかなという印象を持っています。


この問題を繰り返さないために

日大アメフト部を一言で象徴するなら、監督をトップとする全体主義的な組織だったといえるでしょう。
日本が戦争を犯した反省として、こういった組織の存在を許すことはあり得ないと思うのですが、戦後日本の繁栄は、こういった組織を温存したから達成できた側面もあると思われますので、社会的に一定受容されてきた経緯が今回の悲劇を招いたと考えています。


対象的な関西学院大の対応が望ましく思われている理由は、自由・個人の尊重といった、民主主義的な組織という印象を与えているからだと思われます。


おそらく近い将来に「勝つために必要だった」という言い訳を聞く事になると思われますが、大切なポイントは全体主義的な組織、個人崇拝・個人が持つ権力の絶対化、を許さないという点です。
恐怖で他者をコントロールしようとする組織は、これからの社会では必要ないと考えるべきです。


今回の件は、この日本の中で見られるある種の典型的な組織風土が極端に出た形だと思います。
しかし、類型は様々なところで問題を起しているという認識を持って、"誰か"が悪かった、という結論は何の解決策にもならず、一般化しできるだけ広く適用できるあるべき姿を模索しよう、という理解・努力が広がることを期待しています。


最後に、どのような組織であっても帰属意識を高めることは必要で、組織というものは悪意なしに何等かの方法でメンバーに影響を与えようとしています。
それ自身が悪いわけではありません。
問題はルールが不明確で、メンバーに対して自由を与えず組織が望まない選択肢を取ることができない状態に導くことが問題で、その組織から離れることを含めて全ての自由・選択肢がメンバーにあることが望ましく、そこが犯罪的な組織とその他の組織を分けるポイントだという点を強調しておきたいと思います。


2013/05/05

RaspberryPiでLVS+keepalivedを使ってHA構成にしてみた

RaspberryPiは手軽なLinux実行環境ですが、定格で5V/700mAが必要です。 古いPCやUSBハブに接続した場合には、うまく動かない可能性があります。

iPadやタブレットで充電に1000mA(==1A)が必要な状況なので、それほどUSBの電源周りも余裕のある設計になっているものも多くあるはずです。

とはいえ、USB2の定格は5V/500mAなので古めのPCや電源付きUSBハブにいろいろな機器を接続した場合には動作が不安定になる可能性があります。

またカーネルに3.6-trunk-rpiを選択した時には、2013年5月5日時点では、ファイルシステムに負荷をかけるようなタイミングでBUG: scheduling while atomic: swapper/...のエラーが出てまともに動きませんでした。

対応linuxカーネルの有効化

基本的な環境はarmelhfアーキテクチャのRaspbian "wheezy" をインストールした状態です。

Raspbianのカーネルは3.6.11#371版ですが、ip_vsモジュールなどは導入されていません。

このためパッケージからip_vsモジュールの含まれているイメージを導入します。

$ sudo apt-get install linux-image-3.2.0-4-rpi
起動時のカーネルイメージの変更

linux-image-*パッケージを導入しただけでは、再起動をしても引き続きRaspbianの付属カーネルが使われます。 ポイントは次のとおりです。

  • zImageを/boot/kernel.imgのファイル名でコピーする
  • initrdイメージがある場合は/boot/config.txtに記入する
/boot/kernel.imgファイルの置き換え

既存のkernel.imgファイルは退避して、vmlinuz-3.6-trunk-rpiファイルをコピーします。

$ cd /boot
$ sudo mv kernel.img kernel.3.6.11#371.img
$ sudo cp vmlinuz-3.2.0-4-rpi kernel.img

ちなみに/bootはvfatなので、ハードリンクなどを使う事はできません。 基本的にはcopyで対応することになります。

/boot/config.txtファイルの書き換え

initrdを使用している場合には、対象のファイル名をconfig.txtに書き換えます。

...
ramfsfile=initrd.img-3.2.0-4-rpi
ramfsaddr=0x00a00000
initramfs initrd.img-3.2.0-4-rpi 0x00a00000
...

ちゃんと確認していませんが、/bootにあるものとしてファイル名だけを記述しています。

再起動でカーネルの確認

とりあえず再起動して動作を確認します。

うまく行かない場合には別のPCに接続して編集内容を確認します。 /boot以下はVFAT領域なので、問題なく扱えるはずです。

ramfsaddrなどを指定しないと、initrdのイメージが展開されない事になります。 うまくいけばdmesgに次のようなメッセージが表示されます。

$ dmesg | grep init
...
[    1.049760] Unpacking initramfs...
[    1.710015] Freeing initrd memory: 4476K
...

パッケージの導入

ipvsadmとkeepalivedを使いますが、ipvsadmはkeepalivedの導入時に自動的にインストールされます。

keepalivedの導入

パッケージを導入します。

$ sudo apt-get install keepalived

設定

パッケージを導入しても設定ファイルは一切導入されないので、過去のログをみながら設定ファイルを構成します。

/etc/keepalived/keepalived.confの編集

今回はWebサーバではなくて、ESXi上に構成しているLDAPサーバに対してHA構成を取っています。

振り先の設定

LDAPサーバ側にいくつか設定が必要です。

/etc/sysctl.confの編集

対象サーバが1台しかない場合には、問題になりませんが、複数のslave LDAPサーバに処理を分散させるような場合にはサービス(仮想)IPとMACアドレスが強力に結びついてしまうと、ルータからダウンしたLDAPサーバに常に処理が振られてしまうのでARPリクエストに反応しないように変更する必要があります。

/etc/sysctl.confへの追加内容

net.ipv4.conf.eth0.arp_ignore=1
net.ipv4.conf.eth0.arp_announce=2

設定を反映させます。

$ sudo sysctl -p

sysctlコマンド実行後の画面出力

net.ipv4.conf.eth0.arp_ignore = 1
net.ipv4.conf.eth0.arp_announce = 2
サービス(仮想)IPの設定

IPレベルではリクエストは2台のRaspberryPiで共有されるサービス用の(仮想)IP宛てのパケットがLDAPサーバに到着します。

自分宛てのパケットだと認識しないといけないので、loopback(lo)にIPを設定します。 まだ未使用のlo:0デバイスを使います。他に使用している場合には、lo:1,lo:2など適当な番号に変更してください。

/etc/network/interfacesファイルへの追加内容

auto lo:0
iface lo:0 inet static
  address 192.168.1.182
  netmask 255.255.255.255

さいごに

RaspberryPiを入手して、いろいろ試していますが、電源の品質とカーネルの安定性が一番の問題でした。

電源はUSBハブから取っていますが、マウス、キーボードなどは本体に直接つないで他の機器はつないでいません。

PCなどに接続する場合には、2つ口の片側に接続する事で500mA 2つ分の1000mAまで電流が取れるものが多いようです。 最近ではiPadやタブレットに対応した急速充電可能なタイプであれば、1000mAまで取れるので問題ないでしょう。

SDカードはTranscendのClass10 UHS-I対応16GBと、PanasonicのClass 10 SDHC 8GBのカードを使っています。 他のARM系ボードでも使っていますが、これまでのところ問題は起きていません。

この他にも$ sudo raspi-configで変更できるパラメータは少し変更していて、安定して動くようになってから900MHzへのオーバークロックやVRAMを16Mに変更したり、

tail -5 /boot/config.txtの実行結果

# for more options see http://elinux.org/RPi_config.txt
gpu_mem=16
core_freq=250
sdram_freq=450
over_voltage=2

この記事で取り上げた品々

2013/05/04

namecheapで購入したWildcardSSL証明書をOpenLDAPにインストールしてみた

これまで389ポートで運用してきたESXi 5.1上のOpenLDAPサーバにSSL証明書を適用してみました。

実際のところnamecheapは関係なくて、SSL証明書をどこで購入したのかは問題ではなくて、root CAや中間CA証明書の有無などが問題だったりします。

今回利用する証明書の構成や、対象サーバの環境は以下の通りです。

  • OS: Ubuntu 12.04 LTS 64bit版
  • SSL root CA Issuer: C=SE, O=AddTrust AB, OU=AddTrust External TTP Network, CN=AddTrust External CA Root
  • SSL Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=PositiveSSL CA 2

最近は4階層のSSL証明書も普通にありますが、PositiveSSLの中間CA証明書は1つだけの3階層です。 4階層はテストしていませんが、c_rehashコマンドでハッシュファイルへのシンボリックリンクを作成するところを外さなければ、問題なく扱えるはずです。

ファイルの準備

SSL関連の操作ではファイル名は任意なのですが、扱うファイルの数は多い傾向があります。

まぎらわしいので参考のためにリストにしておきます。

  • WildcardSSL.crt: CN=*.example.com(Subject: OU=Domain Control Validated, OU=PositiveSSL Wildcard, CN=*.example.com)
  • PositiveSSLCA2.crt: 証明書 (Subject: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=PositiveSSL CA 2)
  • AddTrustExternalCARoot.crt: CA証明書 (Subject: C=SE, O=AddTrust AB, OU=AddTrust External TTP Network, CN=AddTrust External CA Root)
  • newkey.nopass.pem: パスワードで保護されていないWildcardSSL.crtに対応する鍵ファイル
  • rootca.crt: PositiveSSLCA2.crt + AddTrustExternalCARoot.crtの2つのファイルが連結された単一CA証明書ファイル

*.crtファイルの内容は全て-----BEGIN CERTIFICATE-----で始まるので紛らわしいかと思います。 以下のコマンドで-inオプションの引数にファイルを指定すると中身を確認することができるので便利です。

$ openssl x509 -text -noout -in <cert filename>
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            6f:c7:b2:c6:af:e4:cc:a6:d3:61:4b:1f:6d:56:be:fd
    Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=PositiveSSL CA 2
        Validity
            Not Before: Dec 13 00:00:00 2012 GMT
            Not After : Dec 13 23:59:59 2014 GMT
...

newkey.nopass.pemファイルは-----BEGIN RSA PRIVATE KEY-----で始まるファイルで、パスワードで保護されていない形式です。

パスワードを外す方法はnewkey.pemがパスワードで保護された鍵ファイルだとして、$ openssl rsa < newkey.pem > newkey.nopass.pemのような要領で作成する事ができます。

ファイルの配置

準備したファイルをOpenLDAPサーバ上に配置していきます。

今回はUbuntuなのでシステムで準備している/etc/ssl/certs, /etc/ssl/privateがありますが、クライアント認証をするわけでもなくシステムデフォルトと一線を引いて管理するためにファイルの配置場所は別に準備します。

$ sudo mkdir -p /opt/openldap/ssl
$ sudo cp WildcardSSL.crt /opt/openldap/ssl
$ cat PositiveSSLCA2.crt AddTrustExternalCARoot.crt | sudo tee /opt/openldap/ssl/rootca.crt
$ sudo c_rehash /opt/openldap/ssl/
$ sudo chgrp openldap /opt/openldap/
$ sudo chmod 750 /opt/openldap/

ESXiサーバのシェルの場合などはc_rehashコマンドが準備されていない事もありますが、手動でのリンク管理は面倒なので利用しています。

うまくいくと、次のような内容の/etc/openldap/sslディレクトリが作成できてるはずです。

sudo $ sudo ls -l /opt/openldap/ssl
lrwxrwxrwx 1 root root   22 May  4 18:35 459f9267.0 -> WildcardSSL.crt
lrwxrwxrwx 1 root root   10 May  4 18:35 5f852f3e.0 -> rootca.crt
lrwxrwxrwx 1 root root   10 May  4 18:35 ed207a3e.0 -> rootca.crt
lrwxrwxrwx 1 root root   22 May  4 18:35 f8a2c70e.0 -> WildcardSSL.crt
-rw-r--r-- 1 root root 1679 May  4 18:27 newkey.nopass.pem
-rw-r--r-- 1 root root 3278 May  4 18:34 rootca.crt
-rw-r--r-- 1 root root 1801 May  4 18:09 WildcardSSL.crt

設定ファイルの変更

必要なファイルを配置したら、Openldapの設定ファイルの変更です。

Ubuntu 12.04 LTSでのopenldapの設定ファイルは/etc/ldap/slapd.d以下でLDAP管理となっています。 そのためファイルを編集するという分けにはいきません。

設定方法は、help.ubuntu.comのOpenLDAP TLS設定方法のページに詳しく掲載されています。

このページに書かれているように、LDIFファイル(/tmp/modify.tls.ldif)を作成してldapmodifyコマンドで実行していきます。

/tmp/modify.tls.ldifファイルの内容

dn: cn=config
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /opt/openldap/ssl/rootca.crt
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /opt/openldap/ssl/WildcardSSL.crt
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /opt/openldap/ssl/newkey.nopass.pem
$ sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f /tmp/modify.tls.ldif
/etc/default/slapdの編集

slapdがサポートするプロトコルを指定する行に、ldaps:///を追加します。

/etc/default/slapdの変更個所抜粋

...
SLAPD_SERVICES="ldap:/// ldaps:/// ldapi:///"
...
APPARMOR対応

標準となっている/etc/ssl/ディレクトリ以下にアクセスする事がapparmorによって拒否されるため、今回はディレクトリを/etc/apparmor.d/local/usr.sbin.slapdに追加しました。

/etc/apparmor.d/local/usr.sbin.slapdファイルの内容

# Site-specific additions and overrides for usr.sbin.slapd.
# For more details, please see /etc/apparmor.d/local/README.

/opt/openldap/ r,
/opt/openldap/** r,

dh_apparmorパッケージをインストールしたのですが、うまく動かないのでシステム全体を再起動します。

$ sudo /sbin/shutdown -r now

稼働確認

ポートの確認

netstatで636ポートが開いている事を確認します。

$ netstat -nl | egrep '389|636' 
tcp        0      0 0.0.0.0:636             0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:389             0.0.0.0:*               LISTEN     
tcp6       0      0 :::636                  :::*                    LISTEN     
tcp6       0      0 :::389                  :::*                    LISTEN
ldapsによるクエリの実行

実際のクエリはDNなどを含むので、slapdumpなどでディレクトリの構造を把握しておく事が必要です。

$ openldap -x -H ldaps://openldap.example.com:636/ -b uid=user01,ou=People,dc=example,dc=com

もしホスト名をopenldap.example.comではなくlocalhostのように指定した場合には、SSLのCommonName(CN)に指定されているホスト名(*.example.com)との対応が取れずにエラーとなります。

$ ldapsearch -x -H ldaps://localhost:636/ -b uid=user01,ou=People,dc=example,dc=com
ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)

localhostの部分をlocalhost.example.comのようにCNと対応するFQDNにすれば、正常に稼働します。

$ ldapsearch -x -H ldaps://localhost.example.com:636/ -b uid=user01,ou=People,dc=example,dc=com
# extended LDIF
#
# LDAPv3
...

まとめ

WildcardSSL証明書はけっこう便利です。 PDFファイルの署名にも論理的には使えますが、CA情報が登録されていないので適切な署名とはみてもらえません。

SSL接続時に警告が出るのはマルウェアなどでサイト誘導されているという認識を持たないと、まったく意味がないのですが、残念ながら世間では、この悪い常識が闊歩しているところもあります。

仕事など、責任を伴なう場面では、積極的にSSL化を勧めて環境を整備しましょう。

2013/03/03

VMWare ESXi 5.1のSSLキーを購入したものに入れ替えてみる

自宅で使用しているVMWare ESXi 5.1のアドレスにWebブラウザでアクセスすると、あたかも乗っ取られたサイトであるかのように表示されるので、以前購入したワイルドカードSSLサーバーキーなファイルに入れ替えてみました。

[2013/05/04 追記]
追加した鍵はnamecheapで購入したCOMODOのWildcardSSLなのですが、rootCAの証明書が入っていませんでした。 そのためFirefox (release 20.0.1)ではhttpsでESXiサーバにアクセスした時に警告画面が表示されてしまいます。
ESXiにsshでログインして、以下の手順(;は改行で読み替え)でrui.rootca.crtという名前のファイルにAddTrust External CA Rootの証明書を作成しています。
$ cd /etc/vmware/ssl; $ vi rui.rootca.crt
rui.crtファイルに複数の証明書を保存する事はできません。 ESXiサーバ上にはc_rehashコマンドがないので手動でopensslが証明書を探せるように、ハッシュ名のファイルにシンボリックリンクを張ります。
ln -s rui.rootca.crt $(openssl x509 -noout -hash -in rui.rootca.crt)
ちなみにcrtファイルはPEM形式なので、openssl x509 -in rui.rootca.crt -noout -textのようなコマンドで中身をチェックする事ができます。 rhttpproxyをリスタートして確認してください。

基本的な操作手順はVMWare公式サイトのthe configuration of Certificate Authority (CA) certificates for a ESXi 5.x host.にあります

手順はsshを有効にするところからあるので長いのですが、実際のステップは次のようなところだけです。

  • Log in to the host and then navigate to /etc/vmware/ssl.
  • Copy the files to a backup location, such as a VMFS volume.
  • Log in to the host with WinSCP and navigate to the /etc/vmware/ssl directory.
  • Delete the existing rui.crt and rui.key from the directory.
  • Copy the newly created rui.crt and rui.key to the directory using Text Mode or ASCII mode to avoid the issue of special characters ( ^M) appearing in the certificate file.
  • Type less rui.crt to validate that there are no extra characters.
  • Switch back to the DCUI of the host and select Troubleshooting Options > Restart Management Agents.

コマンドベースで書くと次のようになるんでしょうか

  • ESXiホストにsshでログイン
  • # cd /etc/vmware/ssl/
  • rui.crtとrui.keyを、入手した証明書とパスワードなし鍵ファイルに置き換える
    • scpやWinSCPを使う事もできるが、証明書はテキストファイルになっている。sshログインしているのであれば、catなどとCopy&Pasteの方がいいかもしれない
    • 例: # cat > rui.crt、コピーした後でControl+c(C-c)
    • # cat > rui.key、同様にコピーした後でC-c
  • # /etc/init.d/rhttpproxy restart

自前CA局が悪いかどうかは状況によるのですが、サイトのポリシーなどでWebサイトに導入するSSL証明書は正規に購入すること、などとなっている場合には必要な作業かと思います。

ただお金を出せば証明してあげる、という構造は理解しやすいのですが、一歩引いてみると、CA局はお金を集めるインセンティブを上から下まで持っているので、ルールが曲げられちゃう可能性もありそうで、それでちゃんとtrust-chainが構成できるのか、少し不安に感じる部分がないでもありません。

最上位CA局は技術・倫理ポリシーを持った非営利的機関にして、それは複数あっていいのだけれど、一般に販売されるブラウザにデフォルトで加えるCA局のスタンダードとかも必要な気がします。

2013/02/06

OpenLDAPを導入したので、各OSでの設定方法をまとめてみる

UbuntuにOpenLDAPを導入して、ldap-account-manager (LAM)で管理しています。

VirtualBOXを使った時のOSへのログインユーザーの管理や、ミドルウェアを稼働させるユーザーの管理をOpenLDAPに一元化したいと思ったので、VMとして使っている主なOSでのldap設定をまとめました。

前提知識

LDAPの設定は様々なミドルウェアで行なえますが、微妙に設定できる名称や設定方法が異なります。

共通部分としてはサーバー名、ポート番号の他にバインドDN(とそのパスワード)、BaseDNなどがあります。

製品によってはユーザー名を構成するサブディレクトリ(ou=People等)の指定ができるものがあります。

また階層を辿るために、base,one,subなどのスコープを設定できるものもあります。 何も設定されていないOpenLDAPは自由に階層を辿る事ができるため、全部のディレクトリ情報を表示する事も可能な事が多く、サンプルもそのように構成されている場合があります。

しかし実際には、ディレクトリ全体を辿られてしまうと社員名とID,e-Mailアドレスとの紐付けなどをごっそり持っていかれる可能性があるため、自分自身のディレクトリ情報以外は編集ができず、それ以外の情報はDNで直に指定しないと閲覧できないように設定されている場合もあるでしょう。

LDAPについての設定方法は標準的な部分と、非標準的な暗黙知によって構成されています。 ActiveDirectoryを前提にしていると、Netscapeに由来するようなDirectory構成

ldapserverldapbasednに指定するサーバー名やBaseDN名は適宜変更してください。

CentOSなど(RedHat系)でのldapログイン設定

以前のブログでも書いていますが、コマンドラインから設定する事が可能です。

 $ sudo authconfig --enableldap --enableldapauth --ldapserver=openldap.example.org --ldapbasedn="ou=accounts,dc=example,dc=org" --updateall

これはCentOS 5.4で試した設定方法ですが、CentOS 6.3でも同様に使えます。

Ubuntuでのldapログイン設定

UbuntuではガイドのLDAPClientAuthenticationにあるように2つのコマンドを実行することでLDAPを設定する事になっています。

 $ sudo apt-get install ldap-auth-client nscd
$ sudo auth-client-config -t nss -p lac_ldap

Ubuntu 12.04 LTSで確認したところ次のようなログインできない問題が発生しました。

  • ログインできず、/var/log/auth.logに次のようなメッセージが表示される pam_ldap: could not open secret file /etc/ldap.secret (No such file or directory)
  • $ getent passwdではUserが表示されるのに、ログインできない
存在しない/etc/ldap.secretの問題

前者の/etc/ldap.secretを要求するのは、/etc/ldap.confでrootbinddnを有効にしているからです。

auth-client-configの設定画面で、クライアントからのパスワード変更を許していないので適当なrootbinddnと空のパスワードを入力したのが原因でした。

/etc/ldap.confからrootbinddn行の先頭に#をつけてコメントにする事で解決しました。

user名は認識されるのにログインできない

単純にnscdがリスタートされていないだけでした。

プロセスを再起動:$ sudo /etc/init.d/nscd restart して、無事にログイン($ ssh user1@example.org)する事ができました。

Debian 6.0.3でのldapログイン設定

DebianにはUbuntuにあったldap-auth-clientパッケージが存在しません。 そのためlibpam-ldap, libnss-ldapを手動で導入します。

$ sudo apt-get install libpam-ldap libnss-ldap
/etc/libnss-ldap.conf, /etc/pam_ldap.confファイルの確認

それぞれアンダースコア'_'やハイフン'-'が入っていてまぎらわしですが、この2つのファイルの内容を念のため確認します。

Ubuntuでの経験を活かして、rootbinddnやパスワードへは空文字列を入力してみましたが、libnss-ldap.confではrootbinddnが何も指定されないまま有効になっていました。

パスワード変更にはOSの機能を使わない事にしているので、今回もrootbinddn行はコメントアウトします。

面倒であれば、apt-getの実行時にadminのDNとパスワードを入力する事で、編集なしで良くなるはずです。

最後に/etc/nsswitch.confを有効にする

nsswitch.confなんて昔のBSD系やLinux OSにはなかったんですけどね…。Solaris 2.2か2.4ぐらいを触った時の衝撃といったらありませんでした…。

他のOSと同様にnsswitch.confのpasswd, group行のcompatfiles ldapに変更すれば完了です。

nscdのリスタート

ここまでで、LDAPに登録したIDにsu -の実行やログインができない場合には、nscdをリスタートしてみてください。

$ sudo /etc/init.d/nscd restart

基本的にはこれで完了するはずです。

FreeBSD 9.1でのldapログイン設定

基本的な流れはガイドのLDAP Authenticationの中にあります。 導入が必要なPortsは以下の通りです。

  • net/nss_ldap
  • security/pam_ldap

自動的に両方のPortsが依存しているnet/openldap24-clientも導入されます。

Portsのインストール(# make install)が完了したら、以下のように3つのファイルを編集するとLDAP認証が有効になります。

/usr/local/etc/nss_ldap.confの設定

基本的にはurlかhost,それにbaseを設定すれば動きますが、使っているLDAPサーバーのディレクトリ構成やサーバー自体の設定によっては必要な追加設定があるかもしれません。

/etc/pam.d/loginの編集

sshd経由でのログインも行なうのであれば、/etc/pam.d/sshdの設定も変更する必要があるはずです。

サンプルはガイドにあるので詳細は省きますが、auth sufficient /usr/local/lib/pam_ldap.so no_warnの設定を入れれば完了です。

/etc/nsswitch.confの編集

ここまでの設定が完了していて、/etc/nsswitch.confファイルのgroup行とpasswd行をcompatからfiles ldapに変更すればログインにldapが使われるようになります。

さいごに

LDAP認証ではBindDNやらAdminDNやらRootBindDNやら、似たようなものや、実質同じものが名前をかえて登場します。

LDAPサーバーの動きをちゃんと捉えるのは面倒ですが、いまならLPI-Japanが無償で配布している高信頼システム構築標準教科書やLPIC Level 3の教本なんかが、良いとっかかりになるはずです。

動きから抑えるのが良いのですが、普段はシステムの裏側にいて、簡単にldapsearchが試せる本番環境というのもあまりありません。

ネットワーク屋さんがルーター管理にRADIUSを動かしても特権用の共有IDなんかをファイルベースで作って終りだったり、本来はLDAPを使うべき場面なのに、他の方法で代用されている場合もあるかもしれないですね。

会社や学校でLDAPサーバーがあっても、それがLDAPサーバーだと気がつかない場合があるかもしれませんし、アクセス制御が厳密でなかなか挙動をリバースエンジニアリングするのは難しい場合もあるかもしれません。

なんにしてもLDAPサーバーを試す環境はいまのところ自分で動かすしかないので、単純にサーバーと管理ツールを入れて終りにしないで、高可用性を保つために何が必要か、よりセキュアな環境にするためには何ができるのか、考えてみると良いでしょう。

2012/12/09

RacktablesでLDAP認証をかける時の注意点

Racktablesは簡単に導入ができて、ビジュアル的にもそこそこ見栄えが良く、ネットワーク屋さんがexcelやvisioを使って書くであろう絵の基本的な部分はカバーできるツールではないでしょうか。

PHPベースなので、あいかわらず拡張性が良いとは思えませんが、とりあえず動いているので使ってみる事にしました。

今回は不特定多数で使用する前提で、Ubuntu上で稼働するopenldapを使ったLDAP認証と連携させる事にしました。

racktablesのadminユーザーで、承認するユーザー名を個別に設定する場合には難しい点はないのですが、グループで認証しようとする場合には、Active Directory(AD)が想定されているので、Openldap用に少しだけ変更してあげる必要があります。

基本的なopenldapの設定

今回は手間をかけないために、ldap-account-manager (LAM)を併用しています。

LAMをUbuntuで使う場合は、openldapがデフォルトでドメイン名をみて基本的なディレクトリを作成しています。 sudo slapcatなどで確認して、変更したい場合には、$ sudo dpkg-reconfigure slapdなどで自分の管理するドメイン(dc=example,dc=com)を設定します。

racktablesの導入

ポイントはだいたい次のようなところでしょうか。

  • mysqlをあらかじめ導入しておく
  • wwwrootディレクトリをScriptAliasに設定するなどし、Webサーバーの実行ユーザーには読取権限だけを与えておく
  • inc/secret.phpファイルをWebサーバーの実行ユーザーに書き換えられるよう権限を変更する ($ sudo chown www-data:www-data wwwroot)
  • http://localhost/racktables/など配置した場所に応じたパスの/install.phpにアクセスし、インストール作業を終える

PHPが参照するファイルはWebサーバーのアクセス制限には縛られないので、secert.phpはシンボリックリンクなどにして、Webサーバーの設定としてはシンボリックリンク参照を無効にしておくのがお勧めです。

racktablesにLDAP認証を設定する

inc/secret.phpファイルに既に入っている雛型だけで、LDAP認証は十分です。 domain行は使わないのでコメントのまま無効にしておきます。

だいたい次のようなコードになっています。

secret.phpファイルの内容抜粋


$user_auth_src = 'ldap';
$require_local_account = FALSE;
$LDAP_options = array
(
        'server' => 'localhost',
#       'domain' => 'example.com',
        'search_attr' => 'uid',
        'search_dn' => 'ou=People,dc=x200,dc=example,dc=com',
# // The following credentials will be used when searching for the user's DN:
#       'search_bind_rdn' => NULL,
#       'search_bind_password' => NULL,
        'displayname_attrs' => 'sn',
        'group_attr' => 'gidnumber',
        'group_filter' => '/^([0-9]+)$/',
        'options' => array (LDAP_OPT_PROTOCOL_VERSION => 3),
#       'use_tls' => 2,         // 0 == don't attempt, 1 == attempt, 2 == require
);

group_attrは基本がAD認証なので、posixAccountで定義されているgidNumberをキーにすると、group_attrに対応するgroup_filterも書き直す必要があります。

PHPのldapsearchのマニュアルをみると、ldapsearchは大文字、小文字を意識しないけれど、戻り値として返される配列のキーは小文字になる記述があります。

そのためgroup_attrに指定する文字列は小文字でなければいけません。

また、group_filterの設定は数字が期待されているので、ここでは全ての数字を許可していますが、ドメインのポリシーに従って、10000番台だけを許可するような設定がここで可能です。

racktablesでのauthorization設定

認証されたユーザーがracktablesにアクセスできるかどうかは、Configurationのpermissions設定で行ないます。

Configuration -> Permissions設定


allow {$userid_1}
allow {lgcn_10000}

デバッグの方法について

secret.phpを編集してもうまく動かない場合、内部動作を確認する方法がないので、printfデバッグの手法を使います。 auth.phpファイルを編集する場合には、認証失敗画面に出力されるよう、$ret['memberof'][]に代入するのがお勧めです。

さいごに

ネットワーク管理用のアプリはいろんな形態が考えられますが、物理的なラックに着目した点で、ユニークなアプリなのかなと思っています。

認証済みユーザーに閲覧権限だけ付与するのに、default tabだけへのアクセスを許可するようなアプローチもできそうですが、それでは閲覧できない情報がいろいろあるので良い方法がないか探しています。

この手のアプリケーションをいろいろみていて、拡張性なんかが気になってしまいます。 mediawikiのWeb API的なアプローチが内部構造として採れないか、ちょっといろいろ考えています。

2012/10/14

「アシュリー事件」を読んで

別記事にまとめてはいましたが、改めて本を入手して読み終えたのでまとめておく事にしました。

ちなみにamazonでは2012/10/5の時点で「通常2~4週間以内に発送 (予定日:10月21日 - 10月31日)」というメールが届いていましたが、繰り上がり、10/13の午前には手に取る事ができました。

実はこの後で郡山市内のジュンク堂に在庫があった事が分かったのですが、場所は医学一般書。 在庫があると分かってからも、しばらく探してしまいました。

この本のポイント

最初の入口は、この事件の表層から賛成、反対、というリクアションを持つだろうとは思いますが、 この本全体では、そこからさらに深く入り、その行動や事象の背景をできるだけ明かにしようという姿勢が明確になっています。

著者が自身のブログで「アシュリー事件を語る方に」のエントリとして、娘さんとの日常を綴っている点からも、賛成、反対という二元論的な反応ではなく、当事者にもっと寄り添う形での、事実をもっと知ってから考えて欲しいという姿勢が感じられ、この本から受ける印象と結びついていきます。

改めて本書を読んで…。自分との距離感

私は何も特別な経験を持っているわけではありません。 当事者でもないのに…、といわれても返す言葉は持っていません。

それでも、ここ最近住民税の減税を掲げて当選したどこぞの市長が障害者向け手当の削減や事業の縮小を模索しているのは事実で、障害者に限らず各種セーフティーネットも見直しが行なわれていく流れになっています。

当然この流れには私自身も居て、この生活が誰かの犠牲や誰かへの皺寄せの上に成り立っているというのは気持ちの良いものではありません。

しかし、その罪意識が軽くなるように、排他的な方向でコントロールを効かせるというのは本末転倒でしょう。

といった感じで、利己的な観点で考えても、アシュリー事件での一連の流れを正当化するのは難しいと感じます。

自身の生存を認めてもらうために大多数に属するというではなく、この世の中は誰でもそのメインストリームから外れる可能性を持っているわけで、マイノリティを包含する社会を作っていくというのが、自身のためでもあるというのが日本なら、まだ共有可能な考え方だろうと思います。

とはいえ、いじめが社会問題として今年は大きく取り上げられましたが、この問題が一定の解決がなされずに、ことなかれ的に放置されるようなら、かなり暗い先行きでしょう。

根っこの部分では、異質な者をターゲットにするいじめの構造と、ことなかれ的に全体としての問題への対応を積極的にとってこなかった責任者の行動は、この本を読んで感じる印象と重なるところがあると思います。

震災後も福島県内に居住しているというだけで、遠く離れた人達からどう思われているんだろうなぁ、と考えない事もないわけで、そんなに遠い問題でもないというのが全体を読んでの本当にざっくりとした感想です。

勘違いしていたこと

この本の中でも繰り返し取り上げられていますが、アシュリーの両親が一連の"療法"を行なうにあたって、迷いがなかったという点については、当然葛藤があっただろうと考えていました。

実際どうだったのかはわかりませんが、少なくとも両親の行動からも、この両親が迷いなく我が子に医療的な処置を依頼していた様子が想像できます。 それは異様ではあり、その行動を当然のものとして捉えるために、その両親像について、いくつか残酷な偏見かもしれない想像をめぐらせている自分が少し嫌にはなります。

それでも世の中にはいろんな主義、主張の人がいるわけで、やはりこの両親を非難するというのは間違っている方向として考えるべきでしょう。

でも、そういう風に感じる人は少なくて、賞賛するか、非難するかの選択をするのが普通かもしれません。 ずっと昔に祖父とマインドコントロール化にある某教団の幹部インタビューをテレビでみてて、誰でもこうなる可能性があるといったら、「そんなことはない。こいつは馬鹿なのだ。」といい返されて喧嘩になりそうになった事を思い出します。

今年は生活保護の話題でも弱者の義務というか、自己責任について、報道が多くあったと思います。 生活保護については批判をかわすために、家賃の行政による直接振り込みや、食費のチケット制という話題もありました。

パチンコをやりたいなら、すればいいとは思うんですけど、そうさせないために選択肢を奪う事が成長には繋がらないと思うんですよね。かといって効果的な方法も少ないように思えます。

手を差し延べることはできても、その手を握るかどうは相手次第でしょうし、その手がどういう人の手かによって、握りたいと思うかどうかの自由ぐらいはあるはずです。

そういう答えの出ない問題に望む時には、基礎となる考え方を固めないといけないと思うんですが、そういう訓練のためにも、この本を読んで考える事で、自分の中にあるはいろいろな思いを引き出してくれると思います。

一番怖いのは、この事件を通しての一連の行動がいろいろ検討して影響を考慮した上でとられたものであればまだ救いはありそうですが、無自覚に当然のものとして新たなアシュリーが造られてしまう事でしょう。

2012/10/11

「アシュリー事件」を閲覧して

児玉真美さんが書かれた「アシュリー事件」を読みました、ではなく閲覧しました。 ちゃんと読もうと、amazonやら紀伊国屋で入手しようと予約中ですが、どこも取り寄せ状態で、出版社に在庫があってもしばらく時間がかかりそうです。

いままでの経験からは最悪、入手不可も有り得るんじゃないかなと危惧しています。

2012年10月11日 追記:
10/11の時点では、アマゾンと紀伊国屋のオンラインストアで入手可能と情報が変更されています。 無事に入手できそうです。

さて入手できないなら図書館で内容を確認しようと思いつつ、Webで串刺し検索が出来るのは非常に便利なのですが、福島県内の公立図書館では郡山女子大と福島市立飯館分館、南相馬市立の3個所にしかありません。

pandaboardが5V2Aでは安定して動かないという情報もあったので確認がてら、pandaboardとc920を車に積みつつ、飯館までドライブがてらいってきました。

ここで自分の意見を表明しておくと、こういう処置には反対で、本人の意思が確認できない状態であったとしても、生命の危機がない限り、こういう不可逆的な対応をするべきではありません。

その理由は、この本の中で引用されているいくつかのアシュリーの親に否定的な意見に含まれています。

ただ、一点だけ、私には介護の経験がないし、そのご苦労は想像する事もできません。 この文書を書くにあたり、個人を非難する気はなく、アシュリーとその家族を心からいたわりたいと思います。

しかし、この問題の構造については考えてみる事にします。

この本を読んだ理由

最近は科学の生い立ちやら疑似科学の定義を求めて哲学寄りの本を読んだりしているので、その影響もあって興味を持ちました。

でもアシュリー事件そのものについての情報を知ったのは完全に偶然で、もうよく覚えていません。 たぶん脳死による臓器移植を尊厳死に広げるとかいう、そういう話について検索していて、児玉さんのブログがひっかかったのだと思います。

そして、この子供に対して行なわれた治療なのか判然としない処置について、その効果が本当にあるのかどうかという点を確認するために本を閲覧しに行きました。

父親が肯定的に捉えている様子から効果があるのかなと思いつつ、年齢を考慮すると、訴えているような苦痛が発生するずっと前に対応しようとしている様子が異常に思えました。 「効果がないんじゃないのかなぁ…」と思い、この本で確認したいと思いました。

この本から得られる情報

著者である児玉真美さんの考えが全面に出ているはずなのに、書かれている内容は裁判官や哲学者、社会学者などの発言などを元に、様々な意見が掲載されて、バランス良くまとめられています。

調べたかった、この治療が効果的だったのか、という点については、年齢からまだ効果が不明ところがあり、また、エストロゲンの大量投与などの処置に対する否定的な意見がいくつか掲載されていました。

元々が医療上の必要から選択された理由ではありませんから、否定的な意見に説得力があるのも当然かもしれません。

これから起こるかもしれない不安に対する過剰なリアクションが、この問題を異様にし、また引き立てているのだと思います。

閲覧を終えて

この本を眺めて、私は知的障害を持つ人間に対する基本的人権や尊厳をどの観点で扱うかという事が論点だと理解しました。

論理的に説明をつけて論を展開するのは、もうすでにこの本の中で様々なものが取り上げられています。

主観的には、この障害者や両親の立場に自分の気持ちを投影して、それぞれの立場で考える事になるんだと思います。 「(本人の苦痛や気持ちが分からないのに処置をされて)かわいそう」、「(世話をする親が)つらそう」、等々、どちらの立場から考えるかによって結論は分かれる可能性が大きい話題だとは思います。

これが本人意思の表明が明確に伝われば尊重しましょう、という事になるんでしょうけれど、知的障害があるというところで、本人の意思が不明なら保護者である親の意見をまずは尊重しましょうという意見も成立しそうには思えます。

ただ通常であれば本人が成人するまで、あるいは判断能力を持つまで待ち、本人の意思を確認する事になるわけですが、それが望めない例であるわけです。

意思があるのかどうか、少なくとも現在の知見では、かなり動物的本能に近い判断能力しか持っていないと考えられる子供をどのように尊重するのか、その状態からの回復の見込みがほぼないという状況であれば、親が子を思って行なうその対応を当然だと考える人もいるでしょう。

しかし考えを進めていくと、どこかに境界があるように思えます。 人間が年齢をかさねて過去には知的な活動をしていたものの、幼児のような状態になり、高度な判断ができないと判断されるようになる人もいます。

アシュリーの事例に適用された考えを使えば、保護する者の意向が尊重されるべき事例ではないでしょうか。 もちろんアシュリーと同じ処置は必要ないですが、問題は処置の内容ではなく、QOL向上のために非医療的な処置を行なう事に説得力があるかどうか、という事になります。

こういう処置が許されるのであれば、その延長線上には、保護者というより庇護する者の意思が優先されるべきだという事になるのだと思います。

将来は延命治療の代りに尊厳死を与えてあげたりするような親切が待っているのかもしれません。 しかしアシュリーのケースは延命やQOLの向上が述べられていますから、尊厳死はいいすぎでしょう。
むしろ、その反対に徹底した延命治療が行なわれると考えるべきです。

しかし、それは良いことでしょうか?

どちらにしても人間としての扱いではないと思います。 たしかに本人の意思を察知、判断する事は超常的なテレパシー能力でもない限り難しいでしょう。

かといって、権利団体が主張するような、親ではない第三者機関が判断するような法整備が行なわれても、確認のしようがないのですから、将来の訴訟を恐れて不可逆的な対応を取る事はないと思われます。 少なくとも積極的な処置をするインセンティブは持たないと考えるのが妥当でしょう。

であれば、痛みや苦痛という状態に至った時点で医療を行なうという事になり、消極的な対応だと捉える事もできます。

しかし、意思を持った人間であれば拒否するかもしれないような過剰な処置を行なうべきでしょうか。 状況が違うというかもしれませんが、それでも現時点では必要がない行為を行なう事に正当性はあるでしょうか。

この本を読んで感じた事は、必要性の証明がおそらくできない行為を行なった事。それは人体実験に近い行為であったこと。医師たちに患者本人を尊重する気持ちがなかったこと。 そして、そういう行為が必要だと考えつくほどに家族が疲弊している現実です。

この本にありますが、家族たちの継続的なケアと本人が家族を失なった後もケアを受けられるという希望を持てる社会を望むべきで、実現のために動くべきなのだと思います。

脳は自分の行為を論理的に整合性を取るように働きます。 場合によってはしてしまった自分の人格と行為の間のギャップを埋めるために、いろんな記憶や感情を捏造します。 この状態であれば家族は行為について論理的に閉じるように、第三者からは容認できないような内容だとしても、理屈を考えるでしょう。

別にIT企業幹部でなくても、自身が生きている間に我が子の将来が保障されない現実を変えられないと悟れば、お手軽な一連の行為を思いついて、実現に全力を注ぐのも理解はできます。

しかし医師たちは家族に流されずに客観的に行動するべきでした。 徹底して患者本人に寄り添って尊重するという原則がこの医師たちにあれば、自分たちの判断に余るこの申し立てについて、裁判所への確認が行なわれただろうと思います。 イギリスの事例はアメリカで認められてしまった(かのようにみえる)事例のため、将来の訴えを恐れて事態が進展したのだろうと思います。

徹底的に非難されるべきはこの医師たちのみでしょう。 それでも自死については、それを選択した理由は分かりませんが、残念な事だと思います。

根源的な性質を持つこの問題は、哲学的な人たちの好奇心をかきたてるでしょう。 しかし一般の人達は、その胸の中に生まれた感情をうまく整理する事ができずに、様々なリアクションを行なうのだと思います。

本質的に解決するべきは、どんな状態で生まれて、どんな状態になっても、人間らしくケアされるだろうという希望のある社会を実現することなのだと悟り、そして絶望して、希望を失いそうになります。

2012/10/10

Ubuntu 12.04 LTS (precious)にVMWare CLIを導入してみる

空いているPCにIntel NICを追加して、VMWare vSphere Hypervisor (ESXi)を導入したので、手元のクライアントから操作できるようにコマンドラインクライアント(vCLI)を導入しました。

ちょっとした問題があったので、まとめておく事にします。

インストール手順

CLIのインストール手順はマニュアルのにあります。 必要な前提パッケージを導入すれば、$ sudo vmware-vsphere-cli-distrib/vmware-install.plを実行するだけなのですが、次のようなエラーメッセージが表示されました。

導入時のエラーメッセージ
...
Thank you.

http_proxy not set. please set environment variable 'http_proxy' e.g. export
http_proxy=http://myproxy.mydomain.com:0000 .

ftp_proxy not set. please set environment variable 'ftp_proxy' e.g. export
ftp_proxy=http://myproxy.mydomain.com:0000 .

$ 

正常終了したのかと思いましたが、マニュアルにはコマンドを配置するパス(デフォルト/usr/bin)を指定する段取りがあるはずで、案の定esxcliコマンドは導入されていませんでした。

スクリプトが途中で終了する理由

どういうわけか、プロキシー設定("export http_proxy=..." or "export ftp_proxy=...")を行なわないとスクリプトが終了する作りになっています。

vmware-vsphere-cli-distrib/vmware-install.plの該当個所の抜粋

...
      my $httpproxy =0;
      my $ftpproxy =0;

      if ( direct_command("env | grep -i http_proxy") ) {
         $httpproxy = 1;
      } else {
         print wrap("http_proxy not set. please set environment variable 'http_proxy' e.g. export ht
tp_proxy=http://myproxy.mydomain.com:0000 . \n\n", 0);
      }
      if ( direct_command("env | grep -i ftp_proxy") ) {
         $ftpproxy = 1;
      } else {
         print wrap("ftp_proxy not set. please set environment variable 'ftp_proxy' e.g. export ftp_
proxy=http://myproxy.mydomain.com:0000 . \n\n", 0);
      }

      if ( !( $ftpproxy && $httpproxy)) {
         uninstall_file($gInstallerMainDB);
         exit 1;
      }
...

プロキシーがなくとも外部ネットワークにアクセスできる環境であれば、この評価式全体をコメントアウトしてしまうのがお勧めです。最後のif文の評価式全体をコメントアウトしてあげると、プロキシーを設定することなしに導入する事ができます。

正常終了した時のメッセージ

最終的にインストールに成功した時のメッセージの最後の方は、次のようになっていました。

...

Please wait while configuring perl modules using CPAN ...

CPAN is downloading and installing pre-requisite Perl module "Archive::Zip" .

CPAN is downloading and installing pre-requisite Perl module
"Class::MethodMaker" .

CPAN is downloading and installing pre-requisite Perl module "SOAP::Lite" .

In which directory do you want to install the executable files?
[/usr/bin]

Please wait while copying vSphere CLI files...

The installation of vSphere CLI 5.1.0 build-780721 for Linux completed
successfully. You can decide to remove this software from your system at any
time by invoking the following command:
"/usr/bin/vmware-uninstall-vSphere-CLI.pl".

This installer has successfully installed both vSphere CLI and the vSphere SDK
for Perl.

The following Perl modules were found on the system but may be too old to work
with vSphere CLI:

UUID 0.03 or newer

Enjoy, 

--the VMware team

正式にサポートされているUbuntuは10.04なので、12.04 LTSでは少し前提となるパッケージが違うようですが、とりあえずは動いています。

何か不都合があるのかは、これから使ってみて確認していきたいと思います。

2012/10/09

シリアルから扱えるよう、Pandaboardのgettyを有効にしてみた

前回まででPandaBoardが起動するようにはなったのですが、シリアルの通信は途絶えてしまいシェルが起動するという事にはなりませんでした。

HDMIは使わないので、サーバーとして扱えるようにネットワークとシリアルを有効にするところまでです。

環境

ベースにしているrootfsは前回と同様にL24.9-PandaBoard_validation_environment.tar.gzです。

MLOとu-boot.imgをgitから準備をして起動するようにはなりました。

現状

で、起動はするものの、runlevelを聞いてきたところで数字は打つものの処理が止まってしまいます。

runleveの入力後に処理が停止する様子


...
Enter runlevel: 2
INIT: Entering runlevel: 2
INIT: no more processes left in this runlevel
...

まぁgettyを起動させれば良いのでしょうと、いうわけでSDカードをUbuntu 12.04 LTSに差し、認識された/dev/sdd2/mnt/mmc2にマウントして、/mnt/mmc2/etc/inittabファイルを編集したりしました。

ここら辺の強調したデバイス名やらは環境に依存して変化するので読み替えて下さい。

/etc/inittabを変更して、ちょっとだけ改善

ちょっとだけ進んだところ


...
Enter runlevel: 2
INIT: Entering runlevel: 2

.-------.                                           
|       |                  .-.                      
|   |   |-----.-----.-----.| |   .----..-----.-----.
|       |     | __  |  ---'| '--.|  .-'|     |     |
|   |   |  |  |     |---  ||  --'|  |  |  '  | | | |
'---'---'--'--'--.  |-----''----''--'  '-----'-'-'-'
                -'  |
                '---'

The Angstrom Distribution (none) ttyO2

Angstrom 2010.4-test-20100406 (none) ttyO2

(none) login: root
Login incorrect

よくよくみると、いろいろマニュアルに問題があるようなので、そこら辺をまとめておきます。

inittabファイルの書式について

Minimal-FSの/etc/inittabは次のようになっていました。

null::sysinit:/bin/mount -t proc proc /proc
null::sysinit:/bin/mount -t sysfs sysfs /sys
null::sysinit:/bin/mount -t usbfs usbfs /proc/bus/usb
null::sysinit:/bin/mount -o remount,rw /
null::sysinit:/etc/init.d/udev

ttyO2::respawn:/bin/sh

ここで最後の行でtty02tty2のように数字を除いて指定する必要がありました。

ここを修正すると起動後にrunlevelを入力させた後にシェルが起動します。

まぁMinimal-FSはapt-getもないので、本当にどうしようもないのですが、とりあえずこれでrootでログインする事が可能になります。

別の文書ではboot.scrでカーネルパラメータを指定するような指定もありましたが、デフォルトのkernelパラメータは次のようになっています。

kernelパラメータ

Kernel command line: console=ttyO2,115200n8 vram=16M root=/dev/mmcblk0p2 rw rootfstype=ext3 rootwait

もしこのパラメータを変更する必要があれば、mkimageコマンドを使ってboot.scrファイルを生成します。 今回は試したものの必要ないので、boot.scrファイルは使っていません。

FAQによれば、コマンドラインは次のようになっています。

http://omappedia.org/wiki/PandaBoard_FAQより抜粋


Step-1: create a boot.scr.txt like:
fatload mmc 0 0x80300000 uImage
echo Booting from mmc0 ...
setenv bootargs console=ttyO2,115200n8 noinitrd init=/sbin/init root=/dev/mmcblk0p2 rootwait rw loglevel=8
bootm 80300000

Step-2: run:
mkimage -A arm -T script -O linux -C none -a 0 -e 0 -n "boot.scr" -d boot.scr.txt boot.scr

mkimageコマンドは手元のUbuntu 12.04 LTS上で実行していますが、 ここら辺はuboot-mkimage-0.4当りをキーワードに検索すれば関連する情報が探せるかと思います。

さいごに

rootでログインができたので、必要そうな情報をコピーしておきます。

ネットワークカード
# ip addr
1: lo: <LOOPBACK> mtu 16436 qdisc noop 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: usb0: <BROADCAST,MULTICAST> mtu 1492 qdisc noop qlen 1000
    link/ether 22:17:88:b7:fc:59 brd ff:ff:ff:ff:ff:ff
/proc/cpuinfo

この情報をみるとOMAP4460としては認識されていないのかなと思えます。 あとでちゃんとしたkernelを使って検証することにしましょう。

# cat /proc/cpuinfo 
Processor       : ARMv7 Processor rev 10 (v7l)
processor       : 0
BogoMIPS        : 1396.94

processor       : 1
BogoMIPS        : 1363.33

Features        : swp half thumb fastmult vfp edsp thumbee neon vfpv3 
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x2
CPU part        : 0xc09
CPU revision    : 10

Hardware        : OMAP4430 Panda Board
Revision        : 0020
Serial          : 0000000000000000

さいごに

ここら辺でMinimal-FSは止めて、Ubuntu 12.04 (precise) を動作させてみようと思います。

Ubuntu 12.04 LTSでPandaBoard ES用のu-boot/MLOイメージを作成してみた

Pandaboard ESを入手したのですが、どうも配布されているu-boot.img/MLO/uImageではうまく起動させることができませんでした。

手順は公開されているので、Ubuntu 12.04 LTSをホストにしてクロスコンパイル環境を使ってARMEL用のバイナリを作成してみました。

環境

使用している機材などは次のようになっています。

  • 対象: PandaBoard ES Rev.B1
  • ホストOS: Ubuntu 12.04 LTS 64bit版
  • シリアルケーブル: Arvel SRC06-USB (FTDIチップ使用)
  • SDカード: TOSHIBA製 Class6 SDHC 4GB (いわゆる白東芝カード)
  • rootfsイメージ等: L24.9-PandaBoard_validation_environment.tar.gz
  • 差し替え用MLO/u-boot.imgファイル: origin/Linaro-u-boot-2012.04.2

基本的なインストールの流れ

本家からセットアップのインストラクションを探して、Linux Minimum (Pandaboard Minimal-FS)に辿り着きました。

L24.9-PandaBoard_validation_environment.tar.gzはここで入手できたのですが、X-Loaderはhangしてしまいました。

PandaBoard ES uboot howtoという文書に従ったのですが、少しだけ修正する必要がありました。

$ mkdir pandaboard-es
$ cd pandaboard-es
$ git clone git://git.linaro.org/boot/u-boot-linaro-stable.git
$ cd u-boot-linaro-stable
$ git checkout -b pandaboard-es origin/Linaro-u-boot-2012.04.2
$ export CROSS_COMPILE=arm-linux-gnueabi-
$ make omap4_panda_config
$ make

変更したのは、2011.12のブランチを取得するようになっていたところを最新の2012.04に変更し、CROSS_COMPILE環境変数に指定する文字列から-noneを削除しました。

これをしない場合に、makeが正常に終了しない問題が発生しています。

ARM用gccをUbuntu 12.04 LTSに導入する

手元のUbuntu 12.04 LTSにarm用のgcc環境を構築するには、次のコマンドを実行します。

$ sudo apt-get install gcc-arm-linux-gnueabi

arm用のgcc-4.6が導入されています。 これで、コンパイルに必要なものはほぼ揃うはずです。

成果物の場所

目立ちませんが、$ makeを実行したカレントディレクトリに必要なファイルが作成されています。

  • MLO
  • u-boot.img

この2つのファイルをSDカード上に作成したFAT32領域に書き込めば、カードをPandaboardに移してテストです。

そういえば、配布されているイメージでは、u-boot.imgではなく、u-boot.binが入っていたんですよね。

どっちにしろMLOが見つからないらしく、X-Loader 1.41がエラーを出すので、u-bootまで処理が進んでいないと思われるので、関係ありませんが…。

確認に必要な環境

HDMIで液晶ディスプレイなどに出力をするにしても、まずはシリアル経由で接続しないとX-Loaderやら起動時の画面出力やらが分かりません。

Linux上で動作するUSBシリアルケーブルは内部にFTDIのチップを積んでいるものがお勧めです。

pandaboardのシリアルに接続する場合の、kermitの設定

次の設定を~/.kermrcに入れていて、kermit起動後にC-Kermit> connectとタイプして問題なく動作しています。

Ubuntu 12.04 LTS上の~/.kermrcファイルの全体

set port /dev/ttyUSB0
set speed 115200
set carrier-watch off

手元のPandaboardからの出力は、こんな感じになっています。

起動時のコンソール出力の抜粋

U-Boot SPL 2012.04.01 (Oct 09 2012 - 13:49:33)
OMAP4460 ES1.1
OMAP SD/MMC: 0
reading u-boot.img
reading u-boot.img

U-Boot 2012.04.01 (Oct 09 2012 - 13:49:33)

CPU  : OMAP4460 ES1.1
Board: OMAP4 Panda
I2C:   ready
DRAM:  1 GiB
MMC:   OMAP SD/MMC: 0
Using default environment

In:    serial
Out:   serial
Err:   serial
Net:   No ethernet found.
checking for preEnv.txt
reading preEnv.txt

** Unable to read "preEnv.txt" from mmc 0:1 **
Hit any key to stop autoboot:  0
reading uEnv.txt

** Unable to read "uEnv.txt" from mmc 0:1 **
reading boot.scr

** Unable to read "boot.scr" from mmc 0:1 **
reading uImage

2665748 bytes read
Booting from mmc0 ...
## Booting kernel from Legacy Image at 82000000 ...
   Image Name:   Linux-2.6.35-g6d019da-dirty
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2665684 Bytes = 2.5 MiB
   Load Address: 80008000
   Entry Point:  80008000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK
OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
Linux version 2.6.35-g6d019da-dirty (danders@ccd-dev) (gcc version 4.3.3 (GCC) ) #15 SMP PREEMPT Wed Sep 8 15:33:37 CDT 2010
CPU: ARMv7 Processor [412fc09a] revision 10 (ARMv7), cr=10c53c7f
CPU: VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
Machine: OMAP4430 Panda Board
Memory policy: ECC disabled, Data cache writealloc
OMAP4430 ES2.0
....

さいごに

まだgettyが最後に起動しないので、設定としてはいろいろ足りていないのですが、とりあえず起動するようにはなりました。

ロボットとか作っている人達をテレビでみるとこのカードを積んでたりしますよね。 サーボみたいに電流を流すものは扱わないのですが、ホームセンターなんかでバイク用の小型12Vバッテリーを眺めると、いろいろ夢は広がります。

まぁ12Vを安定的に得るのと充電するので、いろいろ大変そうですけどね…。

それでも携帯電話向けにソーラーパネルが付いたリチウム電池は普通に売っているので、そのままでは実用的に使えないでしょうけど、そんなに手間をかけなくてもモバイルでは運用できるのかな…。

2012/10/07

Ubuntu 12.04 (precious) amd64版にvCLIを導入しようとして、libtiff4関連のエラーに逢う

VMWare ESXi (VMWare vSphere Hypervisor 5.1)を導入しているマシンにリモートからアクセスするために、VMware-vSphere-CLIをダウンロードし、導入しようとしました。

導入方法はマニュアルのInstalling the vCLI Package on a Linux System with Internet Accessにあるのですが、ia32-libsを導入しようとしてエラーになってしまいました。

$ sudo apt-get -f install
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
依存関係を解決しています ... 完了
以下の特別パッケージがインストールされます:   
  libtiff4:i386
以下のパッケージが新たにインストールされます: 
  libtiff4:i386
アップグレード: 0 個、新規インストール: 1 個、削除: 0 個、保留: 0 個。
226 個のパッケージが完全にインストールまたは削除されていません。
142 kB 中 0 B のアーカイブを取得する必要があります。
この操作後に追加で 501 kB のディスク容量が消費されます。
続行しますか [Y/n]?
(データベースを読み込んでいます ... 現在 560449 個のファイルとディレクトリがインストールされています。)
(.../libtiff4_3.9.5-2ubuntu1.2_i386.deb から) libtiff4:i386 を展開しています...
dpkg: /var/cache/apt/archives/libtiff4_3.9.5-2ubuntu1.2_i386.deb の処理中にエラーが発生しました (--unpack):
 './usr/share/doc/libtiff4/README' is different from the same file on the system
dpkg-deb: error: subprocess ペースト was killed by signal (Broken pipe)
以下のパッケージの処理中にエラーが発生しました:
 /var/cache/apt/archives/libtiff4_3.9.5-2ubuntu1.2_i386.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)

解決方法はあっさりしたものだったのですが、不思議な現象に思えたのでメモを残す事にしました。

まずは対処方法から

前述のエラーへの対応方法は、とりあえずlaunchpadで、tiffを検索し、amd64版のlibtiff4パッケージをダウンロードして、手動で導入します。

$ sudo dpkg -i libtiff4_3.9.5-2ubuntu1.2_amd64.deb

続いてエラー原因を解消します。

$ sudo apt-get -f install

なんというか不思議なのですが、これで32bit版のlibtiff4:i386が導入され、対応は完了です。

原因について

結局、原因については不明です。

解決方法は、Ubuntu Forumに記述がありました。

この手の解決策は以前にもあったと思いますが、Ubuntu 12.04にアップグレードした際に何か問題があったのだと思います。

Ubuntu 12.04 amd64版をクリーンインストールした場合には問題はないだろうと思うのですが、エラーメッセージからは32bit版と64bit版で、READMEファイルの配置場所が重複している事が原因だとは思いながらも、どうすれば良いのか分からずしばらく悩んでしまいました。

これで本題のVMWare ESXi 5.1用のCLIが導入できますが、それはそれで問題があったので、別の記事にまとめる予定です。

2012/09/22

平成16年製デミオについて、2012年4月の車検から今月(2012年9月に)までにした こと

いろいろあって最近はブログの更新もいまいちだったので、4月に受けた車検から、今月、2012年9月、に交換した部品やら、その感想なんかを書いてみる事にしました。

別に特別な事をしたわけでもなくて、基本的にはオートバックスで購入したものを、そこのピットで取り付けてもらっています。そのため、オートバックスへの礼賛記事みたいになっているかもしれませんが、そんな気はありません。

かといって、事実を書いた部分が、多少批判的な印象を与えてしまうかもしれませんが、サービスや作業内容に問題があるとは思っておらず、他意はありませんのでご了承ください。

スペック

車の概要は次の通りです。

  • 形式:UA-DY3R
  • 購入年月:2008年4月 (ただし中古車として)
  • 登録年:2004年 (平成16年)
  • 現在までの走行距離:約9万4.3千キロ

中古車ですがディーラーの直営店で購入した事もあって、必要な部品の交換なんかは最初にいろいろやっていて、全体的には問題はなくてとても満足しています。

2012年4月:車検

いままでディーラーで受けていた車検ですが、いろんな状況から、今回始めてオートバックスでやってもらう事にしました。

見積り時の内容でやってもらったので、2010年にディーラーで車検を受けた時と比べて、だいたい半額以下ぐらいの値段になりました。

その代りブレーキ液やエアコンフィルターなんかも変えていないので、それなりに問題を抱えてはいます。

引き渡しの段階で、ブレーキ液やパワステ液の交換なんかを勧めてきて断わったのですが、車検の時にすれば手間が省けるだろうにと思った事を覚えています。

渡された書類にある、後で交換する事になるバッテリーやタイヤの溝なんかのデータは、次のようになっています。

  • 走行距離:約8万9.0千キロ
  • タイヤ溝の深さ
    • 前輪(左、右):(3.0, 2.9)[mm]
    • 後輪(左、右):(3.8, 3.5)[mm]
  • バッテリー診断結果
    • 容量:79%
    • 電圧:12.9V
  • 交換したオイル:マックスファクトリー SM0W20

夏休みの時期などは遠出をしたりした経緯もあって、若干走っていますが、だいたい一ヶ月毎に1,000kmぐらいづつ走っています。

車検から3ヶ月ほど経って、既に3,500kmほど走っていた事もあって、アクセルを踏んでも加速が悪く、坂道を上る時にはかなり大変な多いを感じるようになりました。

2012年9月:オイル交換 + 車検後の無料点検

このまま半年経過するまで待てなかったので、少し暑さがやわらいできた頃に無料点検のハガキが届いた事もあって、ついでにエンジンオイルを交換をする事に決めました。

普段は値段的に安い部分合成油で、オートバックスのPBオイル(Vintage 0W20)を入れていますが、 今回は同じ値段でセール対象になっていた Castrol の Magnatec 0W20 に交換しました。

交換してからは、夏の暑さが続く日でしたが、以前とは見違えるほど、エンジンが回転してダイレクトに前に進む感じが得られる印象です。 まぁエンジンオイルを変更するといつも感じる事ではありますが、これがどれくらい続くのかなぁ、と思っています。 Magnatec自体はいつもと同じ部分合成油なので、3,000km走った時にどんな感じか確認しようと思います。

結果として、特にエンジンに問題があるわけでもなく、車検の時に自動的に交換されたMax Factoryエンジンオイルの劣化の度合いがあまりにもひどかったという事になるんですが、3,000km走った後の印象が良ければ、次はPBオイルではなくて、5千円出しても全合成油系のオイルにしようかなと思います。

さて、このエンジンオイルの交換時に、改めてタイヤとパワステ液とバッテリーの交換を勧められました。 パワステの動きに問題は感じていなかったのと、バッテリーは75%, 12.9Vという事だったので、ここはスルーしました。

タイヤはスリップマーク(1.6mm)が出ていたので、さすがにやばいなぁ、という事で他のお店も周って交換する事に決めました。

ただ、車検から半年、3,5000キロ走って、1.5mmも削れたのか、ちょっと疑問ではありますが、 タイヤ自体が劣化していたはずで、むしろよくバーストしなかったと思います。

2012年9月:タイヤの交換

せっぱつまった状況でしたが、1週間ほど後に再びオートバックスのお世話になりました。 PBタイヤにしたい旨を店員に伝えると、扁平率55%のタイヤはありませんよと即答されましたが、価格表のファイルを見ながら、韓国製タイヤの次にPBタイヤをあたかも先ほどの会話がなかったかのように勧められました。

ちなみに、このデミオに適合するタイヤは二種類あります。

  • 175/65R14
  • 185/55R15

手持ちのタイヤは両方あって、14インチは買った時におまけで付けてもらったスタッドレスにアルミホイール、15インチは購入した時のまま純正アルミホイールに夏タイヤ、として使っています。

今回は15インチの方のタイヤを交換する事にしました。タイヤ舘などもいったのですが、目当てだったSNEAKERがモデルチェンジ前らしく生産中止かつ在庫なし、で残念でした。値段的には購入したオートバックスのPBタイヤとそれほど違わず問題なかったんですけどね。

そんなこんなで、在庫があった事もあって、オートバックスのPBタイヤ(MAXGRADE SIII)にしました。 いままでが悪すぎたため、新品だけあってびっくりするくらいに、取り回しが楽になりました。

以前は、カーブを曲る時にハンドルの戻りがつっかかるように感じたり、ロードノイズをじかに感じていましたが、タイヤを交換してからは、カーブを曲った時にハンドルから手を離すとスルスルと戻るし、静かという印象はないですけれど、エコタイヤというよりはコンフォートタイプといっているだけの事はあって、乗り心地はかなり改善されました。

直進性が増したとは感じませんし、タイヤの経年劣化がどれくらいのスピードで起るのか分かりませんが、想像以上に良くなっていると感じています。

この交換後に片道40〜70kmほどを合計400kmほど走りましたが、いままで良くて13km/lぐらいだった燃費が17km/lになり、オイル交換の直後と比べてもタイヤの交換が大きく寄与した結果だと思っています。

2012年9月:バッテリーの交換

マニュアルによると、UA-DY3Rに適合は46B24Lです。

交換前に使っていたものは2009年5月に、やはりオートバックスで購入しています。 オートバックスで46B24LというとPBの中でも水色の一番安いもので、バッテリー補充液のメンテナンスが必要なモデルです。

4万キロ/2年保障の製品を、3年半ぐらい使っていたわけですが、硫酸銅の結晶がマイナスターミナルに付着していて、4月に79%, 9月に75%となっていた事もあって、真冬に70%を切るのは自殺行為に思えたので交換する事にしました。

メンテナンスしながら短いサイクルでバッテリーを交換すればトータルでのコストは下がりそうですが、 自分には向かない事がよく分かったので、今回はメンテナンスフリーバッテリーが候補です。

55B24Lにしようかなと思っていたのですが、10%引きになる事もあって、65B24Lにしました。 どうせ4年もすれば交換とは思っているので、どっちでも良かったのですが、違いが何か実感できるかなぁぐらいの期待を込めています。

オートバックスで作業してもらった時に、時計やらガソリン交換してからのトリップメーターやらのメモリが消えてしまったのですが、まぁすぐに自分で戻せるし、前の値もだいたい覚えているので、気にしません。

ただ「影響は時計だけですが、すみません。」、と謝られただけで、何かダメージを与えるような事をしたとは説明されていませんが、 どうやってバッテリー交換時にメモリ内容を消したのか、けっこう気になったりしてます。

結晶を落す時に端子に繋っていた線が外れてしまったのかなぁ。

バッテリーを交換して音が良くなるものとは思いませんが、ヘッドライトは確実に明るくなったし、時計の時刻が狂う現象も軽減されるといいなぁというところです。

さいごに

オートバックスのPBエンジンオイルは、いまの時期はネットショップサイトから消えていて、店頭でも在庫らしきものはありましたけれど、山のようには積まれていませんでした。

また、PBバッテリーは、ブランド立ち上げ当初はパナソニックのOEMだった記述がありますが、交換したものはBOSCHのOEMでした。 ひょっとしたら容量別で混在しているのかもしれませんが、よく分かりません。

始めてディーラー以外で車検を受けましたが、中古車とはいえやっぱり定期点検と車検はディーラーで受けたいなぁというのが現時点での感想です。

自分で作業をするようになったわけではありませんが、今回はいろいろと勉強する機会になりました。

2012/09/03

BIND9 (named) が大量の"tmp-*"ファイルを掃き出した理由 - DNSSEC

気がついたら自分で管理しているDNSサーバーの/etc/bindにtmp-で始まるファイルが大量に掃き出されていました。

...
-rw-r--r--  1 bind bind  5267 Sep  3 08:35 tmp-0r4ItfPTMx
-rw-r--r--  1 bind bind  5267 Sep  3 08:47 tmp-s8Wik7LX69
-rw-r--r--  1 bind bind  5267 Sep  3 09:01 tmp-az3Ek2NMn7
...

結論:対応方法

DDNSやMaster/Slave構成などで.jnlファイルを使用しているBINDプロセスは定期的にジャーナルファイルの内容を書き出すので、zoneセクションでfileに指定しているファイルにも書き込み権限が必要になります。

解決策は簡単で、.jnlファイルとそれに対応するファイルの両方について、namedを実行しているbindユーザーの所有にすればエラーはなくなります。

変更後しばらく観察していると、tmp-*が作成される代りにzoneファイルが更新される事が分かるはずです。

本題:原因について

どうしてこういう事が発生したのかが問題です。 サーバーを構築した時は正しく権限を設定していて、動作も確認していました。

ここからの大前提として設定ファイルを格納している/etc/bindディレクトリは、root:bindの所有でtビットが立っています。

$ ls -ld /etc/bind
drwxrwsr-t 2 root bind 20480 Sep  3 11:59 /etc/bind

この設定によってnamedプロセスが上書きして欲くないファイルはroot:bindの所有として保護しています。 また動的に生成するファイルはbind:bindの所有となります。

DNSSEC固有の事情

zoneファイルの権限が変更された原因は、DNSSECを有効にしていたことに起因します。

エントリや鍵ファイルの更新のため定期的にzonesignerコマンドを実行していたのですが、 ここに少しばかり問題がありました。

操作の対象となるのは次の3つのファイルです。

対象ファイル

-rw-r----- 1 root bind  900 Sep  3 11:59 db.yadiary.net
-rw-r--r-- 1 bind bind 9731 Sep  3 11:59 db.yadiary.net.signed
-rw-r--r-- 1 bind bind 3489 Aug 30 05:23 db.yadiary.net.signed.jnl

db.yadiary.netは署名前のオリジナルファイルで、勝手に上書きされても困るので、rootの所有となっています。 この状態でzonesignerを実行すると次のようにパーミッションが変化します。

zonesigner実行後

-rw-r--r-- 1 root bind 9731 Sep  3 11:59 db.yadiary.net.signed

そうしたらsudoをbindユーザーで実行したらどうなるのでしょう。

sudo -u bind zonesigner -zone yadiary.net db.yadiary.net

zonesigner実行時のエラー

unable to open zone file db.yadiary.net at /usr/sbin/zonesigner line 841, <KEYREC> line 73.

namedが乗っ取られてコードを実行された場合を考えれば、DNSSECの署名に必要な鍵ファイルはbindユーザーに見られたくありません。 というわけでbindユーザーでは署名に必要なファイルが見つからないのでエラーとなって、これに直接対応する事はやめました。

とりあえずの対応策

zonesignerを実行するときのコマンドラインのメモの最後に、; chown bind db.yadiary.net.signedを加えました。

でも全体としてバランスが悪いので、他の解決策が用意されていないか探してみようと考えています。

まとめ

いろいろ調べる途中でみた設定例によると、/etc/bindディレクトリにスティッキービット(t)を立てずに紹介しているところもありました。

ファイルのセキュリティについては、chroot環境について触れているものもありました。 しかし、DNSサーバーとして不適切なエントリの追加を防止するためには、chrootだけでは十分ではありません。

namedのファイルパーミッションはいろいろ悩ましいところではあるので、少し試行錯誤してみたいと思います。

2012/08/16

さようならPS3 Linux。

いろいろ思うところがあったけれど、Playstaion 3のファームウェアを3.15から最新版の4.21にする事にしました。

まぁ普通の人なら当然するだけの事をしたんですが、これでHDDの中で10GBほどの領域を占有しているLinux領域にアクセスできなくなるわけです。

ときどき使っていたけれど、本気で使っていたわけじゃありません。 これからCellのプログラミングをする事もないだろうから、Other OSのサポートがなくなるのはしかたがなく受け入れる事にしました。

べつにこれで何か経済的に損失があるというわけでもないですし、ダウングレードしないといろいろできないのは納得したわけじゃないけれど、得られるメリットとのトレードオフなわけで、いま頃になってようやく分岐点を越えて決断に至った次第です。

まぁ自分に非がないのに当時の社長御自身がセールスポイントとしていた機能が削られた分のお金は返金して欲しいなぁとは思います。

2012/08/11

つめこみ教育からゆとり教育への転換で変わらなければいけなかったこと

いわゆる「ゆとり教育」は「つめこみ教育」からの反動として生まれたといわれています。 最近は多少の反省もあって学力低下を憂いて教科の内容は見直しが進められているらしい。

確かに、つめこみ教育自体には反対だけれど、それは落ちこぼれた場合の救済策がほとんどない事と、 学習塾や家庭教師などの学習環境による経済格差が学力に反映される可能性があるからです。

結論からいえば、正社員を20才前後で買って65才で退職金を付けてリリースするという制度を止めて、人材の流動性を高める事が必要だと考えています。そのためには労働者を解雇しやすくする仕組みがあって、その反面、労働者はより頻繁に雇用されて能力を示す機会を与えられる仕組みの構築が行なわれるべきだ、という内容になっています。

ゆとり教育でかわったこと

つめこみ教育は、6〜18才の期間限定でのスキル(知識・能力)獲得ゲーム(猶予期間付き)といえると思います。

最近は、経済力がある家庭は無駄にゲーム機を与えたり、子供を甘えさせたりする場合もあって、必ずしも環境の中で優位とはいえないし、教科の内容が簡単になれば、それなりに要求されるハードルが下がって子供の負担は軽減さえるかもしれません。

しかし、その本質を変えないままにゲームのルールを緩めてしまうと、その枠内でチート的行為を行なおうとするのは当然の帰結に思えます。 ルールがキツすぎるのが問題で、柔軟性を欠いたことでいろいろな問題を起した社会の反省が、ゆとり教育であったはずです。

ゆとり教育は「教科の時間・内容を減らし、経験重視型の教育方針」への転換だといわれています。 なにを経験させたいのかさっぱり分かりませんが、現実にはよりよい経験ができる学校の人気が出るといった学校間格差を生んだだけのように思えます。

この期間、日本の社会では正社員につけない人間は非正規雇用という位置付けを固定的に与えられる結果となり、よりおちこぼれは救済されない社会へと変貌を遂げました。

ゆとり教育においても、18才までにどれいくらいのスキルを身につけたかで判断がなされ、おちこぼれを救済するという結果にはつながっていないと思われます。

強いていうなら、ハードルが下がった事によって「(やらないけど)やればできるはず」と思い込む事が、より現実的になった、とはいえるのかもしれません。 「(やらないけど)やればできるはず」と思い込めれば、将来を悲観する事はなくなるのかもしれません。

社会で必要なのは理想と現実とのギャップを埋める能力

社会で働くというと、ルーチンワークで成り立つ単純労働もありますが、普通はそうやって作ったものを売る方法から考えなければいけないので、どんな仕事でも「現在達成できていない事」を「どうにかして達成させる能力」が求められる事になります。「空のケースがある状態」から「製品でケースが埋まった状態にする能力」ぐらいに考えれば、納得できるでしょうか。

就職活動というものは、「職がない状態」から「どうにかして職を得る能力」を示すものといえるかもしれません。

つまり、課題解決が基本的な仕事の単位と考えます。

以前は課題を解決するために「知っている人に聞けばいい」という状況が一般だったとすれば、いわゆる人脈が課題を解決する能力に等しかった時代もあったのかもしれません。

いまの社会は、いろいろ複雑で、とくにIT系では「課題を作って解決する能力」がないと、どんなにプログラミングが上手でも、他人の作ったライブラリの範囲から逃れる事ができなくて、その一生を下働きで終る事になるかもしれません。

プログラマーですがPHP以外の言語では仕事ができません、とかっていう信じられない状態が普通にあったりするわけです。

いままで書いてきたことは、環境要因もあるので、一概にその個人の能力のみを表現しているわけでもありませんが、それついて考慮するのは、ここの目的ではありません。

とにかく、社会で求められている能力というものは、18才までに習得するはずのスキルとは直接的には関係がないように思えるわけです。

つめこみ教育からの脱却で目指すべきだった社会の方向性

理想を「頑張った人が報われる」社会だとした場合に、一度はドロップアウトしても、後から十分なスキルを習得すれば、就職口があるようなケースが良いとされています。

これを勘違いして努力しなくても仕事がある状態が良いと思って、低賃金かつ単純労働な仕事をやたら誘致する自治体があったりするわけですが、そんな仕事は中国や東南アジアに移ってしまう

つまり常にその地域の特色を活かす必要があるんですが、そういう特色のある仕事をサポートするために、周辺に、単純労働的な仕事が存在するはずなのです。

核となる要素を作らずに、本来、その周辺にあるべきものを作っても、根付かずに終るのは目に見えて明かです。

ゆとり教育が本来目指すべきだったのは、教科の内容を減らす事自体が悪いとは思いませんが、課題を解決する能力の育成や、一度は落ちこぼれても救済可能な環境だと思います。

おちこぼれた人は、会社が準備した6畳一間のワンルームアパートに入って、毎日工場のどこかでその日限りの仕事をするような人材派遣会社に流れたりするわけで、中国や東南アジアからの勤勉な労働者に置き換えられる将来を憂う事になる可能性があります。

そういう最終的な出口に恐怖を感じるとすれば、つめこみ教育時代と何も変わっていないわけで、解決するべき問題は少なくとも教科内容の削減ではなかったと思います。そこは重要ではない。

人生を60年ぐらいのスパンで捉えて、各段階で一度はドロップアウトした人をどうやって再教育するのか、そういう意欲をどうやって持たせるのかが重要なはずです。

これは学校だけで解決するものでもないけれど、18才までの能力で判断することから、どんな年代、段階からでも社会参加できるような仕組みが一番良いもののはずです。

柔軟性を欠いたままの社会構造

一度、正社員として雇用されるとキャリアアップを除いて、なかなか会社を辞めるという事ができない環境があります。 また、基本的に会社は(正当な理由のハードルが高いため)リストラができず、お金を積んだり、単純に窓のない部屋に移動させるとかいう手法を使って、人員の整理を図る事になります。

何かがおかしいんですが、経済が好調な時代には表面化しなかっただけの矛盾を、「これで成功してきた」という間違った成功体験で正当化してしまう事象が発生しています。

ちなみに、主観的な体験を否定はしませんが、人間は脳の構造から、関連のない事象を結びつけて理解したり、本来みえていないものや聞いていないものを体験したと認識できる能力を持っていることもまた事実です。

話を戻すと、労働者の流動性と市場を作っていく事が肝要ではないでしょうか。

労働者も賃金が与えられる(べき)ものと思っているところがあるので、お互い様ですが、陰湿ないじめなしに解雇された方がすっきりするし、会社に20才からずっといる社員で占められる事がなくなれば、本来いうべき事をいう事もできるでしょう。

ただ現状を一気に解決する方法はないので、難しいのですが、少なくとも目指すべき方向性は政治家が示して、法律などのサポートを行なうべきです。

ゆとり教育が目的を達成していない理由

根本的な問題は、目指すべき方向性を誰も理解していない点にあります。あるいは人によって目標が違うというべきでしょうか。 ぼやんとした目標はあるんですが、ゆとり教育の成否が評価できない理由は、期間的な問題もありますが、目標がそもそもないので、何を指標とするのかから議論が始まるからだとも思います。

もっと柔軟な、人に優しい社会にするのだと思っていたのですが、年寄がシステムを変えてくれないので柔軟性はないままで、若くて優しい人たちが(無関心によって)残酷な社会を作っている様子が普通に怖いです。

例えば、教師は自分の給与が社会から与えられていると認識して、将来の雇用主を育てるために、自立して使える人材を作る事に、もっと真剣になるべきです。 そう考えれば、そのためには教科の時間も足りないし、18才までに年刻みで教える事の難しさが見えてくると思います。

そういった必要から社会を変えていく事が必要で、イデオロギーや教条的な思い込みを原動力とする変化はうまくいかないでしょう。

さいごに

社会に出て学んだ事は「現実とのギャップを埋めるために与えられた環境で全力を尽す」という事です。

この社会は不公正で、各人は、ハンディの付いたそれぞれ違うスタート地点から同じゴールを目指すマラソンをしているようなものです。

理想が与えられるべきものだなどという考えは、社会主義を通り越してカルト的な信仰です。 とはいえ、それを羨んでも何も良い事は起きません。

違いはあるし、各人は違う人生を歩いてきた事を認め合って、それぞれが違うスタート地点に立って協調して動く事ができなければ、より大きな仕事を達成する事はできません。

気に入らないからと、足をひっぱる事は全体を停滞させるだけで、より大きな問題を引き起しています。

排他的な群の文化では、この時代において「全滅 or (ひとときの)繁栄」となる事は自明に思えます。

基本的にこれらの柔軟性を欠いている原因は「恐怖心」です。 人間の可能性を潰して、萎縮させて低い能力しか発揮できない原因は、この恐怖心にあります。

学校でのいじめが問題になっていますが、いじめる側がいじめられる側にならないためには、当事者よりも周囲に徹底的に力を誇示する必要があって、それによってエスカレートする宿命を負っているように感じます。

つきつめていけば、この社会が克服しなければいけないのはこの恐怖心ですが、戦前からこの社会に影を落しているものでもあり、この事を認識できるかどうかから試されているように思えてなりません。

日本人が恐怖心から逃れるために作ってきた神話や伝承、社会基盤といった代償的行為を思えば、ストレートに現状を認識することはとても悲観的に思えます。

これを克服するためには、各個人がかなり分析的にこの社会や現代社会の有り様を捉える必要があると思うのですが、哲学のないゆとり教育やそれに続く教育改革がこれに寄与する事ができるのか、この観点ではかなり懐疑的です。

外部の目や、他人の意見に左右されたり、過去の経験や誰かに付いていけばいい、そんな程度の認識ではだめで、もっとあるべき論から議論ができなければいけないのですが、議論にならないのは教育のシステムにも原因があるのでしょう。

何をやっても、全体を包括するような哲学やゴールがはっきりしない、当事者に認識されない間はうまくいかないでしょう。日本のシステムの悪いところは、その必要性や目指すところを「聞くな、感じろ」と強制するところにもあるように思えます。

これまで暗黙のうちに語られなかった事を、シンプルに口に出して明示的に話すだけで、ずいぶん変わる気がするんですけどね。あまりにも黒い理由があり過ぎて口に出せないんでしょうか。でもそれはもっと大きな別の問題なんですよ。

Postscript: 書きながらフォーカスを失なった短文たち

なぜか地方の経済は地方公務員の収入で支えられているところがあります。 周り周っていくお金ですが、基本的には、その収入は公務員以外の産業から埋まれた税金で賄っているはずです。お札を刷れば別ですけれど。

なぜか地方経済というエコシステムの頂点に公務員があるのは食物連鎖的に異常だっていう認識が普通になかったりして、地方公務員が勝ち組みたいな受け止め方をされたりします。

日本はユーロ危機にある現代のギリシャみたいにはならないと思いますが、19世紀に勃興したポルトガルの大航海時代後みたいな位置付けにはなると思います。いまのポルトガルには失礼ですが、将来の日本の姿はここら辺じゃないでしょうか。

ここでは、ゆとり教育が失敗だとはいっていません。 柔軟な人材を育む事に成功している可能性はあります。

しかし、うまくいったとしても、その育んだ人材を受け入れる社会システムが変化しないのであれば、前段のみを変革して、問題のある後段をそのまま維持しようとしているシステムの歪みが次の問題になるでしょう。

学力の低下を持って余りあるメリットが享受できれば良いのですが、それも難しそうです。

震災の後もここまで必死になってバブル期に最大限機能した日本のシステムを維持しつづけようとするとは思いませんでした。 今度こそ変わるかなって思ったんですけどね。意識の問題ではありますが、残念です。

2012/07/29

Linux環境でのbin/neo4j installコマンドの挙動

グラフDBの一つであるNeo4Jをいろいろ試す中で、 サーバースクリプトの引数にinstallオプションがある事に気がつきました。

いろいろ勝手にやってくれるのは便利なのですが、 それはそれで動きが分からないと不便なので、調べたことをメモしておきます。

環境はUbuntu 12.04 LTS 64bit版、JVMはOracle版のJava 1.6.0_33です。

マニュアルの説明

セクション18.1 Server InstallationではWindows, Linux, MacOSX毎の説明が書かれています。 ここではLinux用の記述について説明しています。

まず、導入から起動までの基本的なステップとして次のように書かれています。

  • $ bin/neo4j install
  • $ service neo4j-service status
  • $ service neo4j-service start

そして、導入ステップの中で次のような情報を入力や作業が行なわれるとされています。

  • ユーザー名 (デフォルトは"neo4j") の入力
  • ユーザーが存在しない場合の作成をスクリプトが行なう
  • dataディレクトリ以下のファイル所有者をユーザー名に変更

さらにセクション 22.9 にあるLinux用のパフォーマンスチューニングを実施するよう勧めています。

スクリプトの挙動

サービスとして起動させるために、何をするのかの説明はないので、スクリプトを普通に眺めていきます。

bin/neo4jスクリプトの中では、installservice()シェル関数の中で処理が行なわれています。

1. OS、JVMの判別

bin/utilsで定義されているdetectos, findjavaシェル関数でそれぞれOSとJVMの判別が行なわれています。

detectosの中では$ uname -sコマンドの出力をベースにDIST_OS変数に"linux"(solaris,cygwinなどの場合には正規化した値)が入るようになっています。

findjava関数はいろいろ泥くさい処理をしていて、例えばgentoo linuxの場合には$ java-config --jre-homeの出力をJAVA_HOME変数に設定するなどの処理をしています。 最終的にはJAVACMD変数にjavaコマンドのパスを格納して、それを後続の処理で使うようになっています。

2. /etc/init.d/neo4j-serviceファイルの配置

/etc/init.dディレクトリがある場合には、/etc/init.d/neo4j-serviceファイルはbin/neo4jへのシンボリックリンクとして作成されます。

その後で、$ update-rc.d neo4j-service defaults$ chown -R neo4j: data confのコマンドが実行されています。ユーザー名neo4jは適宜入力された名前に変更されて、ドキュメントにある通りの設定がされています。

グループ名の指定がないのがポイントと、いくつかドキュメントにない暗黙の設定があります。

インストール処理の自動化について

falseに設定されているHEADLESS変数は質問があるところで参照されて、もしtrueだと全ての設問にy(yes)を選択した挙動になります。 これを使う場合、外部から変数にtrueを設定する仕組みはないので、スクリプト自体を上書きする必要があります。

またwrapper_user変数は、作成するユーザー名の指定があって、通常は$ id -unから実行時のUIDの値が入りますが、$ sudo env wrapper_user=neo4jsrvr bin/neo4j installのようにするとコマンドラインからデフォルトのユーザーIDが指定できます。

この他にenvコマンドで同様に操作できるパラメータには次の変数がありました。

  • org_neo4j_server_webserver_port - ポート番号 (既存プロセスのステータス確認に使用)
  • wrapper_user - サーバーを実行するユーザーID
  • wrapper_ntservice_name - /etc/init.d/直下に作成するシンボリックリンクのファイル名 (serviceコマンドの引数に指定する名前)

ユーザーIDと/etc/init.d以下に配置されるファイル名の変更であれば、手動でHEADLESS=falseをtrueに変更して、envコマンドの引数でパラメータを指定すれば、対話的な処理なしにインストール作業を進めることができます。

org_neo4j_server_webserver_port は導入時のプロセスチェックにのみ使われて、confファイルは変更されません。 conf/neo4j-server.propertiesファイルを直接変更する必要があります。

上書きされるファイルについて

変更されたユーザー名については、conf/neo4j-wrapper.propertiesファイルが変更されます。 これによって$ sudo /etc/init.d/neo4j-service startのように実行すると、自動的に指定したユーザーIDでneo4jプロセスが起動します。

これ以外のパラメータは、confファイルを変更する必要があります。

さいごに

installオプションを実行すると、ファイルが展開されているディレクトリがそのまま使われます。 マニュアルにもありますが、/opt以下などにtar.gzを展開する必要があるでしょう。

その反面 data, conf ディレクトリは展開されたディレクトリに含まれているので、本番で運用するのであれば、これらデータ本体の配置は考慮する必要があります。

アップグレード時は、初回起動時にデータベース構造の更新処理が走る事になっているので、tar.gzを展開して、conf, dataを入れ替えるか、シンボリックリンクで適当なディレクトリを参照するようにしてあげるぐらいで良いようです。

その他に本番運用にはクラスタリングやオンラインバックアップなど、まだ考慮しなければいけない要素があるので、これから検証していく予定です。

2012/07/25

Ubuntu 12.04 LTSでmrubyを試してみた

組み込み用途に特化した軽量版Rubyの実装として、mrubyがリリースされています。

これの使いどころを考えてみたのですが、Tech-Onのインタビュー記事では、一例としてC言語で記述が難しい処理をmrubyにオフロードするとありました。

個人的には静的なコードはC言語で書くだろうと考えていて、動的なランタイムの変更をmrubyでユーザーに開放するんだろうなと思っています。 具体的には設定ファイルの記述やプラグインをmrubyスクリプトで作成することになるでしょう。

この使い方だけならluaなんかでも良いんですが、操作可能な要素をクラス単位でまとめる事ができるのは、実際のところ名前空間があるかどうかの違いぐらいしかありませんが、実用上の使い勝手は表面的な違い以上のものがあると感じています。

まぁ、ここら辺はいまのところ信念の問題なのですが、今回はmrubyを使って設定要素をクラスにまとめる場合を想定して、ちょっとしたサンプルを作ってみる事にしました。

テストした環境とmrubyのバージョンは次のようになっています。 特定のmrubyのバージョンには依存していないと思いますが、Webで調べたコードの中の関数の引数の取り方が違うものもあったので、念のため書いておきます。

  • OS: Ubuntu 12.04 LTS x86_64版
  • コンパイラ: gcc 4.6.3
  • mruby git commit: 8b6f6faf1e3771c04a1e2a58b1bbc84fe7d5c1e2

ちなみに、commit:のハッシュを使って、このテストしたmrubyと同じソースコードをbranch名"20120723.083824"で入手するには次のようにします。

$ git clone https://github.com/mruby/mruby.git
$ git checkout -b 20120723.083824 8b6f6faf1e3771c04a1e2a58b1bbc84fe7d5c1e2

mrubyのバージョンや日付によってメソッドの呼び出しシグネチャが違う事がありますが、だいたいそのまま読めると思います。

参考資料

参考にしたのは、主に手探りでおぼえるmruby その1:クラスを定義する、メソッドを定義するで、RICOHの方がまとめた記事もありましたがコードがGPLだったりするので、考え方などを参考にするに留めています。

とりあえずmrubyについては使い方よりも、生み出された背景や、中間コンパイラとしての挙動について、mrbcコマンドの動きを抑えておくのがお勧めです。

実証実験に参加した各種企業が公開しているドキュメントが参考になるでしょう。

mrubyのサイズ

x86_64環境でライブラリをenv COMPILE_MODE=release makeで作成すると、libmruby.a, libmruby_core.aの各ファイルはそれぞれ790KB前後のサイズになります。(strip後は470KB前後)

ruby-1.9.3-p194のコードをビルドすると、librucy-static.aのサイズはstrip後も2.1MBほどになります。

ライブラリの全てのシンボルとリンクする分けでもないので、静的にリンクした実行ファイルのサイズはもっと小さくなるはずですですが、CRubyのライブラリサイズの大きさは少し大き過ぎるなぁと感じるところです。

mrubyに求める機能

既に説明していますが、アプリケーションが提供するクラスを主体として、そのオブジェクトを組み込みメソッドを組み合せて操作できるところがメリットだろうと思っています。

普通のアプリケーションでは設定ファイルに固定文字列しか書けないのが普通ですが、これはセキュアだとは思うものの、記述できる語彙が少な過ぎるとも感じています。

luaはちょっとローレベルに過ぎる印象があってオブジェクト的に構造体の中に値と操作用関数をまとめる事はできますが、その環境をセットアップするのは少し面倒な印象です。

今回のゴール

mrubyを通してユーザーは日時情報や外部ファイルに記述されている内容などの情報に応じて振舞いを変化させる事ができるようになるといいなぁというわけですが、サンプルなので今回の範囲は一組のsetter/getterをラップしてみようと思います。

具体的に何をするのか、図にしてみた

図にしてみると次のようなプログラムを作成してみる事になります。

C言語レベルではConfigクラスに相当する設定可能な要素を構造体で定義します。

アプリからは直接構造体を操作せず、操作用のsetter/getterメソッドをConfigControllerクラスとしてまとめています。mrubyからはWrapperクラスを通してConfigControllerファイルでまとめているメソッドにアクセスしています。

実際のコード

いろいろ大風呂敷を広げましたが、ここから先はしょぼいコードが並びます。

ただGoogleで検索にヒットしたページは、やはりmrubyにコードをオフロードする仕組みやmrbcを使って中間コードを実行する方法に特化していたりしたので、もうちょっと泥くさい使い方を考えてみました。

conf.h, conf.c

実際にはConfとConfControllerに相当する機能はconf.c, conf.hにまとめました。 でも何かするわけではなくて、デバッグモードかどうかを動的に切り替えられるというだけです。

内容にはまったく意味がないんですが、気にしないでください。

conf.hファイル

#ifndef YA_CONF_H
#define YA_CONF_H 1

#include <mruby.h>

struct _conf {
  int is_debug;
} conf;

int is_debug(void);
void set_is_debug(int d);

#endif

conf.cファイル

#include "conf.h"
int is_debug(void) {
  return conf.is_debug;
}
void set_is_debug(int d) {
  conf.is_debug = d;
}
wrapper.h, wrapper.c

wrapper.hファイル

#ifndef YA_WRAP_H
#define YA_WRAP_H 1

#include <mruby.h>

struct RClass* yamrb_class;

mrb_state* yamrb_init(void);
mrb_value yamrb_is_debug(mrb_state* mrb, mrb_value self);
mrb_value yamrb_is_debug_equal(mrb_state* mrb, mrb_value self);

#endif

wrapper.cファイル

#include "conf.h"
#include "wrapper.h"

#include <mruby.h>
#include <mruby/numeric.h>

mrb_state* yamrb_init() {
  mrb_state* mrb = mrb_open();
  yamrb_class = mrb_define_class(mrb, "YaConf", mrb->object_class);
  mrb_define_method(mrb, yamrb_class, "is_debug", yamrb_is_debug, ARGS_NONE());
  mrb_define_method(mrb, yamrb_class, "is_debug=", yamrb_is_debug_equal, ARGS_REQ(1));

  return mrb;
}

mrb_value yamrb_is_debug(mrb_state* mrb, mrb_value self) {
  mrb_value ret = mrb_fixnum_value(is_debug());
  return ret;
}

mrb_value yamrb_is_debug_equal(mrb_state* mrb, mrb_value self) {
  mrb_int arg_debug;
  int argc = mrb_get_args(mrb, "i", &arg_debug);
  if(argc == 1) {
    set_is_debug(arg_debug);
  }
  return self;
}
main.c
#include <stdio.h>
#include "conf.h"
#include "wrapper.h"
#include <mruby.h>
#include <mruby/proc.h>
#include <mruby/compile.h>

mrb_state *mrb;
int gen_code_num;
mrbc_context *mrbc_ctx;

void init() {
  mrb = yamrb_init();
  FILE *fp = fopen("main.rb","r");
  mrbc_ctx = mrbc_context_new(mrb);
  struct mrb_parser_state* st = mrb_parse_file(mrb, fp, mrbc_ctx);
  fclose(fp);
  gen_code_num = mrb_generate_code(mrb, st->tree);
  mrb_pool_close(st->pool);
}

int main(int argc, char** argv) {
  init();
  
  // first run
  printf("current is_debug: %d\n", is_debug());
  mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[gen_code_num]), mrb_nil_value());

  printf("current is_debug: %d\n", is_debug());
  set_is_debug(1);
  printf("new is_debug: %d\n", is_debug());

  // second run
  mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[gen_code_num]), mrb_nil_value());

  // close
  mrbc_context_free(mrb, mrbc_ctx);
  mrb_close(mrb);
}

main.rb

print "-- begin --\n"
y = YaConf.new()
p y.is_debug()
y.is_debug = 2
p y.is_debug()
print "----\n"

Makefileファイル

INC = ./src/include
LIB = ./src/lib

main: conf.o wrapper.o main.c
	gcc -std=gnu99 -I. -I$(INC) -o main main.c conf.o wrapper.o -L$(LIB) -lmruby -lm

conf.o:	conf.c conf.h
	gcc -std=gnu99 -I. -I$(INC) -c conf.c 

wrapper.o: wrapper.c wrapper.h
	gcc -std=gnu99 -I. -I$(INC) -c wrapper.c 

気になったこと

Rubyの拡張ライブラリの知識は、いろんな意味で役に立ちますが、README.EXT.jaに対応するまとまったドキュメントがないので、いろいろ混乱するかもしれません。

FIX2INTなどの型変換マクロがない

Rubyの拡張ライブラリでは標準的なC言語の型との変換はマクロで実現していましたが、 mruby.hでは静的な関数が準備されています。

  • static mrb_value mrb_fixnum_value(mrb_int)
  • static mrb_value mrb_float_value(mrb_float)
  • などなど

mrb_intは標準のint型とtypedefされているだけで、直接に代入できます。 mrb_floatはmrbconf.hで定義されていますが、手元では8byteで通常はdouble型に紐付くようです。 文字列はmruby/string.hに定義されているような、組み込みString型用の関数を使う事になります。

mruby.hに定義されていなければ、操作対象の型に応じてmruby/以下のヘッダーファイルを眺める事になります。

mrb_generate_code()が返すint型の番号を管理する方法が欲しい

これはmrubyが準備する話しではないのですが、今回は処理が単純なのでmrbも全体で共有するような作りにしました。少し複雑になってきても、必要な都度、必要なコードをmrb_run()で呼びますが、この場合には対象のコードをmrb_generate_code()の戻り値で指定する必要がでてきます。

この管理方法が、まぁ対象のアプリに依りますが、どうなるかなぁと思っているところです。

まとめ

rubyはいろいろ機能が増えすぎて特定のバージョンとコードを密接に管理する必要があるので、mrubyはシンプルに保って欲しいなぁと思っています。まぁコンパイル時のオプションで調整することもできる部分もありますが。

C言語でアプリを組む時に機能の一部をオフロードする目的だと内蔵クラスや機能が多い方が楽になるわけですが、アプリケーションのプラグイン的にユーザーに開放する場合には、むしろ機能や組み込みクラスはないぐらいの方がセキュアになります。

mrubyは現状ミニマムで、これからスタンダード、フルといった主にクラスが追加される形のバージョンが出てくる事になっています。 とはいえ、ミニマムしかない現状でアプリの拡張をmrubyで行なおうとすると物足りない印象はあるので、前倒しでミニマウなmrubyが拡張されるような可能もあるのかなぁと思っています。 クラスセットについては、決まっているようですけれど、環境としてはまだまだ機能の追加が続いていますしね。

どうなるか、まだよくわかりませんが、アプリのコアエンジンとして安定してくれるといいなぁと思います。

2012/07/11

Google Chrome拡張を{ "manifest_version": 2 }に対応させてみる

気がついたらGoogleから「マニフェストのバージョンが2になったから対応よろしくね」、という旨のメールが届いていた。 まぁ8月中旬から新規の登録受付を中止して、年内には更新の受け付けができなくなるスケジュールが引かれていたので、 使うだけのユーザーなら影響がでるのは来年以降ですね。

今回はmanifest.jsonファイルを変更して気になった点をまとめていきます。

ちなみに変更は動作確認が終り次第、gitoriousにあるコード(Japan Postal Code Search, Open PinnedTab Link, etc...)に反映させます。

参考にしたページ

Googleのガイドはとてもまとまっているので、あまり他のサイトを調べる必要性を感じないのですが、 さすがに今回はStackOverflowなどのサイトにお世話になりました。

とはいえ、まず抑えておかなければいけないのはGoogleのmanifest.jsonの"manifest_version"の説明ページです。

ここで、全体のスケジュールと全体の変更の概要が書かれています。 しかし、ここだけでは具体的にアプリケーションにどんな変更が必要か把握するのは難しかったです。

具体的な変更作業

とりあえず作成しているOpen PinnedTab LinkJapan Postal Code Searchの2つは、比較的簡単なアプリケーションです。

このアプリケーションを修正した際に必要な修正は以下のようになりました。 まだ稼働確認が終っていないので、追加で必要なものもありそうですが、とりあえずまとめます。

HTML中にonclick, onload属性は書けなくなった

scriptタグを使ったjQueryの$(function() {...});表記などは、そのまま使えますが、(x)HTML上のタグにあるonclick="..."やonload="..."の表記を埋め込む事ができません。

基本的なコードはGoogle ChromeガイドのContent Security Policy (CSP)ページに記載されています。

onloadについは書かれていませんが、onclickと同様にdocument.addEventListener('DOMContentLoaded', function () { ... };の...部分にonloadで行なっている関数呼び出しなどをコピーすれば動きます。

ここで問題になったのはJavaScriptのコード中で、明示的に文字列としてonclick属性を追加している場合でした。

変更前のコード:文字列としてonclick属性を追加している例

...
td4_span.setAttribute("onclick","showMapImg('" + center + "')");
...

変更後のコード:addEventListenerに書き換えた例

...
td4_span.addEventListener('click', function(){showMapImg(center);});
...

元々変更後のように組むべきだったとは思います。 とはいえ文字列で解決するのは単純で簡単だったので、使っている方もいそうです。

動的なアクションはすべからくaddEventListener関数で指定する事になると思われます。

background処理をhtmlからjsファイルへ移動

manifestのbackgroundで指定する対象がhtml("page":文字列)とjavascript("scripts":文字列配列)の2つが準備されています。

これまではhtmlで記述していたので、manifest.jsonを書き換えて、そのまま流用すれば良いと思っていたのですが、どういう分けか、うまく動きませんでした。

変更前:version 1のmanifest.jsonから抜粋

...
  "background_page": "background.html",
...

元々background.htmlは本文のない、scriptタグの中に処理が記述されているだけだったので、その中身をjsスクリプトファイルに分割して、manifest.jsonの表記を書き換えました。

変更後:version 2のmanifest.jsonから抜粋

...
  "background": { 
     "scripts": ["scripts/background.js"]
  },
...

jsファイルを指定した場合でも、内部では空のhtmlファイルが生成されて組み込まれているだけのようなので、今回の挙動はおかしいと思います。 おそらくhtmlファイルのまま移行できるように作られているはずなので、早晩このワークアラウンドは不要になるでしょう。

まとめ

いろいろ書こうと思ったのですが、うまく動かない処理を発見したりして別の記事にまとめる事にして、とりあえず今回はここまでで終りです。

今回取り上げなかったのですが、外部サイトからのJavaScriptファイルのロードなどもデフォルトではできなくなっています。 オプションページのためにjQueryのコードをCDNからダウンロードしたいような場合にも対応が必要そうです。

単純なmanifest.jsonの書き換えで対応できるアプリケーションは少ないのではないでしょうか。

とはいえ、変更内容を確認する限り、機能が制限されているものはないので、既存の"manifest_verison":1アプリは全て、ちゃんと書き換えれば動くはずです。

この「ちゃんと」という部分が曲者ですが、今回の経験からは、新ルールに矯正された事によってアプリケーションのコード全体は良くなっていると思います。

Chrome拡張のAPIについてはいろいろ疑問に思うところもあったので、これから始める方々には、面倒は増えるでしょうが、よりよいコードになっているとは思います。

これがどれくらい面倒かは…、なんともいえませんが、少なくとも既存の開発者は、どこに問題があるか調べるだけで面倒そうです。

2012/07/04

SK17iをICSにして撮影した画像のファイルサイズが増えている件について

ExifPMというAndroidアプリを作成している事もあって、Xperia Mini Pro (SK17i) で撮影した写真データのExifデータをチェックしていると、ICSへのアップデート前後でファイルサイズが違っている事に気がつきました。

Exifデータを比較してみると、画素データのサンプリング方法がYCbCr420からYCbCr422へと変更されていた事が原因でした。

元々500万画素のカメラなのに、生成される写真データは700[KB]から900[KB]程度のファイルサイズだったので、 カメラアプリの不具合かなぁと思っていたのですが、これはデータをYCbCr420で処理していた事が原因でした。

色データの扱いは対象の特性によって異っていて、ディスプレイへの出力はRGBで考えて、印刷をする時にはマゼンダなどの中間色を使ったCMYKが使われます。JPEGの場合にはYCbCrやYCbCrと呼ばれるような、輝度と色差のデータを使う事になります。

基本的にはYCbCr420は縦横4ピクセルで色差情報を共有するので、横並びの2ピクセルで色差情報を共有するYCbCr422と比較してデータ量が落ちるため、画質が落ちるといわれています。

データ量が少ない分だけ劣化するのは事実ですが、まぁそんなに単純な話しでもないので、 サンプリング方法の詳しい説明はGoogleでいくつかのサイトの記述を確認されるのがお勧めです。

問題はICSにアップデートしたSK17iではカメラの画質が上がっているのだろうか、という疑問に対する答えがあるのかどうかです。

結論からいえば情報不足でよく分からないという事になるのですが、とりあえずまとめたところをメモにしておきます。

撮影した画像の見た目の違い

残念ながら同一条件で、同一被写体を撮影した画像がないので、正確な比較はできません。

撮影する時間帯はずれているので照明の条件は同じになりませんが、似たようなアングルで撮影した画像をみてみると、古い画像は絹のような質感が感じられて何か靄のようなもので覆われている印象があります。それと比較するとICS以降に撮影した画像は鮮明に感じられます。

画像をみてICSで撮影された画像かどうか区別できるものもあれば、難しいと感じるものもあって、単純に画質が向上したというのは難しいかなと感じています。

レンズの汚れや撮影環境の条件をちゃんと揃えないと、見た目の判断だけでは何ともいえないところです。

画像ファイルサイズの違い

対象によってファイルサイズは変化しますが、室内・屋外で撮影した手元の画像を眺めると、だいたいファイルサイズは次のようになっています。

  • Android 2.3: 500[KB]〜900[KB]
  • Android 4.0: 1.2[MB]〜1.8[MB]

画質の違いは別にして、ファイルサイズは確実に増えています。

APIからみた画質の変化について

自作アプリを作った時にカメラAPIから渡されたデータは、YUV420SPという形式でした。 ちょっと調べたところ、このAPIに変化はなさそうです。

Androidのカメラアプリを作って気になったのは、カメラからのRAWデータにアクセスする方法がないところでもありました。APIとしては準備されているんですが、あれが有効なデータを返すデバイスを寡聞にして聞いた事がありません。

使えたとして、大抵のデバイスでは、ほぼ確実にヒープ領域が確保できないでしょうから、処理を始める前にアプリが落ちるんでしょうけれど。

カメラ固有のAPIからデータを取得してYCbCr422データを作らない限りは、YCbCr422のデータをYUV420SPをYCbCr422に変換してもデータサイズが大きいだけで画質の向上は見込めない事になります。

現状では満足していますが、画質が向上したのかという疑問にははっきりとした答えが出せないでいます。

さいごに

SK17iを入手して比較的すぐにICSにアップデートしてしまったので、カメラアプリの挙動の違いが本当に正しいのか、設定の違いなんじゃないのか、という点について良くわかっていません。

体験として嘘は書いてませんが、十分に調査したとはいえないので、ひょっとすると勘違いが含まれているかもしれません。その際はご指摘頂ければ幸いです。

ただICSにアップデートした事自体は公開していません。Xperiaのドコモ端末の中でRAM 512MB未満はICSへのアップデートが不適とされて行なわれない事になりました。

理由がRAMサイズにあるという事ですが、それで何が問題なのかという点はよく分かっていません。

ただしばらくSK17iを使っていて、落ち着いて使っている時は良いのですが、ソフトウェアキーボードを急いで操作する時には、ひっかかるように感じる時があります。

その反面、ハードウェアキーボードを使ってメールやtwitterを使う場面で、何か問題が起こった事はないので、細かい違いを気にするのであれば、ICSへのアップデートは避けた方がいいのかもしれません。

それを除けば、いまのところICSだから問題だという現象には遭遇していないところです。 カメラの件は裏の仕組みがどうなっているか分からないので、良いのかどうか分かりませんが、基本的に新しいものが好きなのでICSにして満足しています。