天泣記

2014-06-29 (Sun)

#1

lsb_release と /etc/os-release で、OS の名前とバージョンを得られるが、いくらか違う場合もある。

Debian:

% lsb_release -d
Description:    Debian GNU/Linux 7.5 (wheezy)
% grep PRETTY_NAME /etc/os-release
PRETTY_NAME="Debian GNU/Linux 7 (wheezy)"

Fedora:

% lsb_release -d
Description:    Fedora release 20 (Heisenbug)
% grep PRETTY_NAME /etc/os-release
PRETTY_NAME="Fedora 20 (Heisenbug)"

Gentoo:

% lsb_release -d
Description:    Gentoo Base System release 2.2
% grep PRETTY_NAME /etc/os-release
PRETTY_NAME="Gentoo/Linux"

lsb_release のほうがいくらか詳細だが、これはいつでもそうなのだろうか。

2014-06-24 (Tue)

#2

元データも置いておく。

<URL:2014-06/chkbuild-boron-ruby-trunk.csv>

これはログを機械可読に変換した後、build というレコードだけぜんぶ取り出してまとめたものである。個々のテストの結果とか他のレコードもあるが、多いので除いてある。

#1

最近、chkbuild のログを機械可読な形に変換するツールを作った。

<URL:https://github.com/nurse/rubyci/blob/master/lib/chkbuild-ruby-info.rb>

これで boron で昔からやっている chkbuild のログを変換して、ruby の trunk の test-all の failure の数 (error の数は含まない) の推移をプロットしてみた。(文字の位置はおおざっぱ)

ruby_test_all_failures.png

まぁ、0 が定常状態になったのはタイミングからして rubyci.org と、それにともなってなるせさんがいろいろと言うようになったからですかねぇ。

2014-06-17 (Tue)

#1

プログラム内で OS の名前、バージョン、アーキテクチャを得る方法を調べてみた。アーキテクチャというのが実際になんなのかは微妙だが、まぁ主にプロセッサの種類ということにしよう。

いろいろ調べたのだが、まず簡単なのが 4.4BSD の類である。uname コマンドだけで、しかもオプションのうち、POSIX で定義されている -s, -r, -m, -v だけで済む。

FreeBSD:

uname -s : FreeBSD
uname -r : 10.0-RELEASE
uname -m : amd64
uname -v : FreeBSD 10.0-RELEASE #0 r260789: Thu Jan 16 22:34:59 UTC 2014     root@snap.freebsd.org:/usr/obj/usr/src/sys/GENERIC 

NetBSD:

uname -s : NetBSD
uname -r : 6.1.3
uname -m : amd64
uname -v : NetBSD 6.1.3 (GENERIC)

OpenBSD:

uname -s : OpenBSD
uname -r : 5.5
uname -m : amd64
uname -v : GENERIC#271

DragonFly BSD:

uname -s : DragonFly
uname -r : 3.6-RELEASE
uname -m : x86_64
uname -v : DragonFly v3.6.2-RELEASE #11: Wed Apr  9 19:27:24 PDT 2014     root@pkgbox64.dragonflybsd.org:/usr/obj/build/home/justin/src/sys/X86_64_GENERIC 

uname -s が OS の名前、uname -r がバージョン、uname -m がアーキテクチャということでいいだろう。uname -v は OS の名前が入っていたりいなかったり長すぎたりして使いにくい。ただ、DragonFly のバージョンで最後の桁を得ようとすると uname -v をみる必要があるようだ。

uname はカーネルの情報を表示するものなので、カーネルと OS が一体として開発されているなら uname で済む。しかしそうでない場合、つまり GNU/Linux が典型例だが、OS の名前を得るには他の方法を使う必要がある。Debian などでは、Linux Standard Base (ISO/IEC 23360-1) で標準化されている lsb_release コマンドが使える。lsb_release コマンドにはいくつかオプションがあるが、ここでは "single line description of distribution" を short 形式で表示する -sd オプションを使う。Ubuntu は codename が出なくてちょっとさびしいので lsb_release -sc も使ってみよう。(なお、/etc/debian_version とかは際限がないので避けたい。lsb_release がなかったり、デフォルトではない GNU/Linux distribution があるというのも確かなんだけど。)

Debian GNU/Linux:

uname -s : Linux
uname -r : 3.2.0-4-amd64
uname -m : x86_64
uname -v : #1 SMP Debian 3.2.57-3+deb7u2
lsb_release -sd : Debian GNU/Linux 7.5 (wheezy)

Ubuntu:

uname -s : Linux
uname -r : 3.13.0-24-generic
uname -m : x86_64
uname -v : #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014
lsb_release -sd : Ubuntu 14.04 LTS
lsb_release -sc : trusty

Fedora:

uname -s : Linux
uname -r : 3.13.6-200.fc20.x86_64
uname -m : x86_64
uname -v : #1 SMP Fri Mar 7 17:02:28 UTC 2014
lsb_release -sd : "Fedora release 20 (Heisenbug)"

CentOS:

uname -s : Linux
uname -r : 2.6.18-371.4.1.el5
uname -m : i686
uname -v : #1 SMP Thu Jan 30 06:09:24 EST 2014
lsb_release -sd : "CentOS release 5.10 (Final)"

RedHat 系の lsb_release -sd は結果を double quote で括るのがちょっといやらしいかな。

Slackware については lsb_release は見つからなかったが、systemd が推進している /etc/os-release というファイルがあった。

Slackware:

uname -s : Linux
uname -r : 3.10.17-smp
uname -m : i686
uname -v : #2 SMP Wed Oct 23 17:13:14 CDT 2013

$ cat /etc/os-release
NAME=Slackware
VERSION="14.1"
ID=slackware
VERSION_ID=14.1
PRETTY_NAME="Slackware 14.1"
ANSI_COLOR="0;34"
CPE_NAME="cpe:/o:slackware:slackware_linux:14.1"
HOME_URL="http://slackware.com/"
SUPPORT_URL="http://www.linuxquestions.org/questions/slackware-14/"
BUG_REPORT_URL="http://www.linuxquestions.org/questions/slackware-14/"

ところで、Debian には Linux でないものがある。FreeBSD のカーネルを使った Debian GNU/kFreeBSD や Hurd を使った Debian GNU/Hurd である。Linux ではないのに、という気はするが、これらでも lsb_release コマンドが使える。

Debian GNU/kFreeBSD:

uname -s : GNU/kFreeBSD
uname -r : 9.0-2-amd64
uname -m : x86_64
uname -v : #0 Sat Nov 24 04:44:27 UTC 2012
lsb_release -sd : Debian GNU/kFreeBSD 7.0 (wheezy)

Debian GNU/Hurd:

uname -s : GNU
uname -r : 0.3
uname -m : i686-AT386
uname -v : GNU-Mach 1.3.99-486/Hurd-0.3
lsb_release -sd : Debian GNU 7.0 (wheezy)

GNU/Hurd じゃなくて単に GNU と出てくるのは、ユーザランドとカーネルが両方 GNU だから、かな。uname -m は i686-AT386 と他と比べて長くなっている。プロセッサだけじゃなくてマシンのアーキテクチャもついているのだろう。

他の OS もいくつか調べてみよう。

OpenIndiana (OpenSolaris の fork) の uname は SunOS と名乗って OpenIndiana という名前が出てこない。ここでは /etc/release の先頭行をみるのがよさそうである。バージョンは uname -v で、oi というのは OpenIndiana の略だろう。uname -m は i86pc という見慣れない名前で、見慣れた名前は uname -p (host's ISA or processor type) で出てくるようだ。

OpenIndiana:

uname -s : SunOS
uname -r : 5.11
uname -m : i86pc
uname -v : oi_151a7
uname -p : i386
head -1 /etc/release : OpenIndiana Development oi_151.1.7 X86 (powered by illumos)

Minix は uname で済む感じ。

Minix:

uname -s : Minix
uname -r : 3.2.1
uname -m : i686
uname -v : 3.2.1

Haiku も uname で済むようだが、uname -v も見ないとバージョンは得られない感じか。

Haiku:

uname -s : Haiku
uname -r : 1
uname -m : BePC
uname -v : hrevr1alpha4-44702 Nov 14 2012

Mac OS X の uname では Mac OS X という名前が出てこない。ここでは sw_vers コマンドが使える。

Mac OS X:

uname -s : Darwin
uname -r : 13.2.0
uname -m : x86_64
uname -v : Darwin Kernel Version 13.2.0: Thu Apr 17 23:03:13 PDT 2014; root:xnu-2422.100.13~1/RELEASE_X86_64

% sw_vers
ProductName:    Mac OS X
ProductVersion: 10.9.3
BuildVersion:   13D65

AIX は uname でだいたいわかるようである。GCC Compile Farm にある AIX 7.1 で試したのだが、uname -v が operating system version で、uname -r が release number of the operating system ということなので、きっとこれらをつなげればいいのだろう。また、oslevel というコマンドもある。uname -m は machine ID number なるもので、アーキテクチャは uname -p で得られる。

AIX:

uname -s : AIX
uname -r : 1
uname -m : 00F84C0C4C00
uname -v : 7
uname -p : powerpc
oslevel : 7.1.0.0
oslevel -s : 7100-02-02-1316

2014-05-24 (Sat)

#1

file descriptor passing で、fd が受け取られないで消えてしまったらどうなるか試してみた。

端末1:

% uname -mrsv
Linux 3.14-1-amd64 #1 SMP Debian 3.14.4-1 (2014-05-13) x86_64
% ruby -rsocket -e '
Socket.unix_server_loop("/tmp/s") {|s|
  p s
  p :before_sleep; t = Time.now
  sleep 3
  p :after_sleep; p Time.now-t
  s.close
}'
#<Socket:fd 8>
:before_sleep
:after_sleep
3.000132032

端末2:

% ruby -rsocket -e '
s = Socket.unix("/tmp/s")
r, w = IO.pipe
s.sendmsg("\0", 0, nil, Socket::AncillaryData.unix_rights(w))
w.close
p :before_read; t = Time.now
p r.read
p :after_read; p Time.now - t
'
:before_read
""
:after_read
3.000255096

なにをやっているかというと、端末1で起動した Unix domain socket server に、端末2で起動した client が接続し、その接続を通してパイプの書き込み側を送る。しかし、server は受け取れるパイプを受け取らずに、3秒後に接続されたソケットを close する。

client では、パイプの書き込み側は送った後にすぐに close する。そうすると、書き込み側はどのプロセスにも存在せず、kernel の中にしかない状態になる。その状態で読み込み側からデータを読み出そうとするとどうなるか。

結果としては、(だれもデータを書き込まないので) データは読み出せず、書き込み側を取り出せるプロセスが存在しなくなった時点で EOF が検出される。

まぁ、順当な結果だろう。

2014-05-20 (Tue)

#1

qemu で armhf な Debian GNU/Linux (wheezy) を動かしてみた。

ホスト環境は Debian GNU/Linux (jessie) で、qemu-system-arm をインストールしておく。

  1. Debian の armhf 用の installer をとってくる。

    今回は qemu-system-arm でエミュレートする vexpress-a9 というマシンを使うので、それ用の installer をとってくる。(vexpress-a9 はメモリが 1G まで使えるのが良い。versatilepb は 256M までしか使えなくて厳しい)

    % wget ftp://ftp.jp.debian.org/debian/dists/wheezy/main/installer-armhf/20130613+deb7u2+b1/images/vexpress/netboot/{vmlinuz-3.2.0-4-vexpress,initrd.gz}

    Linux kernel と initrd であるが、これが installer である。CD や USB メモリのイメージではない。

  2. disk image をつくる

    以下で作っているのは raw で 8G なファイルという単純なものだが、LVM を使うとか他の選択肢もあるだろう。

    % qemu-img create debian-arm.img 8G
    Formatting 'debian-arm.img', fmt=raw size=8589934592
  3. installer を起動する

    kernel と initrd をどうやって使うかというと、qemu-system-arm のオプションで指定する。まぁ、仮想マシンのメモリ内に適切に配置して実行できるなら特別に boot loader を使わなくてもいいのだろう。

    % qemu-system-arm \
    -M vexpress-a9 -m 1G \
    -kernel vmlinuz-3.2.0-4-vexpress \
    -initrd initrd.gz \
    -drive file=debian-arm.img,if=sd,cache=writeback

    起動すると、ウインドウが出てきて、Debian installer が起動する。

    以下のようにオプションを足せば、curses を使うモードにもできる。(遠くのマシンでやるには便利)

    % qemu-system-arm \
    -M vexpress-a9 -m 1G \
    -kernel vmlinuz-3.2.0-4-vexpress \
    -initrd initrd.gz \
    -append 'console=ttyAMA0' \
    -drive file=debian-arm.img,if=sd,cache=writeback \
    -curses -serial stdio

    なお、vexpress の kernel は PCI をサポートしていないようで、-hda を使って disk を指定すると No disk drive was detected とか出てきてインストールできない。そのため、SDカードとして扱う。(参考: <URL:https://gist.github.com/bdsatish/7476239>) 単に -sd debian-arm.img じゃなくて -drive ... としているのは耐えがたいほど遅かったからである。

  4. Debian installer と対話する

    基本的に、普通にやればいい。

    最後のほうで、No boot loader installed というメッセージが出て、/dev/mmcblk0p1 の /vmlinuz に root=/dev/mmcblk0p2 と指定して 起動するようにいわれる。

    というわけで、install された kernel と initrd を外に取り出さないといけない。これをやる方法はいろいろあるだろうが、今回は reboot する前に (Alt-F2 で) shell を動かして、nc で取り出した。

    • 外部の端末:

      nc -l 9999 > boot.tar
    • QEMU中の端末

      cd /target
      tar cf - boot | nc 外部のIPアドレス 9999
    • 外部の端末:

      tar xf boot.tar

    (他の方法としては、qemu を止めた後に debian-arm.img から取り出すことが考えられる。)

    取り出したら installer から reboot し、qemu を適当なところで Ctrl-C で止める。

  5. install されたものを起動する

    取り出した kernel と initrd を使って起動する。

    % qemu-system-arm \
    -M vexpress-a9 -m 1G \
    -kernel boot/vmlinuz \
    -initrd boot/initrd.img \
    -append root=/dev/mmcblk0p2 \
    -drive file=debian-arm.img,if=sd,cache=writeback \
    -net nic -net user,hostfwd=tcp:127.0.0.1:3022-:22

    これで動くのはごく普通の Debian で、(installer で外していなければ) sshd が動いている。qemu に hostfwd=tcp:127.0.0.1:3022-:22 と指定して、外側の 127.0.0.1:3022 から内側のマシンの 22 に port forward しているので、外側で ssh 127.0.0.1 -p 3022 とすると中にログインできる。

  6. ウインドウを出さないで動かす

    ウインドウが出るのは試すのにはいいのだが、動かしっぱなしにするにはうれしくない。

    qemu は標準入出力を仮想マシンのシリアルと接続できるので、そのようにしてみる。

    まず、arm な GNU/Linux では、シリアルは /dev/ttyAMA0 というデバイスのようである。なので、/etc/inittab に以下の行を足して ttyAMA0 にログインプロンプトを出すようにしておく。

    AMA0:2345:respawn:/sbin/getty 38400 ttyAMA0

    そして、qemu を以下のように起動する。

    % qemu-system-arm \
    -M vexpress-a9 -m 1G \
    -kernel boot/vmlinuz \
    -initrd boot/initrd.img \
    -append 'root=/dev/mmcblk0p2 console=ttyAMA0' \
    -nographic \
    -drive file=debian-arm.img,if=sd,cache=writeback \
    -net nic -net user,hostfwd=tcp:127.0.0.1:3022-:22

    こうすると、qemu-system-arm の標準入出力が内部の仮想マシンの ttyAMA0 と接続され、起動した端末から普通にログインできる。

    とりあえずこれを screen の中で飼えばいいかな。



田中哲