<< 前へ | Home

PR: 今だから始める!ECショップ開業    こんなこともできる!Webサービス    結婚式は神前式で    エコカーがこれからの主流    本気の婚活!!    みんなのリサイクル意識    引越しのタイミング    語学を学ぶための基礎   

フルスクラッチから1日でCMSを作る シェルスクリプト高速開発手法入門 を読んだ

「フルスクラッチから1日でCMSを作る シェルスクリプト高速開発手法入門」を送っていただきました。

シェルスクリプトでWebアプリケーションを書いてしまう本で、それだけ聞くと単なるキワモノ系な感じがするかもしれないけれど、1冊で3度おいしい本。

まずWebアプリケーションの基本が学べる。というか理解していないと途中で付いていけなくなる恐れあり。しかしこのあたりは理解していないといけないところだと思うので、この本の内容が理解できなかったら、なんとかフレームワークに頼る前にきちんと調べて理解しておくべきだと思う。脆弱性まわりも丁寧に解説されていて素晴しい。

2つ目として、この本は良くあるトリッキーなコードはほとんど使われておらず、非常に純朴なシェルスクリプトで構築されている。それでもシェルスクリプトとそれを支えるツールの思わぬ使い方が学べる。自分もsort -Rでシャフルできるとか <<< を使うことで変数の内容を標準入力として使えるとかは知らなかった。

3つ目にエンジニアとして考え方の基礎が学べる。特にチューニングのところが良いし、なぜwhileを避けるべきかとか、ちゃんと理由が書かれている。あと割り切りがうまい。日本人ってとにかくこの割り切りというやつが苦手で「この程度で十分じゃない」というのが出来ずに無用に造り込んでしまうことが多い。特に面白かったのがサイトのアクセスカウンタのところ。普通ならカウンタ値が書かれたファイルを使うところだけど、そうすると同時アクセスされた時にどうやってカウンタを更新するのか、ロックするのかなどやっかいだ。この本では echo 1 >> counterでカウンタファイルを1バイトごとに大きくしていく。ファイルサイズ=アクセス数だ。アペンドだから同時更新に悩まなくて済む。そのかわりアクセス数が増えればカウンタファイルのサイズが無制限に膨らむことになる。しかしその程度のこといいではないか。仮に100万回その記事が読まれたとしても、たかだか1MBだ。今では大騒ぎするほどのサイズじゃない。

最後に、こういう本を出版してくれたKADOKAWAさんに拍手を送りたい。

鎌倉のあじさい

去年は行けなかった鎌倉。いつもながら凄い混雑だった。

左可井で、いつもの穴子丼。トイレが増設されて2つになってた。


浄妙寺へ。



いつもの猫さんとご対面


長谷寺へ。毎年新しい品種が増えている気がする




汗だくになりながら登っていく




複雑な色合い


これから色付くのかな







ほたるぶくろ




るいもが帰ってきた。

お花を幾つもいただいて、るいもは幸せに天に登って行けたと思います。


TracLightningのJenkinsのJob設定をまとめてやるためのメモ。

今のプロジェクトで、Jenkinsのビルドでたまにソースコードの中身が2重になる(1つのファイルに同じん内容が2回書かれている)状態になることがある。原因は不明で、どうもSubversionとWindowsとの食い合わせっぽい。Jenkinsのジョブ設定で、ワークスペースの更新のデフォルトがsvn updateになっているのを、新規チェックアウトにすると緩和される気がするので、ひとまず全部変更しておこうかと思ったものの、既に数100のジョブがあってとても手でやるのは無理。

JenkinsのAPIを使おうと思ったものの、隔絶環境なのでwgetもcurlも無ければ、Rubyも無くてスクリプト言語系はPerlのみ。Javaでゴリゴリ書くのは辛いなと途方に暮れていたところ、TracLightningなので中にPythonが入っていることを思い出し、ちょっと試してみる。

第一の難関はログインのところ。Firebugで見てみると、TracLightningのデフォルトはDigest認証のよう。これはPythonのurllib2に入っているHttpDigestAuthHandlerを使ってみたら、あっさり突破できた。あとは、ElementTreeをXMLパーサに使用すれば問題無し。以下はjobの一覧を読み出す例:

import urllib2
import xml.etree.ElementTree as ET
URL = 'http://server/jenkins/api/xml'
Realm = 'trac'
Username = 'username'
Password = 'password'

authhandler = urllib2.HTTPDigestAuthHandler()
authhandler.add_password(Realm, URL, Username, Password)
opener = urllib2.build_opener(authhandler)
urllib2.install_opener(opener)
page_content = urllib2.urlopen(URL).read()

elem = ET.fromstring(page_content)
for job in elem.findall(".//job"):
    print job.find(".//name").text
    print job.find("./url").text

以下はjob設定の読み出し例。GETリクエストで読み出し。POSTすれば更新できる。

import urllib2
import xml.etree.ElementTree as ET
URL = 'http://server/jenkins/job/xxx_job/config.xml'
Realm = 'trac'
Username = 'username'
Password = 'password'

authhandler = urllib2.HTTPDigestAuthHandler()
authhandler.add_password(Realm, URL, Username, Password)
opener = urllib2.build_opener(authhandler)
urllib2.install_opener(opener)
page_content = urllib2.urlopen(URL).read()

elem = ET.fromstring(page_content)
elem.find(".//scm/workspaceUpdater").set("class", "hudson.scm.subversion.CheckoutUpdater")
urllib2.urlopen(URL, ET.tostring(elem))

これらをまとめて、全てのジョブのワークスペース更新の方法を、svn updateから新規チェックアウトに変更する例:

import urllib2
import xml.etree.ElementTree as ET

class Jenkins:
    def __init__(self, url, userName, password):
        self.userName = userName
        self.password = password
        self.url = url if url.endswith('/') else url + '/'

    def _setCredential(self, url):
        authHandler = urllib2.HTTPDigestAuthHandler()
        authHandler.add_password('trac', url, self.userName, self.password)
        urllib2.install_opener(urllib2.build_opener(authHandler))

    def _createUrl(self, urlSuffix):
        return self.url + urllib2.quote(urlSuffix.encode('utf-8'))

    def _httpGet(self, urlSuffix):
        accessUrl = createUrl(urlSuffix)
        self.setCredential(accessUrl)
        content = urllib2.urlopen(accessUrl).read()
        return ET.fromstring(content)

    def _httpPost(self, urlSuffix, postXml):
        accessUrl = createUrl(urlSuffix)
        self._setCredential(accessUrl)
        urllib2.urlopen(accessUrl, ET.tostring(postXml))

    def getJobList(self):
        return self._httpGet('api/xml')

    def getJobSettings(self, jobName):
        return self._httpGet('job/%s/config.xml' % jobName)
        
    def setJobSettings(self, jobName, xml):
        self._httpPost('job/%s/config.xml' % jobName, xml)

if __name__ == '__main__':
    jenkins = Jenkins('http://your-server/jenkins', 'username', 'password')
    for job in jenkins.getJobList().findall(".//job"):
        jobName = job.find(".//name").text
        jobSettings = jenkins.getJobSettings(jobName)
        workUpdater = jobSettings.find(".//scm/workspaceUpdater")
        if not workUpdater is None:
            workUpdater.set("class", "hudson.scm.subversion.CheckoutUpdater")
            jenkins.setJobSettings(jobName, jobSettings)

隔絶環境でメモを取りながら作業したのでtypoとかあったらごめんなさい。

るいもとお別れ

るいもが今朝亡くなった。残念ながら18歳は迎えられなかったけど、るいもの兄弟の中では一番の長生きらしい。
ここ最近急速に弱っていたけど、食欲はうちの猫達の中で1番だったし、まだ1-2週間はもつんじゃないかと思っていた。しかし高齢には勝てなかったようで、あっという間に逝ってしまった。




ショパン プレリュード 第16番

ショパン プレリュード 第16番

昔、電子ピアノで録音したものもあるけど、その時と比べて荒々しい感じは表現できただろうか...

鸞鳳玉の花

鸞鳳玉の花が咲いた。

本門寺の桜

今年は、気付いたら梅の季節が終わっていて、桜もあっという間に咲き出した感じ。本門寺は5分咲きくらい?

























夕日の中の桜も、はかない感じで良い














蝋細工のよう
















このサイトの掲載内容は私自身の見解であり、必ずしもIBMの立場、戦略、意見を代表するものではありません。
日本アイ・ビー・エム 花井 志生 Since 1997.6.8