2015-03-31

Bash: Number of CPU cores

インフラを自動化していると、CPU コア数に応じてパラメーターを変えたい、ということがある。Python では /proc/cpuinfo からそれらを計算するライブラリを自作しているのだが、書き捨てスクリプト、特に Bash で同じことをやりたい。

もちろん Bash でも頑張れば可能ではある。しかし、書き捨てスクリプトでは「空で書ける」ことが重要。欲を言えば、Linux 間で可搬性があるとなお良い。

実は以前にも調べたことがあって、その時は満足のいく方法が見つからなかった。最近になってまた調べると、かなり良さげな方法を見つけることができた。

これを参考にして、

cpuinfo.sh:

#!/bin/bash

ncpu_sockets() {
    cat /proc/cpuinfo \
	| grep -P '^physical id\s*:' \
	| sort -u \
	| wc -l
}

ncpu_cores() {
    cat /proc/cpuinfo \
	| grep -P '^(physical|core) id\s*:' \
	| paste - - \
	| sort -u \
	| wc -l
}

ncpu_processors() {
    cat /proc/cpuinfo \
	| grep -P '^processor\s*:' \
	| wc -l
}

echo sockets = $(ncpu_sockets)
echo cores = $(ncpu_cores)
echo processors = $(ncpu_processors)
# grep '^model name' /proc/cpuinfo | head -1
model name      : Intel(R) Xeon(R) CPU           E5640  @ 2.67GHz

# bash cpuinfo.sh
sockets = 2
cores = 8
processors = 16

やっていることのロジックを理解すれば、これくらいなら空で書くのも難しくない。paste コマンドが初見だったが、手持ちの RedHat 系 OS を見た限り何処にでも入っている基本コマンドのようなので、可搬性も問題ないだろう。

2015-02-18

Python: Unbuffered read and write

今回の環境。少し古いのは、そんな環境でも動かす必要があるから。

# cat /etc/redhat-release
CentOS release 5.5 (Final)

# rpm -q python
python-2.4.3-27.el5

長年システムの仕事をしていると、例えば「出力にタイムスタンプを付けたい」とかいうことが一度くらいはあるはず。普段そんな時は Perl でサクッと作るのだが、今回は訳あって Python を使う必要があった。

この手のスクリプトで考えるべきは、バッファリング制御。Python にもこの手のパターンというのがあって、少しググれば stackoverflow とかに山ほどスレッドが見つかる。

timestamp.py:

#!/usr/bin/python

import fileinput
import os
import signal
import sys
import time

sys.stdin = os.fdopen(sys.stdin.fileno(), 'rb', 0)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
signal.signal(signal.SIGPIPE, signal.SIG_DFL)

def main():
    for line in fileinput.input(sys.argv[1:]):
        sys.stdout.write(time.strftime('%F %T ') + line)
    return 0

if __name__ == '__main__':
    sys.exit(main())

上記で、fdopen の「おまじない」部分がそれに当たる。これで標準入出力のバッファリングを無効にしている。その下の signal 云々は、忌まわしき broken pipe を封じる呪文。これも Python 暗黒面の 1 つ。

と作ったスクリプトだが、

# ping -c 5 127.0.0.1 | python timestamp.py -
2015-02-18 18:41:42 PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
2015-02-18 18:41:42 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.016 ms
2015-02-18 18:41:42 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.014 ms
2015-02-18 18:41:42 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.009 ms
2015-02-18 18:41:42 64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.009 ms
2015-02-18 18:41:42 64 bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.016 ms
2015-02-18 18:41:42 
2015-02-18 18:41:42 --- 127.0.0.1 ping statistics ---
2015-02-18 18:41:42 5 packets transmitted, 5 received, 0% packet loss, time 3999ms
2015-02-03 18:41:42 rtt min/avg/max/mdev = 0.009/0.012/0.016/0.005 ms

全然効いてなーい。めっちゃバッファリングしてる。

前述のおまじない以外にも、Python の起動オプション -u でバッファリングを無効にできるが、それでやっても結果は変わらず。訳が分からないので help & man を良く読んでみる。

# python -h

<...snip...>

-u     : unbuffered binary stdout and stderr (also PYTHONUNBUFFERED=x)
         see man page for details on internal buffering relating to '-u'

# man python

<...snip...>

       -u     Force stdin, stdout and stderr to  be  totally  unbuffered.   On
              systems  where  it matters, also put stdin, stdout and stderr in
              binary mode.  Note that there is internal  buffering  in  xread-
              lines(),  readlines()  and  file-object  iterators ("for line in
              sys.stdin") which is not influenced by  this  option.   To  work
              around  this, you will want to use "sys.stdin.readline()" inside
              a "while 1:" loop.

man の方に衝撃的なことが書いてある。「xreadlines, readlines, ファイルオブジェクトイテレーターは内部バッファリングするから、while + readline を使えよ」って、それってあんまりじゃね? readlines の方はともかく、イテレーターの方は裏切られた気持ちで一杯だ。

と文句を言っても仕方がないので、while + readline で書き直してみる。

def main():
    readline = fileinput.input(sys.argv[1:]).readline
    while True:
        line = readline()
        if not line:
            break
        sys.stdout.write(time.strftime('%F %T ') + line)
    return 0

しかし結果は全く変わらず。もしかして、と思い fileinput の実装を見てみると、

案の定、FileInput.readline で readlines を呼んでおり、ここでバッファリングされるらしい。Python3 でも改善は見られず。なんだよ、fileinput 使えねー。今までファイル入力にはずっと fileinput を使ってきたのに、今後は考え直した方が良さそうだ。

そんなこんなで、最終的には下記のようになった。iter(fh.readline, '') の意味は各自で調べて欲しい。私も今回初めてこの使い方を知った。

timestamp.py:

#!/usr/bin/python

import signal
import sys
import time

signal.signal(signal.SIGPIPE, signal.SIG_DFL)

def main():
    strftime = time.strftime
    write = sys.stdout.write
    for arg in sys.argv[1:]:
        fh = arg == '-' and sys.stdin or open(arg)
        try:
            for line in iter(fh.readline, ''):
                write(strftime('%F %T ') + line)
        finally:
            if fh is not sys.stdin:
                fh.close()
    return 0

if __name__ == '__main__':
    sys.exit(main())
# ping -c 5 127.0.0.1 | python timestamp.py -
2015-02-18 18:46:36 PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
2015-02-18 18:46:36 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.019 ms
2015-02-18 18:46:37 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.012 ms
2015-02-18 18:46:38 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.011 ms
2015-02-18 18:46:39 64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.009 ms
2015-02-18 18:46:40 64 bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.009 ms
2015-02-18 18:46:40 
2015-02-18 18:46:40 --- 127.0.0.1 ping statistics ---
2015-02-18 18:46:40 5 packets transmitted, 5 received, 0% packet loss, time 3999ms
2015-02-03 18:46:40 rtt min/avg/max/mdev = 0.009/0.012/0.019/0.003 ms

fdopen のおまじない部分は、なくても動いたので削除した。公式ドキュメントによれば、標準入出力は「行バッファリング」が規定値らしいので、今回の用途ではこれで良さそうだ。

A negative bufsize means to use the system default, which is usually line buffered for tty devices and fully buffered for other files. If omitted, the system default is used.

結局のところ、

  • ファイルオブジェクトイテレーターが入力をバッファリングする
  • fileinput に至っては、Fileinput.readline でさえも入力をバッファリングする

というのが事の元凶だったらしい。特に fileinput、お前はこの手のリアルタイム入力には二度と使わねえ。

まさかこんな単純なスクリプトでここまでハマるとは思わなかった。これでまた 1 つ Python が嫌いになった。使えば使うほど嫌いになっていくのが Python、使うほど手に馴染むのが Perl。:-)


2016-07-18 追記

fileinput の方は、最近になって修正されたっぽい。たぶん 2.7.12 と 3.5.2 から。動作は未確認。

2015-01-31

Animes in the 4th quarter of 2014

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

どう見てもタツミが主人公な件。途中から敵側キャストも拡充されるが、余り盛り上がらずに終息。まあ「どちらかが死ぬ」という設定上、最後が尻すぼみになるのは必然とも言える。

前作は未見。頑張り屋さんのイイ話系かと思ったら、ヒロインが結構ヘタレなのでそうでもない。萌えられるキャラも居なかったが、短尺(15 分)なので見るのは楽だった。

前作からの視聴。相変わらず脚本は聞いている側が恥ずかしくなるレベル。最早ネタのために見てるといっても過言ではない。もちろん次回も見るつもり。

初見で期待してなかったが、やたらと女子キャラのリアクションが可愛い。特にひおたんが秀逸で、監督が苛めたくなる気持ちも分かる。これは是非続きをやってもらいたい。

これこそ私が見たかった正当な Fate な感。しかし主人公が理想を口にするだけのヘタレなことが分かって幻滅。Fate ルートは未視聴だが、見なくても大体予想がついた。多分シリーズでは Fate/Zero が一番ではあるまいか。

ゲーム原作なので全く期待してなかったが、見事に裏切ってくれた。話はもう一押し欲しいが、これだけ丁寧に作り込んでいることに好感が持てる。他のゲーム原作アニメも少しは見習え。

チョロいヒロインにツンデレ彼氏、少女マンガの典型パターン。男が見ても面白味はないが、イケメンなんかに負けないっ→イケメンには勝てなかったよ、に置き換えれば少しは楽しめるか。

何でも脚本が有名人とのことで注意深く視聴していたが、特に何も感じなかった。と言いながら最終話はちょっと涙出してたけど、年寄りは涙腺が弱いので当てにならない。

タイムループ物にしては最後を綺麗に纏めてきたような気もする。が、実は余り良く理解できていない。かといって復習する気もなし。元ネタがエロゲだとは後日知った。

これが噂の進撃(集英社版)ですか。最初は面白く見ていたのだが、火星に降りたくらいから飽きてきた。ゴキがバカっぽいのが原因だと思う。昆虫の勉強には良いのではないかと。

話の内容に言うことはないが、前期に続いて後期もいきなり終わり過ぎ。せめて区切りのある終わり方にしてくれ。劇場版が控えていることは理由にならない。

往年の SEGA 作品が見れて楽しいのだが、ゲーム紹介に留まっていて、当時を生きた老人としては全然足りない。ハードとしてのサターンは好きではなかったが、本サターン(SD キャラ)は可愛くて仕方がない。

主人公強い・ハーレム・ラッキースケベという定番パターンの詰め合わせ。取りあえず、「アーカイブに接続、テーマを実行する」とさえ言っておけば大体合ってる。

清々しい程の中二病に格好良ささえ感じる。各キャラも個性があり絵も綺麗、話も基本コミカルで安心して見れる。この雰囲気を崩さずに、是非第二期をやって欲しい。

魔法少女が不幸を背負うようになったのは、まどマギの罪だと思う。どう終わらせるのか注目していたら、理不尽なハッピーエンドになった。この評価は分かれそうだが、不幸になるよりはマシ。

最初は絵が綺麗なだけと思っていたが、話が進むにつれて各キャラがジワジワ来る。これが原作によるものか、京アニによるものかは不明。フルメタの作者だとは後日知った。

前作からの視聴。パッとしないキャラ揃えからヴィヴィがブレイクするかと思いきや、不発。話も安定の予定調和で終了。萌えられるキャラが居ればまた評価は違ったかも。

前作からの視聴。カムイの言うことがさっぱり分からない上、オカルト現象の種明かしも無し。同じ制作陣が作ったとは思えない。前作が良かったので期待が大きかった分、失望も大きい。

2014-10-31

Animes in the 3rd quarter of 2014

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

主人公が全能過ぎる。ブラコン妹も含めて、各所でネタにされるのも仕方がない。完全に好みが分かれる作品だが、中二病作品の完成形の一つとして、見ておいて損はない。

前作のアップテンポが落ち着いて、ようやく丁度よい感じになった。しかし原作未読で思い入れがないせいか、話が単調に感じる。勉強にはなるので続く限りは見る予定。

無印版を未見でも無問題そうだったので視聴したが、途中からひどい早送り状態。完全にファン向け追加ディスク的な内容だった。寧ろ、これを見たことで原作をやる気が失せた。

また良くあるハーレム作品か、と思っていたら、回を重ねるにつれて各キャラが可愛くなっていった。特にティアがお気に入り。製作者の思う壺な感じだが、素直に続きが見たい。

初話で「GJ 部」のフィギアを見た気がして、てっきり同じ作者だと勘違いした。見終わった後、やっぱりこれが同じ作者のはずがないよね、という結論に。

鉄オタならではの濃い話を見せてくれると思いきや、単なるラッキースケベのハーレム作品だった。そっちは間に合ってるんで、もっと本作品にしかできないことをやってください。

作品については、ほのぼの癒し系くらいしか言うことがない。「ろこどる」が初耳だったので、調べると命名はつんく♂か。「こ」はいったい何処から来たのか。

同性の立場からは主人公(男)にイライラする。ギャグ担当がヒロインくらいしか居ないので、普通に見るには退屈。ただ私的には村尾ちゃんがストライクだったので問題なし。

絶望的な戦力差を覆す主人公にやり過ぎ感を覚えるが、そこに目を瞑れば面白い。それ故に、最終話の早送りには閉口。こういうのを見せられると気持ちが冷めてしまう。

BL 物は今までも幾つか見てきたが、男の娘は初めてかも知れない。話の内容は特にどうということはないが、「シよっ」のセリフは破壊力あり。BL 物でこのセリフは反則だろ。

絵は綺麗で割と好みなのだが、話は主人公強い・モテるの普通のハーレム作品。女子キャラが気に入るかどうかが全て。私的には、青い風使いの人が良かった。

「喰霊-零-」の作者と聞いて。しかし期待に及ばなかった。恐らく「喰霊-零-」の時は、制作者(監督?)の力量による所が大きかったのではないかと推測。

とにかくやたら千代ちゃんが可愛い。今回は「小澤亜李」を覚えた。少女マンガ風なのにガンガン ONLINE と聞いて意外だったが、作者が女性だと知って納得。

「凪のあすから」にインスパイアされた作品か?と思ったら同じ会社とのこと。正直、話の結末には納得が行かないが、何かが心に残る作品ではあった。

話の内容よりも、三森すずこの唄に惚れた。私の中で彼女の株が急上昇。真面目な話、今まで聞いた声優の中で一番かも知れない。でも演技はもう少し頑張って。

基本この手の腐女子向けはスルーなのだが、パステル絵調が好みだったので視聴してみた。結果、やはり見なくても良かったという結論。

前作からの視聴だが、未だに良さが分からない。但し龍子だけは例外。お前はもっと暴れて私を笑わせてくれ。Fate の勉強として、今後も見るつもりではいる。

原作は未読。意外にも、一番つまらないと予想していたアリ編が一番面白かった。但しここがピークだと思うので、どうぞもう作者様はゆっくりお休みください。

今期の一番。「ハートフル」のキャッチコピーは伊達じゃなかった。基本賑やかコメディーで、見ていて全く退屈しない。是非とも続編を希望。ところで「なる」が男だと思っていたのは私だけではないはず。

話はなかなか面白いが、途中で強敵が現れる辺りから雰囲気が怪しくなる。相手が悪役ではなく良きライバルだったなら、もっと盛り上がったのではないかと思う。

2014-09-30

Apache httpd: /bin/sh: /apr-1/build/libtool: No such file or directory

いつも通り Apache httpd を make すると、エラーが発生。

# make
make[1]: Entering directory `/usr/local/src/httpd-2.2.24'
Making all in srclib
make[2]: Entering directory `/usr/local/src/httpd-2.2.24/srclib'
Making all in pcre
make[3]: Entering directory `/usr/local/src/httpd-2.2.24/srclib/pcre'
make[4]: Entering directory `/usr/local/src/httpd-2.2.24/srclib/pcre'
/apr-1/build/libtool --silent --mode=compile gcc -pthread        -I/usr/local/src/httpd-2.2.24/srclib/pcre -I. -I/usr/local/src/httpd-2.2.24/os/unix -I/usr/local/src/httpd-2.2.24/server/mpm/prefork -I/usr/local/src/httpd-2.2.24/modules/http -I/usr/local/src/httpd-2.2.24/modules/filters -I/usr/local/src/httpd-2.2.24/modules/proxy -I/usr/local/src/httpd-2.2.24/include -I/usr/local/src/httpd-2.2.24/modules/generators -I/usr/local/src/httpd-2.2.24/modules/mappers -I/usr/local/src/httpd-2.2.24/modules/database -I/usr/include/apr-1 -I/usr/local/src/httpd-2.2.24/modules/proxy/../generators -I/usr/local/src/httpd-2.2.24/modules/ssl -I/usr/local/src/httpd-2.2.24/modules/dav/main   -c maketables.c && touch maketables.lo
/bin/sh: /apr-1/build/libtool: No such file or directory
make[4]: *** [maketables.lo] Error 127
make[4]: Leaving directory `/usr/local/src/httpd-2.2.24/srclib/pcre'
make[3]: *** [all-recursive] Error 1
make[3]: Leaving directory `/usr/local/src/httpd-2.2.24/srclib/pcre'
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory `/usr/local/src/httpd-2.2.24/srclib'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/usr/local/src/httpd-2.2.24'
make: *** [install-build] Error 2

よく見ると、configure 時にも同様のログが出ていた。

Applying OS-specific hints for httpd ...

./configure: line 5774: /apr-1/build/libtool: No such file or directory
  forcing SINGLE_LISTEN_UNSERIALIZED_ACCEPT to "1"
  forcing AP_NONBLOCK_WHEN_MULTI_LISTEN to "1"

確かにいつもと違ってこのシステムには apr パッケージが入っているが、一体 /apr-1/build/libtool とはどこから来たのか。configure スクリプトを追いかけると、apr-1-config --apr-libtool の出力に辿り着いた。

# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 6.5 (Santiago)

# type apr-1-config
apr-1-config is hashed (/usr/bin/apr-1-config)

# apr-1-config --version
1.3.9

# apr-1-config --apr-libtool
/apr-1/build/libtool

私には apr-1-config と configure スクリプトのどちらが間違っているのかは分からない。しかしどちらであろうと、動かないシステムに価値はない。

結論: --with-included-apr が正義。

今後も余計なトラブルに逢いたくなければ、常にこのオプションを付けておくのが良さそうだ。普通、パッケージ提供バイナリよりも自分でビルドした方がパフォーマンスも良くなるはずだし。

もしかすると最新版の httpd では対処済みかも知れないが、面倒いので未確認。

2014-07-31

Animes in the 2nd quarter of 2014

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

殺し屋が云々って前振りで始まる割に、結局誰も死んで無くね?という。毎回ある謎掛けも一体何だったのか。結局、最後まで何がやりたかったのか良く分からなかった。

原作は途中から既読。話数が足りずに描写不足だし(話が抜けているっぽい)、原画にあったキャラの魅力もアニメ絵で失われている。結論として、原作を呼んだ方が面白い。

正直、前期の方が楽しめた。あと、この作品に限ったことでは無いが、モーションキャプチャー CG をそのまま使うのは、アニメとしては手抜きだと思う。

最近では珍しいエロスの方向性。個人的にはアリ。ただ途中の主人公差し替えが水を差した。リッツは最初は何とも思わなかったが、後からジワジワ可愛くなってくる。

絵的に期待してなかったが、先出二名の女子キャラには妙な魅力がある。主人公が欲望に素直なのも良い。個人的にはベタだと言われようが「みはり」ちゃん推し。

女子キャラ多過ぎ、主人公モテ過ぎ、終盤の展開早過ぎ。最後は全くついていけなかった。何か無理やり終わらせた感じを受ける。ただ一つ、「がをがをー」だけは認める。

記憶消去作品は今までに何度か見てきたが、特定日に消去というのは初体験。基本いい話系だが、途中で少し陰鬱な感じになるのと、主人公(男)がヘタレなのが頂けない。

前作からの視聴だが、前作程のインパクトがない。新キャラ中心で話が進むが、その新キャラ勢に狂三みたいな勢いがない。その狂三も今作ではいい子ちゃんでつまらない。

主人公たち自身がチートなことに目を瞑れば、独特な絵調もあって普通に楽しめた。ただ人によっては、受け付けないことも多そう。最近は日笠陽子の演技に感心することが多い。

話は典型的な少女マンガなので意外性はない。この手の作品を見ると、やっぱり女子もツンデレが好きなんだなと思う。そして、「但し二次元に限る」という所まで同じ。

前作からの視聴。相変わらず独特の雰囲気があり、他作品とは一線を画している。続きがある限り見ていくつもりだが、何故あんな中途半端で終わったし。

地味ながら丁寧に作られている感はある。ただ、私にはヒロインに萌えるのは無理だった。サバター兄妹も活躍が地味だし、全てにおいて何かが足りない気がする。

スポコン作品としては安定。しかし気持ち重視の作品なので、納得できない部分も多い。個人的に「かもめ☆チャンス」と比べてしまうので、どうしてもそういう評価になる。

基本 CG アニメは認めない派だが、本作に限れば CG が原画にマッチしていて全くアリだった。話も独特で面白いし、次回も(あるなら)期待している。

原作のゲームは知らないが、取りあえずメディアミックスでアニメにしました、という感じが半端ない。少なくとも、これを見てゲームをやる気は起きない。

絵を見たときは不安しか無かったが、良く考えればこの絵でアニメ化するのに話が面白くない訳がなかった。アニメを見て原作を読みたくなった作品は久しぶり。

作品の雰囲気に似合わず財宝トラップがエグい。話も終盤は陰鬱になるし、宝探しはもっと楽しくあるべき。「ファイ・ブレイン」と同じ過ちを犯している気がする。

2014-07-01

Emacs 23: Fix font-lock colors for 8 colors terminal

例えば RHEL6 で、SSH + screen + Emacs 23 とかいう組み合わせで使うと、Emacs の色付けが上手くいかない。具体的には、

  1. ソースコードのコメントに色が付かない
  2. Bash スクリプトの関数名に色が付かない

8 色ターミナル + Emacs 23 + 黒背景という組み合わせだとこうなる。最初は Emacs 23 からの仕様かとも思ったが、そんなはずはなかった。正直(2)はどうでも良いが、(1)は冗談抜きで生産性に直結するので見過ごせない。

;;; font-lock settings for 8 colors terminal
(when (require 'font-lock nil t)
  ;; fix comment color in dark background
  (and (>= emacs-major-version 22)
       (eq 'unspecified (face-attribute 'font-lock-comment-face :foreground))
       (set-face-attribute 'font-lock-comment-face nil
			   :foreground (face-attribute
					'font-lock-comment-delimiter-face
					:foreground)))
  ;; fix function symbol color in Bash script
  (when (= emacs-major-version 23)
    (eval-after-load "sh-script"
      '(let ((tail (cddr (assq 'bash sh-font-lock-keywords-var))))
         (and (eq 'shell (car tail))
	      (setcar tail 'sh)))))
  (global-font-lock-mode 1))

どちらも Emacs 24 では直ってるっぽいが、オールド世代への扱いが不憫過ぎて泣ける。8 色ターミナルで Emacs 黒背景とかもう誰も使ってないですか、そーですか。