2008年2月29日金曜日

threading.Condition.wait @ python

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Timeoutをraiseしてほしいのですが・・・。

これは正しく動かない。waitが何で帰ってきたかを計時から判定するのは変。
取れているかもしれないのにTimeout扱いのときがある。

# We can't create a new resource, so we have to decide
# how we will wait for one to become available.
if timeoutSeconds:
# Raise an exception if a resource is not
# available within the given amount of seconds.
self.__availableCondition.wait(timeoutSeconds)
if (time.time() - startTime) >= timeoutSeconds:
raise TimeoutError(
"Unable to get resource within %s seconds"
% timeoutSeconds)


これにあるようにresultを用意するのは面倒だし。

condition.acquire()
try:
while not result:
condition.wait()
finally:
condition.release()


MLでもぎろんされたようだ。しかしここはreturnの値が問題としている。exceptionにすれば既存のコードに対する親和性は高いだろうに。

interruptもきかないらしい。ぎょえ~~。

彼女にinternetを説明した

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
あまりいい説明ができなかった。まとめはまあまあか?

- Domain NameとIPの対応付け(DNS)
- GlobalなIPとLocalなIP(192.168.x.xなど)
- GlobalとLocalなIPの対応付け
- IPアドレスに情報の小さい塊(packet)を送りつけることができる(IP)
- 順序等が保障されないからそれをどうにかする手順(TCP)
- いろんなソフトウェアがTCPを使いたいので、それを見分ける番号をつける(Port)
- 返事は送り手のIP/Portに戻ってくる。
- httpは80を使う。
- localからglobalにでる時に動的に対応付けを作れる。(IPマスカレード)
- 自宅でサーバを運用したいときは静的に対応付けを指定する必要がある。(NAT)
- プロバイダの向こう側は動的に経路が決まる。(自律システム)
- 192.168.2.100で192.168.2.200を盗聴できる。@mask 255.255.255.0
- 暗号の話
- 対称暗号
- 非対称暗号
- 公開鍵・秘密鍵
- デジタル署名
- 証明書チェーン

2008年2月28日木曜日

Telnet & Command Pattern

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
送受信を行うthreadへの指示をcommandで行うようにしたが、Commandがいっぱいあって実装がだるい。

threading and decorator

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
参考

処理内容はたいしたことないですが、threadでデータを受け取りながら、ほかのthreadで読み出し、読み出した量がある一定量を過ぎると、受け取りthreadのfilter関数を差し替えるということをやっています。

なぜpipeを使っているのかとはつっこまないこと。
関数の入れ子がアレゲなのですがlisp系の言語でないので我慢するしかない。

自動的にlockが起こるオブジェクトもつくれるが、基底クラスとして供給したときに複数のインスタンス間でのdead lockとかパフォーマンスの低下を考えると面倒だからパス。面白そうだけどね。

どのデータがthread間で共有されているのかコンシャスじゃないといけないが、pythonではそういうものだろう。Haskellみたいな言語だったらきっとちがうのだろうが。
これとかか?



#!/usr/bin/python

import os
import thread
import threading
import urllib2

def identity(x):
return x

def upper(x):
return x.upper()

def synchonized_with(lock):
def bind(critical_section):
def synchonized(*args, **kw):
lock.acquire()
try:
ret = critical_section(*args, **kw)
finally:
lock.release()
return ret
return synchonized
return bind


class Base:
_lock = threading.RLock()
proclist = []

@synchonized_with(_lock)
def handler(self):
if self.proclist:
proc = self.proclist[0]
self.proclist = self.proclist[:-1]
else:
proc = identity
return proc

def listener(self, fd):
try:
h = urllib2.urlopen('http://www.cnn.com')
while True:
buf = h.read(10)
handler = self.handler()
buf = handler(buf)
while buf:
n = os.write(fd, buf)
buf = buf[:-n]
finally:
os.close(fd)

@synchonized_with(_lock)
def add_handler(self):
self.proclist.append(upper)

def serve(self):
r, w = os.pipe()
thread.start_new_thread(self.listener, (w,))
try:
x = True
while True:
print os.read(r, 40)
if x:
self.add_handler()
x = not x
print os.read(r, 40)
finally:
os.close(r)

b = Base()
b.serve()

Metric

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
一応PyMetricを使おうかと思ってみたわけですよ。参考記事

buildbotのbuildプロセスに組み込めないかな?slocの集計とMcCabeが7を超えたやつをlistしてくれればよいのだが。

しかし、変な継承とか変なhookとかは引っかからないからなぁ。動的に調査するツールがないと限度があるな。もはや複雑さの原因はifじゃないから。

2008年2月27日水曜日

CallNameProxy

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
っても、xmlrpclibのServerProxyから抽出しただけなんだけど。
__handlerじゃなくて_handlerなのが味噌ですね。前者だと継承で上書きできません。

htmllibとかcmdのdo_xxxがどうしても好きになれないのです。


class CallNameProxy:
class Method:
def __init__(self, handler, name):
self._handler = handler
self.__name = name

def __getattr__(self, name):
# To Support nested call
return CallNameProxy.Method(self._handler, "%s.%s"%(self.__name, name))

def __call__(self, *args, **kw):
return self._handler(self.__name, args, kw)

def __repr__(self):
'''Need override for better printing'''
return ("")
__str__ = __repr__

def _handler(self, methodname, *args, **kw):
'''Must override to use'''
print 'override me!'

def __getattr__(self, name):
return CallNameProxy.Method(self._handler, name)

2008年2月26日火曜日

Be happy with loggin' raise

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
コード

#!/usr/bin/python
import logging

def raiser():
try:
1/0.0
except:
logging.exception('my except:')
raise

try:
raiser()
except Exception, why:
print 'printing', why
print 'printing', why.__class__


実行結果

[nori@Asama]/usr/lib64/python2.4% python ~/Desktop/work/test/loggingexception.py
ERROR:root:my except:
Traceback (most recent call last):
File "/home/nori/Desktop/work/test/loggingexception.py", line 6, in raiser
1/0.0
ZeroDivisionError: float division
printing float division
printing exceptions.ZeroDivisionError
[nori@Asama]/usr/lib64/python2.4% fg


「式を伴わない場合、raise は現在のスコープで最終的に有効になっている式を再送出します。そのような式が現在のスコープに全くない場合、エラーを示す例外が送出されます。」とあり、「最終的に有効になっている式」ってピンとこなかったけど発生したexceptionらしい。

蛇足:
「try 文には二つの形式: try...except および try...finally があります。これら二つの形式を混合することはできません (互いにネストすることはできます)。」とtry文の説明にありますが、python2.5ではできます。悪い機能じゃないけど、これだけが理由で2.5以前のpythonで動かなくなるのはアホ過ぎる。ネストすればいいだけだし、2.4以前を使っているディストリはそれなりにあるからだ。

参照:
6.9 raise 文 @ Python リファレンスマニュアル
7.4 try 文 @ Python リファレンスマニュアル
2.4 組み込み例外 @ Python ライブラリリファレンス

よーやくなぞが解けた。

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
os._exit(0)がきかないからへんだなぁ、と思っていたら、その前でexceptionを発生していて到達していなかったらしい。http handler内のどっかのexcept:に捕捉されてシカトされていたようだ。

ふい~~。exception 起きているであろう場所にtry/exceptを入れてloggingするようにする。

教訓::
Unit testのありがたみがなんとなく理解できるっぽい。single process single threadなら話はらくだが、forkするならされるmoduleのtestとエラー処理はちゃんとしておくべき。

2008年2月25日月曜日

more on XMLRPC server

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
A simple XML-RPC server @ASPN
コメントにthreadとsubprocessを使ったサンプル。

bug があるらしい。

これと同じとのこと。


SocketServer.ForkingMixIn.collect_children() does:

pid, status = os.waitpid(0, options)

By setting pid = 0, it will wait on any children, even
if the children were not started by the SocketServer.
This causes sporadic test failures:

うは。見つけていたら頭からこのバグに突っ込んでいたかも。
2.5.1にならないとなおらんだと・・・・。いかんなぁ。

解析に使うgnubg重いから、何かforkすることは確定なので。

loggingもせにゃならん。
- hathaway daemonは標準のloggingを使っている。ので、やっぱりloggingをつかう。
- 自前コードはimport logging + logging.debug/infoなどで好きにできる。
- XMLRPCはログをstderrにだす。どっかのパラメータで挙動かえられたっけ?
- コンストラクタの引数になにやら渡せばいい。ブツは何だろう?:SimpleXMLRPCServer(addr[, requestHandler[, logRequests]])
- Booleanぽい。今したいことはstderrに垂れ流す代わりにloggingを使ってほしいのだ。
- SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.log_request(self, code='-', size='-')Selectively log an accepted request.か?実装はこんな感じだ。

def log_request(self, code='-', size='-'):
"""Selectively log an accepted request."""

if self.server.logRequests:
BaseHTTPServer.BaseHTTPRequestHandler.log_request(self, code, size)


- 落とし穴
- Python で logging


logの問題。web.pyのコード。log_messageをオーバーライドしてあげればよいようだ。

def log_message(self, format, *args):
"""Log a message; overrides 'BaseHTTPRequestHandler.log_message'."""

# Write an Apache-style log entry via the server instance.
message = "%s - - [%s] %s\n" \
% (self.address_string(),
self.log_date_time_string(),
format%args)
self.server.LogMessage(message)


元のコード(from BaseHTTPServer.py)

def log_message(self, format, *args):
"""Log an arbitrary message.

This is used by all other logging functions. Override
it if you have specific logging wishes.

The first argument, FORMAT, is a format string for the
message to be logged. If the format string contains
any % escapes requiring parameters, they should be
specified as subsequent arguments (it's just like
printf!).

The client host and current date/time are prefixed to
every message.

"""

sys.stderr.write("%s - - [%s] %s\n" %
(self.address_string(),
self.log_date_time_string(),
format%args))

2008年2月20日水曜日

hostbasedauth@ssh, /etc/hosts, access from local

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
LANにたっているserverがある。

DNS
LANの入り口にあるRouterでNATしていてDNS(コンテンツサーバ)を動かしている。

HTTP
apacheは、name baseのvirtual hostで動いている。
localからみえるサービスと外から見えるがある。

sshしたい。LAN同士と外から中へ。中へ入るときはNATしている。
- sshの鍵はコピーしたくない。
- LAN内のマシンでsshしたい
http://209.85.175.104/search?q=cache:vQw6WVSviAMJ:scrapbook.ameba.jp/tsudoe-purograma_book/entry-10019581663.html+ssh+get_socket_address+cannot+get+local+ipaddr/name&hl=ja&ct=clnk&cd=1&gl=jp


以上の条件を満たすには、LAN内のマシン間はhostbaseのauthするしかないが、hostsの関係でうまくhost名が解決できない。別名を定義しているとsshdにけられてしまう。DNS cacheサーバを立てようにも、contentsサーバと並存は無理。

DNS cacheを用意せずにhostsから消すとserverの立っているホストからhttp://で公開しているサーバにアクセスできない。LANの中のサーバ自身を自分自身に向けてNATすることは無理があるらしい。

とりあずはhostsを直して撤収かな。このままではcodeのcommitも難しい。

ぶっちゃけこれでもいい。

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
http://www.ne.jp/asahi/tao/elis/bitfaq/s007.html

パイプでネットワークを越えることもできる.もちろんコマンドの機能を使うのだが,例えば次のようにする.

tar cfB - . | rsh host '(cd todir; tar xfBp -)'

tar のオプションに種類があるので,このままでは動かないことがあるが,tar でカレントディレクトリ以下のファイルをすべて標準出力に書き出し,rsh で遠くのホストの tar にパイプで接続する†.rsh は標準入出力をそのまま接続するし,cd はシェルの内蔵コマンドなので,これで tar 同士が繋がるのだ.パイプのように洗練された機能があってこそ,UNIX は生き長らえているのだ.

やりたいことはなんなのか?

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
分散関数呼び出し @ doukaku.orgに似たものなのではないだろうか?

gauche run-process

:host hostspec

この引数は、commandをリモートホストで実行させるのに使います。 hostspecの完全な構文はprotocol:user@hostname:portで、 protocol:、user@、:portの部分は省略可能です。 protocolはリモートに接続するプロトコルを指定します。現在のところ sshだけがサポートされており、また省略された場合もsshが使われます。userはリモートでのユーザ名を、hostnameはリモートホスト名を指定します。portはprotocolのデフォルト以外のポートを使いたい場合に指定します。

RPyC

rpycレビュー、日本語



現状ではど~~も簡潔さがたりない。

原因の見当をつけずに開発方針を変えてはいけません。

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
http://d.hatena.ne.jp/scinfaxi/20070211/1171149091

shiro 2007/02/13 07:04

原因の見当をつけずに開発方針を変えてはいけません。「動くはず」のものが「動いていない」のですから、どこかに見落としがあるはずです。それをそのままにしておいて別のやりかたで動いているように見えたとしても、さきほどの見落としがどこかに潜んでいないことをどうやって保証しますか? いつかそのバグが顕在化して噛みつかれるかもしれませんよ?
「なんとなくこうすれば動く」というレベルでは安定したものは作れません。「こう動くはず」と思ってその通り動くものがつくれないと。そうなるには、動くはずなのに動かないケースを徹底的に追求する経験が重要です。(そういう経験を積めば、そのうち設計の段階でひっかかりそうな「危険な臭い」を嗅ぎ分けられるようにもなります)。

2008年2月19日火曜日

pythonライブラリの落とし穴・・・module名

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
最近はまったもの
- os.kill
- signal.signal

むかしはまったもの
- shutil.mrtree
- os.makedires

同じモジュールの中にいてくれよ~~~。

signal @ python

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
signal moduleの中にsignalを発生させる関数が見当たらんが・・・?!?

とりあえず、あきらめ。signal.SIGCHLDでガマン。forkしなおすべ・・・。てか、serve_foreverを例外で抜けざるを得ないから、clientにも迷惑がかかる。orz。

しかし死んだ子プロセスのpidはframeからわかるのかね??
プロセスが死んだら計算結果を取りに行くのか・・・。


だめすぎ。


import time
import signal
import os


def handler(signum, frame):
print "child is gone"
print signal.SIGCHLD, signum
print dir(frame)

signal.signal(signal.SIGCHLD, handler)


if os.fork():
time.sleep(5)
else:
time.sleep(1)
os._exit(0)

print "done"

SimpleXMLRPCServerはConcurrentじゃない。

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
というだけこと。まあ、答えを返すまでの時間が短く、呼ばれる頻度が低く、ほぼ同時呼ばれるようなことがなければ特に問題はないのですが。

server.py

#!/usr/bin/python

import xmlrpclib
from SimpleXMLRPCServer import SimpleXMLRPCServer
import time
import os
import sys



server = SimpleXMLRPCServer(('localhost', 9000))

def fib(n):
server = xmlrpclib.ServerProxy('http://localhost:9000')
if n == 0:
return 0
elif n == 1:
return 1
return server.fib(n-1) + server.fib(n-2)

server.register_function(fib)
server.serve_forever()

n > 1でcallすると戻ってこない。fibを呼んでいる間にfibを呼び出せないから。
「帰り」のサーバを用意して、戻ってきたらos依存な方法で通知するの?なんだかなぁ・・・。


今思いつく解決策:

- ConcurrentなXMLRPCServerを持ってくるか、もしくは実装する。呼び出し側はその関数でBlockする・・・HTTPがTimeoutしねーか?

- 帰りのサーバを用意してfolkで生じた子プロセスからXMLRPCで呼び出してもらう。帰りのサーバから呼び出しもとのプロセスに通知する必要がある。

signal @ codezine。しかしsignal moduleの中にsignalを発生させる関数が見当たらんが・・・?!?

SimpleXMLRPCServer and fork

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
os._exit()の代わりにsys.exitでも一応動くが、子プロセス側でコネクションが腐るのでエラーメッセージがstderrに吐き出される。

os._exit fork xmlrpc @ google codeをみると当たり前。しかし、google webだと何もかからない。なにか壁があるらしい。

対処したい問題の解決にはなる(blockingなpopen2を使って処理をしたいのだが、それを引き起こすxmlrpc callはすぐに帰って次の要求を受け付けてほしい)のだが、最初の意図は2が先に帰ってきて、次に10が帰ってくることなのでそういう意味では解決になっていない。要は結果とそのタイミングを安易に取得したいのだが、callbackを設定しないと無理っぽい。


#!/usr/bin/python

import xmlrpclib
from SimpleXMLRPCServer import SimpleXMLRPCServer
import time
import os

server = SimpleXMLRPCServer(('localhost', 9000))

def sleep(n):
if os.fork() == 0:
time.sleep(n)
os._exit(0)
else:
return n

server.register_function(sleep)
server.serve_forever()

SimpleXMLRPCServerについての疑問

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
つぎのようなserverをたてておきます。

server.py

#!/usr/bin/python

import xmlrpclib
from SimpleXMLRPCServer import SimpleXMLRPCServer
import time

def sleep(n):
time.sleep(n)
return n

server = SimpleXMLRPCServer(('localhost', 9000))
server.register_function(sleep)
server.serve_forever()


んで、このclientでたたきます。
call.py

#!/usr/bin/python

import xmlrpclib
import sys

server = xmlrpclib.ServerProxy('http://localhost:9000')
print server.sleep(int(sys.argv[1]))


たたくときに

#!/bin/sh
python call.py 10 &
python call.py 2 &

とかします。
するとかならず

10
2

なにがいいたいかというと最初の呼び出しが返るまで次の呼び出しはブロックされているということです。

ブロックしないとなるとそれぞれの呼び出しにprocessもしくはスレッドを与えるしかないでしょう。しかし、rpcの中でforkしたら何がおこるんでしょうね。いい予感がしません。親はreturnしてclientに値を返しますが、もうひとつは処理が終わったらexitするのかな?

非同期な方法も考えましょう。
pygtkのmlへのポスト
twistedを使うことが一般的解決策らしいですが・・・ちょっと勉強が必要。

2008年2月18日月曜日

Lincense

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
なやんだらApache License 2.0がオススメ?

Buildbotその6--my コンセプト

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
  • Trigger
    • def pull()
    • Clock is a sort of Trigger.
    • Event commit etc is a sort of Trigger.
  • Build
    • is a procedure of software construction.
    • is a sort of remote script execution.
  • Slave
    • is an xmlrpc server.
    • is a Daemon process.(UNIX)
    • is a service(M$ Windows)
  • Task
    • set of Trigger(when), Build(what), Slave(who)
  • Result
    • is a collection, databasing.
    • Result and Task.
  • Interface
    • web based.
      • mod_wsgi?
      • stand alone server?

Buildbotその5

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
ドキュメント読んでいてもなんか好きになれない・・・。
buildの自動化ってもっと単純な気がするんだけど、buildbotはドキュメントが回りくどい。読んでいてむかついてくる。cfgもむかつく。何度も同じ名前をタイプさせるな。

1. buildを発生させたい条件
 a. commit
 b. 定時
 c. 手動
2. buildを行う実体
 a. どのmachine
 b. どのdaemon etc.
3. buildで行う作業
 a. checkoutの方法
 b. makeの方法
4. buildの結果報告
 a. web
 b. mail
 c. irc, etc.

基本的にはこれらの条件を指定すればいいわけだ。2,3なんて要はリモートのホストにスクリプトを注入して結果を取ってくる機能があれば実現できるわけで、設定作業というのはほぼスクリプトを書くことに他ならない。steps.SVNとかにはあまりセンスを感じない。結局スクリプトの一行一行に対してpopen2.Pope3みたいなことをするわけでしょ?だったらリモートホストで実行するスクリプトをそのままかかせろや。応用は利かないし、問題があったときに原因探すのがやりにくい。

1はフックの方法を指定することになる。BuildをTriggerするということで、Triggerと呼ぶけど、Buildの設定は、Buildの名前、Triggerの名前、slaveの名前、build scriptの名前のタプルを登録みたいなわかりやすい方法にしてほしいなぁ。
んで、TriggerのsubclassにtimerとhookがあってTimerは周期をとるし、hookはxmlrpc callとかsvnのpost-commitとか。

間違ってもTrigger生成でslaveやbuildの対象の名前を要求したりしてほしくない、その逆もね。

管理しているsourceの問題解析にはtimingはあんまり関係がない公算が高くて(build systemの問題は別)、どのマシンかという情報とrevistionが肝。gitのbisecみたいな機能もほしいね。てか、gitがbisecを実装しているのは微妙にやりすぎな気もする。bisecを提供するのは上位の仕事だと思う。bisec test.pyとかするとtest.pyがどのrevisionでこけるか調査してもらえるとか。

Buildbotその4

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
svnで失敗していたが、原因はなぜか$HOMEが/home/noriになっていたことだった。HOMEをbuildbotの設定から指定してもうまくいかない。slaveを起動するときにsudo -u buildbotとしていたためらしい。sudo -H -u buildbotとしたらうまくいった。

2008年2月17日日曜日

requires

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
setup.cfgに

[bdist_rpm]
requires = foo > 0.1
bar >= 0.2

とかすればいいのだが、fooのversion指定に=を使うとcfgパーサが混乱してしまう・・・。

Buildbotその3

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
なんか依存関係が設定されていない。
Zope.interfaceをuninstallしてもTwistedも消えないし、Twistedを消してもBuildbotが消えない。明日やるか。あ~~あ。

Twistedのsetup.pyは独自実装なので、zope.interfaceがinstallされていないとrpmを作ることができないという変わったつくり。

setup.cfgにrequiresを記述すればいいはずなのだが?!

rpm -qpR で検証しましょう・・・。

2008年2月16日土曜日

Buildbotその2

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
またしてもrpmがすんなり作れない。
で、setup.pyを書き換えた。

問題となったエラー:rpmbuildにemit.pyoがfile listにないけどインストールされたといわれる。



packages=["buildbot",
"buildbot.status", "buildbot.status.web",
"buildbot.changes",
"buildbot.steps",
"buildbot.process",
"buildbot.clients",
"buildbot.slave",
"buildbot.scripts",
"buildbot.test",
],

変更後

packages=["buildbot",
"buildbot.status", "buildbot.status.web",
"buildbot.changes",
"buildbot.steps",
"buildbot.process",
"buildbot.clients",
"buildbot.slave",
"buildbot.scripts",
"buildbot.test",
"buildbot.test.subdir",
],

Buildbot

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
twistedを落としてきてインストールを試みる。zope interfaceがないと動かないが、必要とされるバージョンがyumに登録されているものより新しいので自前でrpmを作る。zope interfaceはうまくいくのだが、twisted本体分のsdistを生成できない。はて。

[nori@Asama]~/Desktop/work/packaging/twisted/Twisted-2.5.0% python setup.py sdist
running sdist
warning: sdist: manifest template 'MANIFEST.in' does not exist (using default file list)
Traceback (most recent call last):
File "setup.py", line 108, in ?
dist.setup(**setup_args)
File "./twisted/python/dist.py", line 74, in setup
return core.setup(**kw)
File "/usr/lib64/python2.4/distutils/core.py", line 149, in setup
dist.run_commands()
File "/usr/lib64/python2.4/distutils/dist.py", line 946, in run_commands
self.run_command(cmd)
File "/usr/lib64/python2.4/distutils/dist.py", line 966, in run_command
cmd_obj.run()
File "/usr/lib64/python2.4/distutils/command/sdist.py", line 143, in run
self.get_file_list()
File "/usr/lib64/python2.4/distutils/command/sdist.py", line 240, in get_file_list
self.add_defaults()
File "/usr/lib64/python2.4/distutils/command/sdist.py", line 301, in add_defaults
self.filelist.extend(build_ext.get_source_files())
File "/usr/lib64/python2.4/distutils/command/build_ext.py", line 371, in get_source_files
self.check_extensions_list(self.extensions)
File "/usr/lib64/python2.4/distutils/command/build_ext.py", line 304, in check_extensions_list
(ext_name, build_info) = ext
TypeError: unpack non-sequence
Error: Subprocess exited with result 1 for project core

検索すると・・・
svnから直取りしなさい・・・そういうことじゃないだろ。
バグレポートにもでている。

これっぽい。

[#1811] setup.py bdist_rpm fails on FC5 for x86_64 (opened by troy@???) (CLOSED, duplicate)
defect core http://twistedmatrix.com/trac/ticket/1811


重複だといわれていて、統合された先はこいつ



On Red Hat EL4, Twisted 2.2.0 fails to build into RPMs with "python setup.py all bdist_rpm". Here are workarounds for two problems:

1. The detectExtensions hack in Twisted-2.2.0/twisted/python/dist.py setup() causes the build to fail. The build proceeds if this is commented out.

2. Except for the core and Conch, the components all have names in setup.py of the form "Twisted Something". This causes the RPM spec file to be invalid, as RPM package names cannot have spaces. A fix is to change the names to "TwistedSomething?".

2008年2月15日金曜日

commit時に自動的にrpm packageを生成する。

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
post-commitにフックするのだが、実行権限問題とrpm-buildをインスト&実行できるサーバに制限があることから、xmlrpcでリクエストを受け付けるサーバを書くことにした。で、ちょっと汎用的に書いたら任意のスクリプトを実行できるようになってしまった。makeでもキック可能。当然だけどセキュリティ上の問題を引き起こすので、これで立てたサーバを外部に公開しないように。urlのお尻に";rm"をつけてみるとか・・・。

スクリプトを実行する部分。

import string
import os
import popen2
import shutil
import tempfile


class FlyingCircus:
commands = ['$monty -V']

def __init__(self):
self.monty = 'python'

def expand_keyword(self, str, kw):
kw.update(self.__dict__)
t = string.Template(str)
return t.substitute(kw)

def apply(self, f, kw):
return [f(self.expand_keyword(cmd, kw)) for cmd in self.commands]

def get_result(self, s):
return s

def run(self, **kw):
def identity(cmd):
return cmd
def execute(cmd):
child = popen2.Popen3(cmd, capturestderr=True)
r = child.wait()
if os.WTERMSIG(r) or not os.WIFEXITED(r) or os.WEXITSTATUS(r):
raise child.childerr.read()
else:
return child.fromchild.read()
if "dry_run" in kw and kw['dry_run']:
f = identity
else:
f = execute
return self.get_result(''.join(self.apply(f, kw)))

class ScriptRunner(FlyingCircus):
def __init__(self):
self._cwd= os.getcwd()
self.working_dir = tempfile.mkdtemp()
os.chdir(self.working_dir)

def __del__(self):
os.chdir(self._cwd)
shutil.rmtree(self.working_dir)


rpmを作るサーバ。

import os
import xmlrpclib
from SimpleXMLRPCServer import SimpleXMLRPCServer
from daemon import Daemon
from ScriptRunner import ScriptRunner

class RPMPackager(ScriptRunner):
commands = ['svn checkout $src $working_dir',
'python $working_dir/setup.py bdist_rpm',]
def get_result(self, x):
fname = ''
dir = 'dist'
d = os.path.join(self.working_dir, dir)
for f in os.listdir(d):
if f.endswith('noarch.rpm'):
fname = os.path.join(self.working_dir, dir, f)
f = file(fname, 'r+b')
try:
return f.read(-1) #ugh!
finally:
f.close()

def on_commit(url):
p = RPMPackager()
return xmlrpclib.Binary(p.run(src=url))

class PackageDaemon(Daemon):
default_conf = '/home/nori/Desktop/work/autopackaging/my.conf'
section = 'Package'
def run(self):
server = SimpleXMLRPCServer(('localhost', 9000))
server.register_function(on_commit)
server.serve_forever()

2008年2月14日木曜日

ちょい投げやり。

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
例によって2space indent

Packagerの主要部分。

def prepare(self):
client= pysvn.Client()
try:
print "checking out"
print self.src
client.checkout(self.src, self.working_dir)
except pysvn.ClientError, e:
print 'failed to checkout'
print e
pass
def build(self):
bdist = popen2.Popen3(
'python %s/setup.py %s'%(self.working_dir, self.subcommand),
capturestderr=True)
return os.WIFEXITED(bdist.wait())


デーモン化

class PackageDaemon(Daemon):
default_conf = '/home/nori/Desktop/work/autopackaging/my.conf'
section = 'Package'
def run(self):
server = SimpleXMLRPCServer(('localhost', 9000))
server.register_function(on_commit)
server.serve_forever()


buildbotなるものがあるので調べることにしよう。

2008年2月13日水曜日

daemon化

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Tracより転載。

= Resources =
== article ==
* [http://labs.unoh.net/2007/04/unix.html from unoulabo]
* [http://www.velocityreviews.com/forums/t399413-creating-a-daemon-process-in-python.html "creating a daemon process in python" from velocityreviews ]
* [http://blog.ianbicking.org/daemon-best-practices.html]
* lots of nice comments. djb's deamon tools is not candidate, as I do not use djb dns.(I do not agree with his license!)

== code ==
* [http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731 "Creating a daemon the Python way" from ASPN]
* [http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66012 "Fork a daemon process on Unix" from ASPN]
* [http://hathawaymix.org/Software/Sketches/daemon.py from hathawaymix.org]
* it looks best but no license.
{{{
# - drop privileges
self.set_uid()
}}}
instead, I prefer to code this like. The original code has comments 'drop privileges' twice!
{{{
self.drop_privileges()
}}}
* [http://snippets.dzone.com/posts/show/1532 Python - create daemon from snippets.dzone.com]
* italian? commnets no good.
* [http://homepage.hispeed.ch/py430/python/ Unix Daemon @ Chris' Python Page]
* accoding to comment, it is descendant of "Fork a daemon process on Unix"
* [http://homepage.hispeed.ch/py430/python/daemon.py code]
* [http://www.void.in/wiki/Python/Daemon from www.void.in]

* [http://lowlife.jp/yasusii/stories/24.html Python と Twisted できみにも書ける Web サーバ(1)]
* It uses twisted. far Differ from other aproach.


以下、普通の。

Resources

article

code

revisorの代わりその5

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
うーむ。Yumで依存関係を解決するためにパッケージをインストールする機能でも依存関係の再帰的な解決をしているのでそこを流用できたかも。

2008年2月8日金曜日

rpm-build + post-commit

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
rpm-buildであってrpmbuildじゃない。Yumで探すときは気をつけてね。

さて、post-commitでrpmbuild and createrepoを考えているのですが権限が問題。apacheでbuildしたくないし、createrepoはapacheじゃなくてyumでやりたい。rpmbuildは絶対にapcheやroot権限で動かしたくない。本来ならサービス機にはインストールすらしたくない。

suid Python scrip とかできかれている。レスがないところを見ると、だれも問題にしていないらしい。ちなみにperlにはsuidperlなるものがあって足を打ち抜くことが簡単らしい。そもそもにscript
で権限を変えて実行することに無理がある気がする。スクリプトは所詮、インタプリタプログラムのデータに過ぎない。sudoだとインタプリタ自体が指定の権限で実行されているわけだ。スクリプトの#!/usr/bin/env xxxもloaderがそれを見てインタプリタに渡しなおしているだけだ。loaderはバイナリだったらメモリにロードするが。

と・・・こんなことを書いているときに解決策を思いついた。xmlrpcを使ってyum権限で走っているcreaterepo serverとbuild serverを用意して、そいつにたいしてrequestを投げる構造にしておけばええんでないかい?ちょっと大げさな気がしないでもないが。そしてxmlrpcが、私にとって「何もかも釘に見えるハンマー」と化しつつある。しかも開発機にserverを立てればアレだ、rpmbuildをサービス機に入れなくてすむ。

unix - permissionあれこれちょっと納得。

うが~~なソリューションたち


おお~~。
gaucheではbinaryを作ることでsetuidすることができる(正確にはバイナリのふりとあるが・・・)。
rubyのexerbpythonのpy2exeがあるが、Linux用のバイナリではない。

revisorの代わりその4

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
そもそも使えるものがあったのでね?

  • Mailing listを調べてみた。順番が逆だが。[Yum] Recursive dependency resolution Thu Apr 28 17:39:30 EDT 2005 listだけを生成する手段はないという結論が出ている

  • PungiDocs/GatherDocs


    Get package deps
    Loops through a package list and finds all the deps, then deps of deps, until there are no more packages.

    Get package objects
    Finds package objects in repos based on a package name in the package list.

    NIH指数たかめだべ。gather.py LL167 pungiでうまくいっていれば、そもそも作らないわけで、どうするかが問題。

revisorの代わりその3

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
cli.pyのこれがすべて。

def deplist(self, args):
"""cli wrapper method for findDeps method takes a list of packages and
returns a formatted deplist for that package"""

self.doRepoSetup()


for arg in args:
pkgs = []
ematch, match, umatch = self.pkgSack.matchPackageNames([arg])
for po in ematch + match:
pkgs.append(po)

results = self.findDeps(pkgs)
self.depListOutput(results)

return 0, []

pkgsとresultが何であるかが問題。で、resultはdepListOutをみてやればいい。

output.pyでこんな感じになっている。

def depListOutput(self, results):
"""take a list of findDeps results and 'pretty print' the output"""

for pkg in results.keys():
print "package: %s" % pkg.compactPrint()
if len(results[pkg].keys()) == 0:
print " No dependencies for this package"
continue

for req in results[pkg].keys():
reqlist = results[pkg][req]
print " dependency: %s" % prco_tuple_to_string(req)
if not reqlist:
print " Unsatisfied dependency"
continue

for po in reqlist:
print " provider: %s" % po.compactPrint()

んで、site-package/yum/__init__.pyの中で

def findDeps(self, pkgs):
"""Return the dependencies for a given package object list, as well
possible solutions for those dependencies.

Returns the deps as a dict of dicts:
packageobject = [reqs] = [list of satisfying pkgs]"""

results = {}
self.doRepoSetup()

for pkg in pkgs:
results[pkg] = {}
reqs = pkg.requires
reqs.sort()
pkgresults = results[pkg] # shorthand so we don't have to do the
# double bracket thing

for req in reqs:
(r,f,v) = req
if r.startswith('rpmlib('):
continue

satisfiers = []

for po in self.whatProvides(r, f, v):
satisfiers.append(po)

pkgresults[req] = satisfiers

return results


これらを参考にごにょごにょしてrdepなるコマンドを実装。

YUMBaseCli.__ini__ registerするコードを追加。

cli.py

self.registerCommand(yumcommands.DepListCommand())
self.registerCommand(yumcommands.RDepCommand())

def registerCommand(self, command):


本体

def rdep(self, args):
"""recursive define dependency list."""

self.doRepoSetup()

pkgs = []

for arg in args:
ematch, match, umatch = self.pkgSack.matchPackageNames([arg]
)
for po in ematch + match:
pkgs.append(po)

print 'pkgs:', pkgs
work = pkgs
results = {}
while work:
print len(work)
deps = self.findDeps(work)
work = []
for v in deps.values():
for x in v.values():
for po in x:
if po not in results:
results.update({po:None})
work.append(po)
results= self.findDeps(results.keys())
self.depListOutput(results)

return 0, []



yumcommands.py

コマンドの実装。rdepを呼ぶ。

class RDepCommand(YumCommand):
def getNames(self):
return ['rdep']

def doCheck(self, base, basecmd, extcmds):
checkPackageArg(base, basecmd, extcmds)

def doCommand(self, base, basecmd, extcmds):
base.verbose_logger.log(logginglevels.INFO_2, "Recursive dependen
cies: ")
try:
return base.rdep(extcmds)
except yum.Errors.YumBaseError, e:
return 1, [str(e)]



[nori@Asama]~/Desktop/work/custompackaging/tool% python yummain.py deplist busybox
Loading "installonlyn" plugin
Loading "fastestmirror" plugin
Finding dependencies:
Setting up repositories
Loading mirror speeds from cached hostfile
Reading repository metadata in from local files
package: busybox.x86_64 1:1.2.0-3.el5.centos
No dependencies for this package

[nori@Asama]~/Desktop/work/custompackaging/tool% python yummain.py rdep busybox
Loading "installonlyn" plugin
Loading "fastestmirror" plugin
Recursive dependencies:
Setting up repositories
Loading mirror speeds from cached hostfile
Reading repository metadata in from local files
pkgs: []
1
[nori@Asama]~/Desktop/work/custompackaging/tool% python yummain.py rdep bash | grep package:
package: tzdata.noarch 2006m-2.fc6
package: tzdata.noarch 2007c-1.el5
package: libgcc.i386 4.1.1-52.el5
package: glibc.i686 2.5-18.el5_1.1
package: bash.x86_64 3.1-16.1
package: filesystem.x86_64 2.4.0-1.el5.centos
package: libgcc.i386 4.1.2-14.el5
package: glibc-common.x86_64 2.5-12
package: basesystem.noarch 8.0-5.1.1.el5.centos
package: libtermcap.x86_64 2.0.8-46.1
package: tzdata.noarch 2007d-1.el5
package: tzdata.noarch 2007j-1.el5
package: glibc-common.x86_64 2.5-18.el5_1.1
package: glibc.x86_64 2.5-18.el5_1.1
package: mktemp.x86_64 3:1.5-23.2.2
package: setup.noarch 2.5.58-1.el5
package: glibc-common.x86_64 2.5-18
package: glibc.i686 2.5-12
package: libgcc.x86_64 4.1.2-14.el5
package: libgcc.x86_64 4.1.1-52.el5.2
package: tzdata.noarch 2007f-1.el5
package: glibc.i686 2.5-18
package: tzdata.noarch 2007d-1.el5
package: tzdata.noarch 2007h-1.el5
package: termcap.noarch 1:5.5-1.20060701.1
package: libgcc.x86_64 4.1.1-52.el5
package: glibc.x86_64 2.5-12
package: glibc.x86_64 2.5-18
package: libgcc.i386 4.1.1-52.el5.2
[nori@Asama]~/Desktop/work/custompackaging/tool% python yummain.py rdep python | grep package:
package: krb5-libs.x86_64 1.5-29
package: krb5-libs.i386 1.5-26
package: glib2.x86_64 2.12.3-2.fc6
package: libgcc.i386 4.1.1-52.el5
package: bash.x86_64 3.1-16.1
package: module-init-tools.x86_64 3.3-0.pre3.1.16.0.1.el5
package: cracklib.i386 2.8.9-3.3
package: krb5-libs.x86_64 1.5-23
package: grep.x86_64 2.5.1-54.2.el5
package: libtermcap.x86_64 2.0.8-46.1
package: net-tools.x86_64 1.60-73
package: tzdata.noarch 2007f-1.el5
package: findutils.x86_64 1:4.2.27-4.1
package: krb5-libs.x86_64 1.5-26
package: krb5-libs.i386 1.6.1-17.el5
package: e2fsprogs-libs.x86_64 1.39-8.el5
package: libstdc++.x86_64 4.1.2-14.el5
package: openssl.x86_64 0.9.8b-8.3.el5_0.2
package: krb5-libs.x86_64 1.5-28
package: setup.noarch 2.5.58-1.el5
package: libacl.x86_64 2.2.39-2.1.el5
package: initscripts.x86_64 8.45.14.EL-1.el5.centos.1
package: libgcc.x86_64 4.1.1-52.el5.2
package: device-mapper.i386 1.02.20-1.el5
package: pcre.x86_64 6.6-2.el5_1.7
package: e2fsprogs.x86_64 1.39-10.el5
package: mcstrans.x86_64 0.1.10-1.el5
package: chkconfig.x86_64 1.3.30.1-1
package: audit-libs.i386 1.5.5-7.el5
package: termcap.noarch 1:5.5-1.20060701.1
package: libgcc.x86_64 4.1.1-52.el5
package: krb5-libs.i386 1.5-29
package: openssl.i686 0.9.8b-8.3.el5_0.2
package: bzip2-libs.x86_64 1.0.3-3
package: tzdata.noarch 2007c-1.el5
package: openssl.i686 0.9.8b-8.3.el5_0.2
package: audit-libs.x86_64 1.5.5-7.el5
package: libselinux.x86_64 1.33.4-4.el5
package: device-mapper.x86_64 1.02.20-1.el5
package: glibc.i686 2.5-18.el5_1.1
package: pcre.x86_64 6.6-1.1
package: initscripts.x86_64 8.45.17.EL-1.el5.centos.1
package: libgcc.i386 4.1.2-14.el5
package: basesystem.noarch 8.0-5.1.1.el5.centos
package: centos-release.x86_64 10:5-1.0.el5.centos.1
package: krb5-libs.x86_64 1.5-17
package: keyutils-libs.i386 1.2-1.el5
package: python.x86_64 2.4.3-19.el5
package: tzdata.noarch 2007j-1.el5
package: psmisc.x86_64 22.2-5
package: ethtool.x86_64 5-1.el5
package: ncurses.x86_64 5.5-24.20060715
package: libgcc.x86_64 4.1.2-14.el5
package: procps.x86_64 3.2.7-8.1.el5
package: shadow-utils.x86_64 2:4.0.17-12.el5
package: libacl.x86_64 2.2.39-1.1
package: pam.x86_64 0.99.6.2-3.14.el5
package: db4.x86_64 4.3.29-9.fc6
package: audit-libs.i386 1.3.1-1.el5
package: libselinux.i386 1.33.4-4.el5
package: libselinux.i386 1.33.4-2.el5
package: openssl.x86_64 0.9.8b-8.3.el5_0.2
package: e2fsprogs-libs.i386 1.39-10.el5
package: popt.x86_64 1.10.2-47.el5
package: popt.x86_64 1.10.2-37.el5
package: glibc.x86_64 2.5-12
package: coreutils.x86_64 5.97-12.1.el5
package: gawk.x86_64 3.1.5-14.el5
package: libgcc.i386 4.1.1-52.el5.2
package: centos-release-notes.x86_64 5.1.0-2
package: tzdata.noarch 2006m-2.fc6
package: sed.x86_64 4.1.5-5.fc6
package: filesystem.x86_64 2.4.0-1.el5.centos
package: util-linux.x86_64 2.13-0.45.el5_1.1
package: cracklib.x86_64 2.8.9-3.3
package: sysklogd.x86_64 1.4.1-39.2
package: pam.i386 0.99.6.2-3.14.el5
package: zlib.i386 1.2.3-3
package: krb5-libs.x86_64 1.6.1-17.el5
package: device-mapper.i386 1.02.13-1.el5
package: krb5-libs.i386 1.5-23
package: iputils.x86_64 20020927-43.el5
package: krb5-libs.i386 1.5-28
package: pam.x86_64 0.99.6.2-3.26.el5
package: glibc-common.x86_64 2.5-18.el5_1.1
package: module-init-tools.x86_64 3.3-0.pre3.1.16.el5
package: util-linux.x86_64 2.13-0.44.el5
package: udev.x86_64 095-14.9.el5
package: glibc-common.x86_64 2.5-18
package: glibc.i686 2.5-12
package: openssl.i686 0.9.8b-8.3.el5
package: krb5-libs.i386 1.5-17
package: libstdc++.x86_64 4.1.1-52.el5.2
package: zlib.x86_64 1.2.3-3
package: libsepol.x86_64 1.15.2-1.el5
package: audit-libs.x86_64 1.3.1-1.el5
package: sysklogd.x86_64 1.4.1-40.el5
package: cracklib.x86_64 2.8.9-3.1
package: openssl.x86_64 0.9.8b-8.3.el5
package: mingetty.x86_64 1.07-5.2.2
package: readline.x86_64 5.1-1.1
package: glibc.i686 2.5-18
package: glibc.x86_64 2.5-18
package: gdbm.x86_64 1.8.0-26.2.1
package: tzdata.noarch 2007d-1.el5
package: tzdata.noarch 2007h-1.el5
package: keyutils-libs.x86_64 1.2-1.el5
package: centos-release.x86_64 10:5-0.0.el5.centos.2
package: pam.i386 0.99.6.2-3.26.el5
package: glibc-common.x86_64 2.5-12
package: mktemp.x86_64 3:1.5-23.2.2
package: centos-release-notes.x86_64 5.0.0-2
package: mcstrans.x86_64 0.2.6-1.el5
package: libselinux.x86_64 1.33.4-2.el5
package: e2fsprogs-libs.x86_64 1.39-10.el5
package: libattr.x86_64 2.4.32-1.1
package: iproute.x86_64 2.6.18-4.el5
package: tzdata.noarch 2007d-1.el5
package: info.x86_64 4.8-14.el5
package: pcre.x86_64 6.6-2.el5_1.1
package: device-mapper.x86_64 1.02.13-1.el5
package: SysVinit.x86_64 2.86-14
package: pcre.x86_64 6.6-2.el5_0.1
package: udev.x86_64 095-14.5.el5
package: e2fsprogs-libs.i386 1.39-8.el5
package: e2fsprogs.x86_64 1.39-8.el5
package: glibc.x86_64 2.5-18.el5_1.1
package: util-linux.x86_64 2.13-0.45.el5
package: module-init-tools.x86_64 3.3-0.pre3.1.34.el5
package: libstdc++.x86_64 4.1.1-52.el5
package: MAKEDEV.x86_64 3.23-1.2
package: libcap.x86_64 1.10-26
package: cracklib-dicts.x86_64 2.8.9-3.3
package: cracklib.i386 2.8.9-3.1
package: cracklib-dicts.x86_64 2.8.9-3.1
package: libsepol.i386 1.15.2-1.el5

2008年2月7日木曜日

revisorの代わりその2

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
どのrpmが必要かを決める必要がある。
そのためには最終的に入っていてほしいrpmがどのrpmに依存しているかを再帰的に探す必要がある。
となると、yum deplist で実行した結果で返ってくるdependencyで出てくるproviderを引数に渡してもう一度yum deplistを呼べばいいことになる。pythonからyumを呼び出すライブラリがあれば簡単にできそう。

yum deplistに相当するメソッドを呼んだときに得られる結果を辞書に突っ込んでいって辞書が大きくならなくなったときが終わり。

起動不良

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
しっかし再起動しようとすると起動したりしなかったり。

- HDDが認識されない。
- Overclock失敗だよメッセージがBIOSから出される。

電圧不足が原因と見て電源からの結線を変えてみたが確信を持てず。
600Wの電源で、買った当時はなんともなかったし、いままで停めたときやbackplaneをやめたときも問題がなかった。う~~ん。いつぞやの容量計算ソフトは700Wを勧めていた気がするのでちょっとちぇっくじゃ。

今使っているのはOWLTECHのこれ

電源投入時は、ディスクやファンを始動しなきゃいけなくてそのため電力がでかいのだろう。このへんを見る限り、15Wくらいは使うようだ。ファンは6Wくらい。

となると、disk4本Fan1本の1Uで70Wは見なきゃいけない。2Uで140w。
筐体Fanがほかに2本、DVDドライブは15W食うだろう。これでさらに30W
CPU/MBは?CPU 105W, MB165らしい
これは、参考になった。

やっぱり700Wの電源を買うかぁ・・・。あとはUSB HDDのガワとあたらしい予備HDDか。

電源の候補は
- オウルテック SS-700HM
- Antec True Power Quattro TPQ-850

今使っているのはSS-600HM

rebuild

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク


tw_cliで見る限り、うまくいっているようだ。しかし時間がかかる。風呂は行っている間に10%しか進んでいない。修復している間にカウンターパートが死ぬと駄目だね。そしてそのキケンはそれなりにある。10といえども過信は禁物だ。

HDD交換

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
S.M.A.R.T.が32を返していたことにず~~~と気づいていなかったらしい。
ともあれキモイので交換。

32が返ってきたのでBit5がたっていたということだから、

man smartctlより

Bit 5: SMART status check returned "DISK OK" but we found that some
(usage or prefail) Attributes have been <= threshold at some
time in the past.


か。

それよりraidのrebuildがちゃんと完了できるのか心配。
ついでに内部の掃除もした。

アクセスLEDがないのでなにが起こっているのかさっぱりわからん。

rebuildが完了したら組みなおさないと。やっぱりbackplaneはずしたの失敗かしら。
箱の外を引き回せるほうRAIDのほうがいいような気がする。
いちいち本体の箱をあけるのはうざすぎ。整備性わるし。

2008年2月6日水曜日

ここまでの調査のまとめ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
勘違いもあるかもしれんが、とりあえず書き出して頭をすっきりさせたい。

実装としてのfsとサービスとしてのfs(ボリューム?)がある。
-サービスとしてのfsは、実装としてのfsとデータと名前を持つ。
- ramfsは実装(VFSのcache機構を利用している。dirtyなままなcache)
- rdは実装(block deviceなram disk, 1ファイル・・・。)のためのdiskで中身はext3とか?
- initrdはfsじゃないサービスで、rdをrootとしてmountする。これができた当時はrootfsがなかった。
- initramfsはサービスとしてのfs。
実装はramfsで、format はcpio
- rootfsはサービスとしてのfs。
 実装はramfs?
ほかのfs(サービスとしてのfs)をマウントするためのfs、すべてをぶら下げるための「出っ張り」

initramfsは、/initのための情報・コードが入っている。ので、initramfs内での位置をカーネルが知っていないとシステムが立ち上がらない(カーネルイメージにリンクされる)。立ち上がったあと、switch_rootで本来のHDDやらなにやらからなるfsをrootfsにmountする。

んで~~~なんでkernel以外にfile systemにおいておきたいモノがあるのか?
それらは何かという問いに答えると多分すっきりする。
early-userspace
より抜粋
Linux カーネルのブート中に利用可能である必要はあるのだけれども
カーネル自身の内部で実行する必要はない

ものが詰まっている。

ではそれらは具体的になんであってどのような順序で実行されて、
カスタマイズする際はどのようにやれば目標を達成することができるのか?

固めるだけならcpioでもよいのだが、kernelから実行されるように
固めなければならない。entryはどこか?というのも問題。

再び
ramfs-rootfs-initramfs.txt
より抜粋

起動初期ユーザスペースへの移行が必要なのは、実ルートデバイスの検出とマ
ウントが複雑なためです。ルートパーティションは複数のデバイスに分散する
事があります(RAID または分離ジャーナル)。ルートパーティションはネット
ワーク越しになる事があります(DHCP、特定の MAC アドレスの設定、サーバへ
のログイン、等)。ン、等が必要な場合があります)。ルートパーティションが
リムーバブルメディア上にある場合は、動的にデバイスのメジャー/マイナー
番号が付けられており、固定名称とするためには、完全な udev 実装によって
解決しなければなりません。ルートパーティションは圧縮、暗号化、
copy-on-write、ループバックマウント、特殊な分割、その他あれこれされる
事があります。


initramfs VIVERの技術

(ブートパラメータの解釈、ハードウェア認識、カーネルモジュールの
ロード、デバイスノードの作成、ネットワークの起動、HDDのマウント

fatboot、liveCDとかほかのdistributionのinitramfsを
cpioであけて見てみるのも一つの方法ですね。

initramfs

initramfs作成支援スクリプト

initramfs-toolsの解説プレゼン

ちょっと違うなぁ・・・
rhel boot-init-shutdonw-process

2008年2月5日火曜日

revisorの代わり

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
build-a-custom-centos-5-install-cd
を試し始めてみた。

$ tar -cf - . | ( cd ~/build/c5disc1 ; tar -xvpf - )

cfのあとと、-と.の間はspace。まあ、|があるから標準出力に出すのだが。で、標準出力で受け取って解凍。しかしなんでcpじゃないのか?つう疑問があるが、cpじゃイケなんだろうね。filesystemがちがうからかな?あとはアレ、ファイル名か。iso9660って制限があるからなぁ。しかしext3のほうがゆるいから問題ないとおもうのだが展開されたりしちゃうのかね?

- アプリだけじゃなくてOSも入れ替えたいとするとこのへんかな?
- このへんもよさげ。
いままでぜんぜんほしい情報が手に入らなかったのは検索語が悪かったためらしい。

googleで"iso9660 cp"で一杯引っかかる。cpioとかinitrdとかだともっと効率がよさそう。

TightVNC

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
TightVNCを使っていて不満なのは、ctrl+tabとかがwindows側に食われてしまってremote側のfocus windowの変更に使えないこと。Tight VNCになんかモード無いのかしら?

revisor

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
revisorの記事なのだがその昔、こいつで自分の環境を一発再構築できるDVDを焼こうかとたくらんだことがあったが、revisorがうまくCentOS5で動かなくてあきらめた。

さて、最近はどうなのやら

yumに聞いてみたらconflicts with centos-release < 5だとさ・・・。4.xじゃないとだめよか。
Revisor, 2.0.4.1-2からはCentos5のdiskを作れるが、Centos5にはインストールできないようだ。

cfengine
puppet
も要チェックだ。

とりあえず、gitを使ってsourceを落とし見ることにした。makeしたらインストできない原因がわかるかも。

2008年2月4日月曜日

ぼんやりおもった。

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
非演算子がある演算に関して閉じていることはプログラムとか数学において大事らしい。たとえばsqlとかは、対象になるデータと出力結果は同じ「型」を持っている。プログラムのたちばからいうと、応用・拡張性に富むわけだ。

igoogleをみておもったことは彼らのガジェットはweb上で閉じることに意味があるのかなぁとおもった。

2008年2月2日土曜日

いい方法が思いつかない。

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
情報オリンピック2006年度国内本選@どうかく

nチームの参加しているときに
- Piをチームiの順位
- Siをチームiのスコア
- Rijをチームiとチームjの対戦結果
とすると、

0 < i <= nな任意のiについて 
Pi + Si = n
が成り立つ

これを使うと早く計算できる方法がありそうな気がするのだが・・・。

ちなみにa)の証明自体は帰納法を使う。n+1のテーブルから全勝のチームを除外してnに帰結させればよい。

全部の組み合わせを生成するO(2^n)なやりかたは駄目コードを叩きのめしたいという出題者の思う壺だろう。

よいやりかたじゃないと計算量が採点基準に引っかかるように作られた出題だ。設問3でも正方形を作る4点を選ぶやり方と2点から計算でのこりの候補を絞るやり方では計算量が違いすぎる。前者だと得点できないはず。

・・・・・

解説をよんで納得。やっぱり採点基準は考えられているという読みはあたっていた。
しかし効率のよい解法がエレガントだなぁ。