Logo

@nhoriguchi


文章を web で公開する訓練の副産物

2012/05/07

Beaker でマシンを取るとパーティション構成がデフォルト (全領域 LVM) になってしまうので、生デバイスが欲しいときにちょっと困ってしまう。その場合、workflow xml ファイルの <partition> タグを用いてインストール時のパーティション構成を指定することができる。複数のディスクがあるマシンならば <:recipe> タグの ks_meta 要素をに "ondisk=sda" などと記入することで、kickstart のレベルでパーティション構成に影響も与えることもできるが、こちらは色々分かっていないと問題を引きやすいため、熟練者向けか。参考までに Beaker プロジェクトへのリンクも張っておく。

2012/04/26

今だに画像すら貼れないブログというのもダサいので、今週末あたり弄ってみようかな。
Git のソースから RHEL6 カーネルを rpmbuild するまでの自動化について。パッチの数はどうせ 1, 2 個なので手動でも問題ないのだが、今後 2, 3 年で数百回は実行することになる作業なので、ここらで自動化が必要と感じた。kernel.spec を書き換える部分で、ruby ワンライナーで別ファイルから読み込んだデータを埋めこむという若干面倒なことをしているので、今後のコピペ用にコード片を晒しておく。
 # LOCALVER: local version of your build
 # PDIR: your patch directory (use quilt export, stg export, ..)
 # Replace local kernel version
 
 sed -ie "s/# % define buildid .local/%define buildid .$LOCALVER/" /tmp/kernel.spec
 
 ruby -i -p -e 'if $_ =~ /^Patch999999: linux-kernel-test.patch$/        
   open("'${PDIR}/series'") do |f|                                           
     i = 0                                                                   
     f.each do |line|                                                        
       next if line =~ /^# /                                                 
       i += 1                                                                
       puts "Patch#{i}: #{line}"                                             
     end                                                                     
   end                                                                       
 end' /tmp/kernel.spec
 
 ruby -i -p -e 'if $_ =~ /^ApplyOptionalPatch linux-kernel-test.patch$/      
   open("'${PDIR}/series'") do |f|                                           
     f.each do |line|                                                        
       next if line =~ /^# /                                                 
       puts "ApplyOptionalPatch #{line}"                                     
     end                                                                     
   end                                                                       
 end' /tmp/kernel.spec                                                   
kernel.spec の変更のポイントは 3 箇所で、1 つめはローカルバージョンの命名で、upstream カーネルなら .config の CONFIG_LOCALVERSION の変更に相当するようだ。あとは自前で用意したパッチをリストに加えて、ビルド時に当てる命令を追加するのが 2 つめと 3 つめ。ちょうどそれぞれ Patch999999: linux-kernel-test.patch というダミーのパッチ用の項目が用意されているのでその直前に追加するように書いた。ruby のワンライナーについては perl や sed などと似たようなオプションが定義されているで、慣れていれば迷わないが、ちょっと微妙だったのは、ruby の -e オプションで与えるスクリプト部はシングルクオートで囲まなければならない点。シェル変数を渡しにくいではないか。数分悩んだあと、いったんシングルクオートを閉じる逃げ道を見つけた。昔 awk でも似たような tips をどこかで見つけたが、awk はダブルクオートでスクリプトを渡せるのであまり困ったことがなかった。
それにしても twitter である偉い先生が言うには「日本語の技術情報って基本的にゴミだよね」。ゴミを増やすのに貢献してしまった。すみません。ま、もっと力を抜いて気楽に。

2012/04/16

gnome-terminal でマウスで選択した範囲内の文字列を中クリックでペーストする機能は頻繁に使うが、Fedora 16 のデフォルトではダブルクリックでハイライトしたときに、コロンが文字列区切りとして扱われないように変更されたため、URL や grep -n の結果をコピーする際に不便に感じていた。検索してみると xterm ならセパレータを柔軟に設定できるとのことで色々調べてみたが、後で gnome-terminal のプロファイルに単語と認識する構成文字を設定できる項目があり、ここからコロンを除けば問題は簡単に解決した。何でもすぐに google 検索に頼りがちだが、まず手元の状況を良く見ることが大切だね。ちなみに xterm はフォントが美しくないので使いたくない。

2012/04/13

知っていたけど blog を真面目に継続するというのは難しい。何年もマメに更新を続けられている人はそれだけで尊敬に値する。
普段 git で管理されたソースコード上でパッチを開発するとき stgit を使用しているが、unapplied パッチがある状態で他のブランチに移動してしまったとき、元のブランチの unapplied パッチにお手軽にアクセスできると嬉しいと思って調べてみたら、ちゃんとブランチを指定するオプション -b が用意されていた。 stg branch -l を実行するとブランチ一覧が表示されて stgit が作成されているブランチ上には 's' マークが付くので、そのブランチを -b で指定して stg series なり stg show をしてやると良い。
新しく購入した ThinkPad で YouTube 聞きながら作業していたらフリーズしてしまった。そうでなくても以前から何か異常に電源の減りが早くて、何かファンがずっと回りっぱなしだなーと思っていたら、なんと、ThinkPad x220 はデフォルトだとファンの回転数が自動制御されないらしい。そんなバカな。
実際検索すれば良く知られた問題のようで、それでもまあ Fedora 16 の話は少ないのでメモを残す価値はあるだろう。ThinkWiki のファンの制御に関するページを見てみると、カーネルモジュール thinkpad-acpi (カーネルに既に入っている) のパラメータを fan_control=1 に変更するのが第一歩らしい。デフォルトは fan_control は off になっている。
[hori@nhori ~]$ cat /sys/module/thinkpad_acpi/parameters/fan_control
N
上記 URL にも記載されている方法で (Fedora 16 だからか、/etc/modprobe.d/ 配下のファイルは .conf 拡張子が付いていないとモジュールロード時に Warning が出て気持いが悪い。.conf 拡張子を付けておこう。) fan_control を有効にすると
[hori@nhori ~]$ cat /sys/module/thinkpad_acpi/parameters/fan_control
Y
となる。ふむ。
これとは別に事前に sensors-detect を実行しておいて、sensors から HW の温度計が見えるようにしておく。
[hori@nhori ~]$ sensors
acpitz-virtual-0
Adapter: Virtual device
temp1:        +52.0°C  (crit = +99.0°C)
 
thinkpad-isa-0000
Adapter: ISA adapter
fan1:        3494 RPM
 
coretemp-isa-0000
Adapter: ISA adapter
Physical id 0:  +52.0°C  (high = +86.0°C, crit = +100.0°C)
Core 0:         +52.0°C  (high = +86.0°C, crit = +100.0°C)
Core 1:         +52.0°C  (high = +86.0°C, crit = +100.0°C)
ふむ。
thinkpad_acpi がユーザ空間に見せているインターフェースを利用して実際にファン回転数を制御するツールが thinkfan で、これをソースからビルドして利用する。README に書いてあるように
$ cat /tmp/fancheck.sh
for i in 0 1 2 3 4 5 6 7; do
       echo "level $i" > /proc/acpi/ibm/fan
       echo "level $i..."
       sleep 6
       cat /proc/acpi/ibm/fan | egrep "^speed"
       echo
done
  
$ bash /tmp/fancheck.sh
level 0...
     speed:2973
 
level 1...
     speed:1808
 
level 2...
     speed:2419
 
level 3...
     speed:3557
 
level 4...
     speed:3494
 
level 5...
     speed:3906
 
level 6...
     speed:3886
 
level 7...
     speed:4362
という感じに、/proc/acpi/ibm/fan に "level N" という文字列を書き込むことでファンレベルの上げ下げができるようだ。ファンレベルと実際の回転数は線形にはなっていないようだが、これは何か理由があるのかな。ちなみに、thinkpad_acpi の fan_control を使用しない場合、常にファンの回転数が 3700 程度に固定されている。常時フル回転というわけではなかったようで、だから無線 LAN を使用して YouTube をゴリゴリ見たりなんかすると thermal event が発生したのかもしれない。
で、この後設定ファイルを作る必要があるのだが、README に従って fan 行を追加すると何故か thinkfan が上手く動作しなかった。残念なことに、動作が悪い方向に倒れてしまい、ファンレベルが 0 に下がったきり、温度が上がってもファンレベルが上がらないという動作になってしまった。テストする際は注意が要るかもしれない。
動作が確認できたら init スクリプトで自動起動するようにするが、ソースコード内に Fedora 用の起動スクリプトが無く、自分で書くのも面倒 (いや嘘、正直 init スクリプトの書き方を知らないだけ) なので適当なスクリプトを書いて cron で常時起動状態にしておく。
 #!/bin/bash
  
pgrep thinkfan > /dev/null && echo "Already running." && exit 0
/usr/sbin/thinkfan -q -c /etc/thinkfan.conf
ちなみに、動作イメージはこんな感じ。
[root@nhori thinkfan-0.7.3]# ./thinkfan -n -c /etc/thinkfan.conf 
 
WARNING: You have not provided any correction values for any sensor, and your fan will only start at 55 °C. This can be dangerous for your hard drive.
Config as read from /etc/thinkfan.conf:
Fan level       Low     High
 0              0       55
 1              48      60
 2              50      61
 3              52      63
 4              56      65
 5              59      66
 7              63      32767
 
sleeptime=5, temp=59, last_temp=0, biased_temp=59 -> level=4
sleeptime=2, temp=68, last_temp=57, biased_temp=93 -> level=7
sleeptime=5, temp=56, last_temp=57, biased_temp=60 -> level=5
sleeptime=5, temp=57, last_temp=56, biased_temp=58 -> level=4
sleeptime=5, temp=56, last_temp=57, biased_temp=56 -> level=3
...
ふむ。無事動作して良かった。

2012/04/08

大した意味はないが、systemtap のプローブ宣言の繰り返しを排除するために簡単なラッパーを書いてみた。probe の宣言で正規表現が使えれば楽なのかもしれないが、まあ当面はこれで。
 #!/bin/bash
 
tmpf=`mktemp`
probes=( do_machine_check me_pagecache_clean me_pagecache_dirty mce_rdmsrl mce_log
         memorure __memory_failure send_sig_info invalidate_inode_page
         generic_error_remove_page )
 
probes_inline=( hwpoison_user_mappings )
 
cat < ${tmpf}.stp
 #!/usr/bin/stap
EOF
 
echo_stp() { echo "$@" >> ${tmpf}.stp; }
 
for probe in ${probes[@]} ; do
    echo_stp ""
    echo_stp "probe kernel.function(\"$probe\") {"
    echo_stp "    printf(\"%s %3d %d\n\", pn(), cpu(), gettimeofday_us());"
    echo_stp "}"
    echo_stp ""
    echo_stp "probe kernel.function(\"$probe\").return {"
    echo_stp "    printf(\"%s %3d %d\n\", pn(), cpu(), gettimeofday_us());"
    echo_stp "}"
done
 
for probe in ${probes_inline[@]} ; do
    echo_stp ""
    echo_stp "probe kernel.function(\"$probe\").inline {"
    echo_stp "    printf(\"%s %3d %d\n\", pn(), cpu(), gettimeofday_us());"
    echo_stp "}"
done
 
 # cat ${tmpf}.stp
 
stap ${tmpf}.stp
 
rm -f ${tmpf}*