2013-02-27

RHEL6: ssh-keygen: Permission denied

SSH 鍵を作ろうとすると、「Permission denied」と言われる。

[rhel62]# mkdir ~/.ssh

[rhel62]# chmod 700 ~/.ssh

[rhel62]# ls -dl ~/.ssh
drwx------. 2 root root 4096 Feb 27 09:04 /root/.ssh

[rhel62]# ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa ; echo $?
Generating public/private rsa key pair.
open /root/.ssh/id_rsa failed: Permission denied.
Saving the key failed: /root/.ssh/id_rsa.

パーミッションに抜かりなどある訳がない。失礼な。こういう時、真っ先に疑うべきは SELinux。

/var/log/audit/audit.log:

type=AVC msg=audit(1361923639.970:20915): avc:  denied  { create } for  pid=1932 comm="ssh-keygen" name="id_rsa" scontext=unconfined_u:unconfined_r:ssh_keygen_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file
type=SYSCALL msg=audit(1361923639.970:20915): arch=c000003e syscall=2 success=no exit=-13 a0=7f6f3282cb80 a1=241 a2=180 a3=fffffff7 items=0 ppid=1875 pid=1932 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts3 ses=2 comm="ssh-keygen" exe="/usr/bin/ssh-keygen" subj=unconfined_u:unconfined_r:ssh_keygen_t:s0-s0:c0.c1023 key=(null)

案の定、何か文句を言っている。~/.ssh のコンテキストを確認すると、

[rhel62]# ls -dZ ~/.ssh
drwx------. root root unconfined_u:object_r:admin_home_t:s0 /root/.ssh

何処が気に入らないのかは良く分からないが、ともかく restorecon してみる。

[rhel62]# restorecon ~/.ssh

[rhel62]# ls -dZ ~/.ssh
drwx------. root root unconfined_u:object_r:ssh_home_t:s0 /root/.ssh

何か修正されたっぽいので、リトライ。

[rhel62]# ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa
Generating public/private rsa key pair.
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
a7:14:6f:f0:8a:72:64:20:01:55:2b:24:4c:aa:a7:30 root@rhel62
The key's randomart image is:
+--[ RSA 2048]----+
|=++..            |
|.+ . .           |
|. o o   o        |
|.  o .   =       |
|E .   o S =      |
|.+   o o =       |
|.   . o o        |
|     o           |
|                 |
+-----------------+

動いた。ちなみに ~/.ssh を作るのを ssh-keygen に任せると、何もしなくても上手くいく。

[rhel62]# rm -fr ~/.ssh

[rhel62]# ls -dl ~/.ssh
ls: cannot access /root/.ssh: No such file or directory

[rhel62]# ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa ; echo $?
Generating public/private rsa key pair.
Created directory '/root/.ssh'.
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
e6:83:f6:38:dc:fc:eb:6a:45:f1:39:05:34:7d:ad:68 root@rhel62
The key's randomart image is:
+--[ RSA 2048]----+
|           .+o  .|
|          .  .o o|
|           o + o |
|          . E .  |
|        S. . .   |
|       +  .      |
|     .ooo.       |
|     .oo+.       |
|      .oo++.     |
+-----------------+

これは理屈としては理解できるが、非常に分かり辛い動作だと思う。

この理屈に従うと、作ったファイル・ディレクトリが SELinux のポリシーに沿っているかどうか、逐一確認しなければならくなってしまう。そういうことを平気で要求する SELinux の気が知れない。だから「SELinux 氏ね」とか言われるんだよ。:-p

ところでコンテキストの修正は restorecon で行えるが、現在のコンテキストが正しいかどうかはどうやって確認すれば良いのか。

matchpathcon を使え、と。

[rhel62]# rm -fr ~/.ssh

[rhel62]# mkdir ~/.ssh

[rhel62]# chmod 700 ~/.ssh

[rhel62]# matchpathcon -V ~/.ssh ; echo $?
/root/.ssh has context unconfined_u:object_r:admin_home_t:s0, should be system_u:object_r:ssh_home_t:s0
1

[rhel62]# restorecon ~/.ssh

[rhel62]# matchpathcon -V ~/.ssh ; echo $?
/root/.ssh verified.
0

注意点として、matchpathcon には絶対パスを渡す必要がある。でないと判定に失敗する。

[rhel62]# ls -dZ .ssh
drwx------. root root unconfined_u:object_r:ssh_home_t:s0 .ssh

[rhel62]# matchpathcon -V .ssh ; echo $?
.ssh has context unconfined_u:object_r:ssh_home_t:s0, should be <<none>>
1

これも理解できる動作ではあるが、やはり分かり辛い。もう少しマシなメッセージは出せないのかと文句を言いたい。

と、いうようなことを実は 1 年以上前にやっていたのだが、最近になって RHEL6.3 では本現象が起こらないことに気が付いた。調べてみると、この辺か。

「理解できる」と言っておいてアレだが、どうやら仕様ではなかったらしい。

2013-01-20

Animes in the 4th quarter of 2012

アニメは IT エンジニアの必須科目です。 ということで簡単なレビューを。

最初、主人公は一匹狼的でカッコ良さげなのだが、ヒロインと合流してからヘタれてしまう。このヒロインは男をダメにするサゲ○○に思えてならない。アクセル・ワールドと同じ作者と聞いて、妙に納得した。この人は世界観は良いが、脚本がダメなんだと思う。音楽だけは良いと思ったら、梶浦由紀だった。これも納得。

序盤は人類が天敵にエサにされるという展開。またキツいのが始まったなあ、と思っていたら、後半は殆ど人間の話になった。人の敵は人の心の中にこそある、というのは真実だとは思うが、結果として至って普通の話になった。個人的には、最初の絶望的な雰囲気で進めて欲しかった。きっと見るのは鬱になっただろうけど。

第一章はさっぱり面白くなかったが、第二章も変わらず。団結力だけが取り柄の弱っちい主人公達が仲間割れしたら、いったい何を褒めれば良いのか。最後に強くカッコよくなるが、その過程が理不尽。想いだけで強くなれたら世話ない。第一章と同様、OP くらいしか褒められるところが無かった。

少女マンガ原作ながらイマイチだった。ヒロインが惚れっぽくて話の展開が読める。神様の仕事そっちのけで狐とイチャつくことしか頭にない神様ってどうよ。まあ確かに年頃の女子とはそういうものだろうが、話もギャグも中途半端でお気に入りのキャラも無し、というのが正直な感想。ただ OP・ED は作品の雰囲気に合った良作。

原作は読んでたつもりだったが話がさっぱり思い出せない。と思ったら、実はアニメ用のオリジナルだったらしい(by Wikipedia)。そのせいかは分からないが、個人的にはイマイチな内容だった。本シリーズにしては、話が真面目すぎる気がする。まあ私はアニメより漫画の方が面白いと思ってるので、私的には問題ない。

今度は戦車を女子化か!?と思ったら流石にそれは無かった。戦車のことは知らないが、戦車の挙動がやけにリアルで、嘘かも知れないが本当にドリフトとかしそうに思える。個人的には好きな作品だったが、決勝戦の最中に「私たちの戦いはこれからです!!」と衝撃の終わり方。決して不人気のせいではなく、内部事情だと思いたい。

本シリーズは初めての視聴。原作も未読なので、最初は女子キャラの区別が付かなかった。ご都合展開全開の作品だが(何故いちいちパンツに突っ込む?という台詞は道理)、長寿作品なだけあって各キャラの個性は立っている(主人公を除く)。ただ長女の扱いがサブキャラ並みだなと思ったら、本作は一応スピンオフ作品だとは知らなかった。

原作は最初の五話くらいで挫折。ただ現在も連載中なので、アニメで魅力を発見できるかと期待したが、もう全然ダメだった。主人公、ヒロイン、敵の親玉、どいつの台詞も嘘くさくて私には全く受け付けられない。これは次回作があっても見ないと断言できる。

前期からの続き。序盤は雰囲気が変わったように思えて心配になったが、中盤以降は元に戻ったので安心。ただし最終回は消化不良。いきなり「2 年後」もそうだが、ヨナの心の変化、どう納得したのかが良く分からなかった。サブキャラの近況描写も一瞬だし、「風」の意味も不明。まあそれを差し引いても、全体としては十分に満足。

今クールの少女マンガ原作では、ダントツの出来。ギャグベースのドタバタ劇に、出てくる女子キャラは(サブキャラでさえも)魅力的で、見ていて飽きない。少女マンガ原作はこうでないとね。今回は「種﨑敦美」を覚えた。鈴木達央も今回の演技で見直した。唯一の不満は、最終回があっさり過ぎて終わったことに気付かなかったこと。

典型的な少女マンガという印象。内気なヒロイン、自分勝手で強引なイケメン、ライバルの出現。最初「君に届け」とデジャヴったが、君届には全く及ばなかった。風早くんの方がよっぽどいい奴だし、シリアス一辺倒で話に遊びがない(最終回を除く)。次回予告は良かったが、そういう遊びを本編にも入れて欲しかった。

まず目を引くのが独特な画質。特に空間制御魔法の描写が印象的。キャラも主人公以外は魅力的で、個人的にはネコがお気に入り。ただ、話がキャラに追いついていない感じがする。キャッチコピーの「きずな」は何処に出てきた? 結局ネコが何者かも分からないし。まあ既に続編が決定しているらしいので、そちらでの解決に期待。

大して期待していなかったが、賑やかさ・パロディー・エロス(?)など、その方面で期待していた「生徒会の一存」を食ってしまった。しかしそれは同時に、万人から見るととても「疲れる」作品になってしまった可能性も否定できない。個人的には元ネタが分からないパロディーがあったのが悔しい。まだまだ勉強が足りないようだ。

前作が結構好きだったので、引き続き視聴。しかし前作の勢いが感じられず、前半は空回りが目立つ印象。林檎、飛鳥での話のような盛り上がりがもっとあれば良かった。この作品の肝は生徒会メンバーの「デレ」だから。制作会社や声優が変わったりと扱いが不憫だが、そこまでして第二期を製作する必要があったのかは疑問。

2012-12-16

Python: cElementTree returns non open object

xml.etree.cElementTree は、xml.etree.ElementTree の C 実装だ。

ElementTree クラスはエレメントの構造を包み込み、それと XML を行き来するのに使えます。

この API の C 実装である xml.etree.cElementTree も使用可能です。

C 実装であること以外、ElementTree と cElementTree の違いについては述べられていない。違いがないなら、C 実装の方を使わない手はない。しかし、

$ python
Python 2.6.6 (r266:84292, Sep 12 2011, 14:03:14)
[GCC 4.4.5 20110214 (Red Hat 4.4.5-6)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import xml.etree.ElementTree
>>> html = '<html></html>'
>>> tree = xml.etree.ElementTree.fromstring(html)
>>> tree.html = html
>>> tree.html
'<html></html>'
$ python
Python 2.6.6 (r266:84292, Sep 12 2011, 14:03:14)
[GCC 4.4.5 20110214 (Red Hat 4.4.5-6)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import xml.etree.cElementTree
>>> html = '<html></html>'
>>> tree = xml.etree.cElementTree.fromstring(html)
>>> tree.html = html
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: html

cElementTree が返すオブジェクトはオープン・オブジェクトではないらしく、属性を追加することができない。C 実装されたモジュールとはそういうもんか、とも思ったが、

$ python
Python 2.6.6 (r266:84292, Sep 12 2011, 14:03:14)
[GCC 4.4.5 20110214 (Red Hat 4.4.5-6)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cProfile
>>> p = cProfile.Profile()
>>> p.foo = 'foo'
>>> p.foo
'foo'

同じ C 実装モジュールの cProfile では問題ない。想像するに、ElementTree の場合、木構造で大量のオブジェクトを使用するためメモリをケチってるのかも知れない。

ともかく、RHEL5 + elementtree で作ったスクリプトを RHEL6 で動そうと喜んで cElementTree を使った私にとっては、この上ないぬか喜びだった。

2012-11-21

psycopg2: Can't mogrify `None' in a tuple to `NULL'

RHEL6 付属の psycopg2 で、

# rpm -qa | grep psycopg
python-psycopg2-2.0.13-2.el6_1.1.x86_64

tuple 中にある None を mogrify するとエラーになる。

test1.py:

#!/usr/bin/python

import psycopg2.extensions

def main():
    conn = psycopg2.connect('dbname=testdb user=testuser')
    cur = conn.cursor()
    for param in [0, [0], (0,), '', [''], ('',), None, [None], (None,)]:
        print '%s\t->' % repr(param), cur.mogrify('%s', [param])

if __name__ == '__main__':
    main()
$ python test1.py
0       -> 0
[0]     -> ARRAY[0]
(0,)    -> (0)
''      -> E''
['']    -> ARRAY[E'']
('',)   -> (E'')
None    -> NULL
[None]  -> ARRAY[NULL]
(None,) ->
Traceback (most recent call last):
  File "/root/tmp/test1.py", line 12, in <module>
    main()
  File "/root/tmp/test1.py", line 9, in main
    print '%s\t->' % repr(param), cur.mogrify('%s', [param])
  File "/usr/lib64/python2.6/site-packages/psycopg2/extensions.py", line 100, in getquoted
    qobjs = [str(o.getquoted()) for o in pobjs]
AttributeError: 'str' object has no attribute 'getquoted'

落ちている場所は、

/usr/lib64/python2.6/site-packages/psycopg2/extensions.py:

# The SQL_IN class is the official adapter for tuples starting from 2.0.6.
class SQL_IN(object):
    """Adapt any iterable to an SQL quotable object."""

    def __init__(self, seq):
        self._seq = seq

    def prepare(self, conn):
        self._conn = conn

    def getquoted(self):
        # this is the important line: note how every object in the
        # list is adapted and then how getquoted() is called on it
        pobjs = [adapt(o) for o in self._seq]
        for obj in pobjs:
            if hasattr(obj, 'prepare'):
                obj.prepare(self._conn)
        qobjs = [str(o.getquoted()) for o in pobjs]
        return '(' + ', '.join(qobjs) + ')'

    __str__ = getquoted

register_adapter(tuple, SQL_IN)

print デバッグすると直ぐに分かるが、このとき o には 'NULL' という文字列(str 型)が入っている。当然、単なる文字列に getquoted なんてメソッドがあるはずがない。そりゃ落ちるわ。

何がどうあるべきなのかは分からないが、「動かないシステムに価値はない」の持論に従い、ともかく動くようにする。

test2.py:

#!/usr/bin/python

import psycopg2.extensions

# Fix a bug that can't mogrify `None' in a tuple to `NULL'
class FIXED_SQL_IN(object):
    def __init__(self, seq):
        self._seq = seq

    def prepare(self, conn):
        self._conn = conn

    def getquoted(self):
        adapt = psycopg2.extensions.adapt
        pobjs = [adapt(o) for o in self._seq]
        for obj in pobjs:
            if hasattr(obj, 'prepare'):
                obj.prepare(self._conn)
        qobjs = [getattr(o, 'getquoted', o.__str__)() for o in pobjs]
        return '(' + ', '.join(qobjs) + ')'

    __str__ = getquoted

psycopg2.extensions.register_adapter(tuple, FIXED_SQL_IN)

def main():
    conn = psycopg2.connect('dbname=testdb user=testuser')
    cur = conn.cursor()
    for param in [0, [0], (0,), '', [''], ('',), None, [None], (None,)]:
        print '%s\t->' % repr(param), cur.mogrify('%s', [param])

if __name__ == '__main__':
    main()
$ python test2.py
0       -> 0
[0]     -> ARRAY[0]
(0,)    -> (0)
''      -> E''
['']    -> ARRAY[E'']
('',)   -> (E'')
None    -> NULL
[None]  -> ARRAY[NULL]
(None,) -> (NULL)

ということを、実は 2 年くらい前に RHEL5 + psycopg2-2.0.12 (from rpmforge)という組み合わせでやっていたのだが、最近になって検索すると次が出てきた。

本件は psycopg2-2.4 で直っている模様。しかし私が試した限り、この変更部分を 2.0 系に持ってきても動かない。None に対してアダプターを登録しても、全く動く気配がない。None に対するアダプターが動くようになる変更が 2.4 までの何処かに入ったのかも知れないが、私的にはもう上述の方法で解決しているのでこれ以上は調べる気なし。

2012-10-31

Animes in the 3rd quarter of 2012

アニメは IT エンジニアの必須科目です。 ということで簡単なレビューを。

前期は面白く無かったのに、第二期が始まってしまった。何とか面白いこと言おうと一生懸命なのは伝わってくるが、殆ど空回るので見てて痛々しい。ただ、黄・紫・メガネの掛け合いは良かった。ていうか「コミック百合姫」とかあるんですか? つくづく日本人って凄いと思う。確かに女子しか出てこないし、タイトルの意味もよく分かった。

最初はどうなることかと思ったが、我慢して見てたら後半は普通に見れた。キャラ付けもできてると思うし、意外なことに AKB が当てている声も慣れればそれっぽく聞こえた(一部を除く)。ただ、それなら襲名メンバーにプロ声優を当てたのが中途半端だと思う。突っ込み所を数えれば切りが無いが、結果としてこれはこれでアリだった気がする。

最初の一人目、幼馴染とはいえ、さっきまでの敵同士が手のひら返して「オレたち親友」とか言ってる所からもうダメだった。その後も仲良しごっこ、恋愛ごっこ、主人公のコンプレックス丸出し言動など、色々とイタいところが多すぎる。せっかく世界観はなかなか良いと思うのに、脚本で全てが台無しになるという良い例だった。

主人公がイライラするのは前作と同様。個人的にはエレナがツボったが、エウレカスイッチでヒステリーになるのが残念。前作もそうだったが、このシリーズはヒステリー持ちが多くて楽しくない。全体的な点としては、エウレカの存在感が大きすぎて今作キャラがすっかり霞んでしまった感がある。寧ろエウレカは出さない方が良かったのでは。

前回はイマイチだったが、今回も同様。ロボットものなのに途中からロボットに乗るの放棄するし、いったい何処に向かっているのか。敵味方が行使する力の理屈も世界観もさっぱり伝わってこないので、楽しむものがキャラくらいしか無い。しかしキャラの魅力も今ひとつなので詰んでる。絵は綺麗なだけに、色々と勿体ない作品だった。

基本、一話毎に新キャラが出るので、キャラを覚えられない。これは構成のミスだと思う。数あるキャラでは、秀吉がお気に入り。米を食って幸せ一杯の「ウマー」にやられた。声が名塚佳織というのも意外で良かった。少年サンデーでも短期連載があったが、両者の中身は全くの別物。笑えるという意味では漫画の方が勢いがあって良かった。

前作に引き続き、話がさっぱり分からない。もうこれは「要、予習・復習」とかいうレベルではなく、これがカッコイイと勘違いしているのでは。せめて重要そうな「歴史再現」の説明はもっと kwsk。訳の分からなさは徹底しているので、後はキャラを楽しむだけ。もう少しビギナーへの配慮が欲しかった。普通は Wikipedia とか読まないからね。

サンライズにしては絵がチャチく感じる。チラ見した限りは原作の方が綺麗に見える。中身は典型的なドタバタ劇で、花澤香菜(ヒロインの中の人)の頑張りが伝わってくる。が、それでも枠の中に収まっている感が否めない。他作品と比べるのは良くないが、同じサンライズとして銀魂・SKET DANCE くらいを期待してしまうのは酷だろうか。

主人公は苦もなく強力な力を手に入れる -> 強いのでモテる、というご都合ハーレム展開。一応、神々との戦いでは何か理屈が働いてるっぽいのだが、神話マニアじゃないから良く分からん。取り巻きに好みさえ居れば、まあ見れる。私は青い人(喜多村英梨)が真ん中だったので無問題だった。もし続きがあれば、青い人目当てで見ると思う。

武将を女子化するのはもういい加減に食傷ぎみだが、絵は好みの部類。しかしヒロインが大してイケてない主人公にデレるとか、ぜんぜん信長っぽくない。史実の改変を許容しているので、話もどうしてもご都合展開になってしまう。加えて主人公は典型的な「気持ち」だけの人で努力の描写が欠如している。残念だが私には楽しむのは無理だった。

視聴前の印象よりは良かったが、その後の期待には及ばなかった感じ。個人的には第二話がピーク。合唱がテーマの割には合唱シーンが少ない。その合唱も全員が同じパートを歌うのではなく、少なくとも(キーが異なるのだから)男女でパートを分けた歌をもっと聞きたかった。と細かい不満を言いたくなるくらい、個人的には惜しい作品。

果たして「超訳」は言い過ぎだったと思うが、まあ確かに今風のノリとツッコミでアレンジされている。ワクワクする面白さは無いが、退屈することもない。逆に、百人一首に思い入れがあると受け付けないかも知れない。ところで毎度こういうのを見るにつけ、つくづく人間って千年経っても 1 ミリも進歩してないんだなあと実感する。

原作はどうもに読む気にならないが、アニメ版は素直に面白かった。テンポが良いのと、何より白石涼子(姫子)の力が大きい。何でこの人はこんなにも方言キャラにハマるのだろうか。もし別の声優が当たっていたら、今よりずっとつまらなかったと思う。後釜は「銀魂」とのことで、銀魂 -> SKET DANCE の無限ループが見えた気がする。

アサルトライフルを女子化とか誰が考えた。挙句に「T バック」とか「撃鉄落ちちゃう」とか、バカじゃねーの? もう、同じ日本人として誇りに思うよ:-D。メインキャラには萌えなかった(高等部の方が良かった)が、その他でお腹一杯になったので良し。ライフルへの愛が伝わってくる作品ではあるが、一般人にはなかなか勧められない作品。

前期は未見、原作は既読。そのせいかも知れないが、これはアニメ化する意味があったのだろうか。本作の魅力は女子キャラと発酵のうんちくだと思っているが、アニメになったせいで後者が著しく損なわれてしまった。かといって前者が立っているかというと、何か声優がミスマッチのような気がするし。まあ原作の復習としては丁度良い感じ。

少女マンガ原作だが、結果はイマイチ。まず個人的な好みの問題として、ヒロインに萌えなかったのが大きい。そして中盤から主人公が精神世界に行きっぱなしになり、ずっと支離滅裂な世界を見せられた後、現実に戻ったらハッピーエンドを通り越してお葬式。って感情移入する暇が全く無いんだけど。原作もこうなの? ただ ED は良かった。

やっぱり「ガンダム」の冠は重いよね、という予想通りの結果。AGE の意味が分かったときには新鮮な驚きはあったが、親子三代はやり過ぎだろう。作風から低年齢が主なターゲットに見えるが、ガンダムファンはみんな高年齢なので評価されるのは難しいと思う。とはいえ SEED の例もあるし、そのうち当たりもあるだろうと次に期待。

前作に続き視聴。キャラは倍に増えたが、話はますます暗くなった。どいつもこいつもコンプレックスの固まりで、見てるこっちが陰鬱になってしまう。パズルの楽しさは何処にいった。あと、やっぱり個人的に萌えるキャラが居ない。エレナは相変わらず出番が少ないし。何を思ったか更に 3 期に続くようだが、このままでは期待できる要素が無い。

ジャンプのスポーツ漫画らしく、必殺技がデフォルト。まだ本作は人間の範疇に見えなくもないので我慢できるが、そのうち影分身とかするようにならないか心配。必殺技に目をつむって人間関係だけを見れば、普通に面白いと思う。個人的には、もっと(本作にも無い訳ではないが)正しい努力の積み重ねが結果に結びつくという描写が欲しい。

思わず見とれてしまう程の、絵の美しさ。これだけでも見る価値はある。話の方はグッとくる面白さは無いが、地味に面白い。絵のせいもあり独特な雰囲気があるので、深夜にしんみり雰囲気に浸って見るのがお勧め。個人的には色々と納得いかない推理も多かったが、それはきっと私がバカだからだろう。あと、1st OP は良かった。

OP や初話のノリで期待して見ると、実は結構な重い話に裏切られる。各キャラが個々のイベントにマジレスし過ぎ。そりゃ本当に人格が入れ替わったら大変だよ。心を壊す輩も出てくるさ。しかしその葛藤をアニメにする意味が分からん。ハッピーエンドになるのは分かってるが、道中もハッピーにして欲しかった。キャラが魅力的なだけに残念。

しかしこう書き連ねてみると、いい加減にアニメ見過ぎだな。もう少し絞らないと時間がいくらあっても足りない。しかしアタリかハズレかなんて見ないと分からないしなあ。

2012-09-24

RHEL6: multi NICs in the same subnet

タイトルは「NIC」としているが、どちらかと言えば「インターフェイス」の意味。要は複数 LAN ポートを同一サブネットに繋ぎたい。

例として、次のように設定する。

  • eth0: 192.168.1.11/24 (00-0c-29-11-11-11)
  • eth1: 192.168.1.12/24 (00-0c-29-22-22-22)

このとき双方に ping を打つと、実際には eth0 だけが応答する。

>ping 192.168.1.11
>ping 192.168.1.12
>arp -a
インターフェイス: 192.168.1.101 --- 0xc
  インターネット アドレス      物理アドレス      種類
  192.168.1.11          00-0c-29-11-11-11     動的
  192.168.1.12          00-0c-29-11-11-11     動的

これは Linux ネットワークの仕様。RHEL5 だと、次を設定することで両方から ping が返るようになる。

net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.all.arp_ignore = 1
>ping 192.168.1.11
>ping 192.168.1.12
>arp -a
インターフェイス: 192.168.1.101 --- 0xc
  インターネット アドレス      物理アドレス      種類
  192.168.1.11          00-0c-29-11-11-11     動的
  192.168.1.12          00-0c-29-22-22-22     動的

しかし、RHEL6 で同じ設定をしても動かない。具体的には、eth1 への ping が返ってこず、ARP テーブルにも登録されない。

>ping 192.168.1.11
>ping 192.168.1.12
>arp -a
インターフェイス: 192.168.1.101 --- 0xc
  インターネット アドレス      物理アドレス      種類
  192.168.1.11          00-0c-29-11-11-11     動的

この理由がずっと分からなかったが、どうやら RHEL6 から rp_filter の挙動が変わったようだ。結論から言うと、次の設定で RHEL6 でも動くようになる。

net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.rp_filter = 2

理由はこの辺りを参照。

RHEL5 では、conf.all.rp_filter と conf.<interface>.rp_filter との論理積(AND)が rp_filter の実効値だったが、RHEL6 では最大値(MAX)が実効値になった。

RHEL5 / RHEL6 のどちらにも、/etc/sysctl.conf に次の設定がある。

# Controls source route verification
net.ipv4.conf.default.rp_filter = 1

よって RHEL5 の場合、rp_filter の値は次のようになる。

[rhel5]# sysctl -a | grep '\.rp_filter' | sort
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.eth0.rp_filter = 1
net.ipv4.conf.eth1.rp_filter = 1
net.ipv4.conf.lo.rp_filter = 0

rp_filter の実効値は、eth0 であれば all.rp_filter AND eth0.rp_filter (=0)となり、eth0 の rp_filter は無効となる。つまり /etc/sysctl.conf にそれらしい設定がありながら、実は 全く効いていなかった ということ。騙された。

RHEL6 の場合は、

[rhel6]# sysctl -a | grep '\.rp_filter' | sort
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.eth0.rp_filter = 1
net.ipv4.conf.eth1.rp_filter = 1
net.ipv4.conf.lo.rp_filter = 1

今度は MAX(all.rp_filter, eth0.rp_filter) (=1)となり、rp_filter は有効となる。RHEL5 と全く同じ動作にしたいなら、/etc/sysctl.conf で net.ipv4.conf.default.rp_filter = 0 と設定する必要がある。

今回の目的(同一サブネットに複数インターフェイス)では、rp_filter = 2 にすれば良い。これは loose mode というらしく、いずれかのインターフェイスから到達可能な宛先であればパケットを受信する、というモードのようだ。RFC3704 なんて読む気ないので詳しくは知らない。

そもそも今回の件で rp_filter が影響することが分かり辛いが、極力プライマリインターフェイスで通信しようとする Linux の特性を考えると、何となく理解できなくもない。今回の場合、プライマリ側である eth0 が ARP パケットを処理する際に rp_filter が効くのだろう(と思う)。が、やはり Linux のこの特性は分かりにくい(直感的でない)と思う。

以上のように、Linux で複数インターフェイスを同一サブネットに繋ごうとすると、非常に微妙な領域に足を突っ込むことになる。やるなら 1 個のインターフェイスに仮想 IP アドレスを付ける方法(仮想インターフェイス)をお勧めする。じゃあ私は何故そうしないのかと言うと、現場 SE に「仮想 IP アドレス」とか言っても通じないから。少なくとも自力で設定できるとは思えない。しかし「1 つの LAN ポートに 1 つの IP アドレス」であれば、彼等にも理解してもらえる確率がグッと上がる。:-)

2012-09-02

Tomcat: Cannot stop in wrong hosts configuration

あるサーバーだけ、Tomcat の停止に失敗する。

2012/08/29 15:56:51 org.apache.coyote.http11.Http11Protocol pause
情報: Coyote HTTP/1.1を http-8080 で一時停止します
2012/08/29 16:00:00 org.apache.catalina.connector.Connector pause
致命的: プロトコルハンドラの一時停止に失敗しました
java.net.ConnectException: Connection timed out
	at java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
	at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
	at java.net.Socket.connect(Socket.java:529)
	at java.net.Socket.connect(Socket.java:478)
	at java.net.Socket.<init>(Socket.java:375)
	at java.net.Socket.<init>(Socket.java:218)
	at org.apache.jk.common.ChannelSocket.unLockSocket(ChannelSocket.java:492)
	at org.apache.jk.common.ChannelSocket.pause(ChannelSocket.java:288)
	at org.apache.jk.server.JkMain.pause(JkMain.java:726)
	at org.apache.jk.server.JkCoyoteHandler.pause(JkCoyoteHandler.java:153)
	at org.apache.catalina.connector.Connector.pause(Connector.java:1064)
	at org.apache.catalina.core.StandardService.stop(StandardService.java:578)
	at org.apache.catalina.core.StandardServer.stop(StandardServer.java:788)
	at org.apache.catalina.startup.Catalina.stop(Catalina.java:662)
	at org.apache.catalina.startup.Catalina$CatalinaShutdownHook.run(Catalina.java:706)
2012/08/29 16:00:01 org.apache.catalina.core.StandardService stop
情報: サービス Catalina を停止します

Tomcat バージョンも示しておくが、多分どのバージョンでも起こる。

[appserver]# service tomcat6 version | grep version
Server version: Apache Tomcat/6.0.35

ちなみにタイトルは「Cannot stop」としているが、正確には上記のタイムアウトに時間が掛かる(3 ~ 5 分)だけで、待ってさえいれば停止する。

最初は、何でシャットダウンするのに socket が timed out するのかと思ったが、自身のシャットダウンポートへ通信しているのではと勘付けば、ネットワークに問題がありそうだと察しが付く。(ソースコードは見てないので、実際のところは知らない)

[appserver]# ifconfig | grep 'inet addr'
          inet addr:172.16.1.10  Bcast:172.16.1.255  Mask:255.255.255.0
          inet addr:127.0.0.1  Mask:255.0.0.0

/etc/hosts:

# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1		localhost.localdomain localhost
::1		localhost6.localdomain6 localhost6
192.168.10.12	appserver

案の定、実際の IP アドレス(172.16.1.10)と /etc/hosts (192.168.10.12)が食い違っている。私が試した限り、それぞれが別ネットワーク(サブネット)だと今回のエラーになるようだ。食い違いがあっても、同じネットワークだと起こらない。

/etc/hosts を修正して、ネットワークを再起動すれば解決する。

# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1		appserver localhost.localdomain localhost
::1		localhost6.localdomain6 localhost6

所詮、現場 SE の程度なんてこんなもんだ。IP アドレスを変更する際に /etc/hosts に気を払うこともできない。ちなみに今回の場合、上記に加え /etc/resolve.conf も /etc/sysconfig/network もボロボロだったことを付け加えておこう。

そしてこういうことがあるから、特に理由のない限り、自ホスト名は「127.0.0.1」に登録するのが正しい。これについては以前のエントリで述べた通り。

127.0.0.1 ではなくサーバーの IP アドレスで登録すべき、と言われそうだが、それでは DHCP 環境で使えない。固定 IP アドレス環境でも、永遠に IP アドレスを変えないと保証できるはずもない。その際に IP アドレスを変更する SE が、/etc/hosts に気を回すスキルを持っていると期待するほど、私はお人好しじゃない。