投稿

BitVisor の UEFI 向けのブートローダーを読む(2nd stage)

この記事は BitVisor Advent Calender 2017,20 日目の記事(大遅刻)です。

UEFI 向けのローダーでも読んで記事書くかーって思ってたら先にやられてしまってウンウン唸ってましたが, 彼の記事の続きを勝手に書けば良いことに気がつきました。

では元気よく,UEFI の 1st stage loader から entry_func に飛んだ後を追っていきましょう。
いきなり find と grep を使っても良いのですが,折角手掛りがあるのでまずリンカスクリプト, bitvisor.lds を読んでみます。1st stage loader を読む記事に因ると,bitvisor.elf を 0x10000 だけ読んで,paddr (おそらく物理アドレス,physical address の略でしょう)に読んで,そこからエントリポイントを計算して,entry_func に飛んでるらしいです。

bitvisor.lds リンカスクリプト 2 行目,phys = 0x00100000; となっており,11 行目, .entry : AT (phys + (code - head)) { をみるとこのアドレスは bitvisor.elf の .entry というセクションになってるらしいので,このセクションを探せば良さそう。ついでに,このスクリプトから bitvisor.elf がメモリに置かれるときの仮想アドレスの開始位置もわかります。

core/entry.s.entry セクションをみると,まず multiboot のヘッダが書いてあって,次に 32-bit のコードが始まってます。test 命令の結果,もしリアルモードであるならば,jc によってリアルモード用の初期化コードに飛んでますが,今回は割愛。
で,その後,32-bit なら jnc 命令で分岐せず multiboot のためのコードにジャンプ,ロングモードなら uefi64_entry に分岐しているわけですが,この分岐のやりかたが結構トリッキーというか,あんまりちゃんとなんでこれでいいのかわかってないなあと思ったら, BitVisor本体のブート仕様 2 年前のえいらくさんの記事にしっかり書いてあった……。やだ,もしかしてこの記事を書く必要なかった……?
でももう書き始めちゃったのでこ…

Chinachu を SELinux 有効にして使う

https://github.com/Chinachu/docker-mirakurun-chinachu

Chinachu の docker コンテナの README から抜粋
- SELinuxの無効化推奨 無効化推奨,じゃあないんだよ!有効化しろよ!ということで,SELinux を enforcing するまでの道程です。

まず最初に,ディストリビューション。Chinachu は Debian や Ubuntu での導入記事を多く見受けますが,今回は REHL/Fedora/CentOS 系統を使います。
SELinux のデフォルトのポリシーが充実してるのがその理由。
次に,Chinachu はコンテナ化したものを用います。Chinacu は npm のモジュールをローカルにインストールしたり ffmpeg をビルドしたり,パッケージ以外から導入するものが多すぎなので,それに対してラベル付けたりポリシーを書いたりするのがダルいからです。

私は Fedora 27 で設定を行い,この記事を書いてます。

では前置きはここまでにして,以下手順

1. SELinux 有効化
CentOS の場合は先にパッケージを入れておきましょう。
# yum -y install selinux-policy-targeted setools とはいっても Red Hat 系のディストリビューションはデフォルトで有効のはずです。CentOS はパッケージいれてから再起動が必要ですが。

デ フ ォ ル ト で 有 効 の は ず で す が

もし無効化してたなら,とりあえず /etc/selinux/config の中で SELINUX=permissive にして再起動しときましょう。
なお,現状だと,docker のストレージに btrfs を使っていて,それで docker pull をすると,SELinux が enforcing のときだとコケるっぽいです。解決中。まあ pull のときだけ permissive にしてサービス動かしだしてから enforcing でも困らん気がする。

2. ラベリング

docker-compose.yml の volumes を次のように設定していると仮定します。
services:
    mirakurun:
        (…

Facebook の特定の公開ページの投稿を全部クロールする(ひなビタ♪)

ひなビタ♪ Advent Calender 用の記事です。

やほやほっ,おるみんです!

みなさんは日向美ビタースイーツ♪というバンドをご存知でしょうか。
架空の地方の商店街,日向美商店街を舞台とする,町興しをテーマに少女たちが奮闘したり日常を過ごしたりするガールズバンドです。
最近はひなビタ♪の舞台のモデル,鳥取県倉吉市ともコラボを積極的にしているみたいですよ。

私の地元と近い場所だったり,鄙びた商店街という舞台だったり,自分自身の体験や実感と重なったりするところも多くて思わずハマっちゃいました☆[1]

さて,このひなビタ♪なのですが,音楽 CD や KONAMI のアーケードリズムゲームなどへの展開は勿論,小説や SNS での投稿といったマルチメディア展開をしています。
主なストーリーラインや彼女たちの音楽制作の様子といったものが Facebook を中心に展開される,非常に珍しいコンテンツと言えるでしょう。

しかし,Facebook でコンテンツを追うのは大変です。
試しにひなビタ♪のページを PC のブラウザで自動スクロールさせて古いポストを開かせようとしたところ,メモリ不足により半分くらいスクロールしたところでタブが死にました。
iPhone のアプリの場合,最後までスクロールできましたが,バッテリーが 30% くらい持ってかれた上に,スクロールをしていたのが家への帰路でしたが,数十分〜一時間くらいずっとスクロールする破目になりました。もうしません。

そこで,次のようなものを作りました。

orumin/hinabitter_read: ひなビタ♪の Facebook 投稿を快適に読みたい https://github.com/orumin/hinabitter_read 使い方は README.md の通りです。
アクセストークンを取得するコールバックは,
facebookのタイムラインへpythonから投稿する - Qiita 
をパク……参考にしました。

とりあえずこれで,2017/12/09 現在 2.4MB にもなるテキストファイルが取得できます。
今回は力足らずここまでなのですが,できれば近いうちに画像や投稿のシェアについてもちゃんと取得するようにした上で,整形して EPUB かなんかにして Kindle にメールで送り付けてシュッと読めるようにした…

Apple SuperDrive を Linux で使う

Apple Inc. 謹製の CD/DVD ドライブである SuperDrive,これは実は素で Linux から使えません。
これは,sg3_utiils に入ってる sg_raw コマンドで,SCSI のメッセージとして特定のマジックを送るとドライブが起きて使えるようになります。
$ sg_raw /dev/sr0 EA 00 00 00 00 00 01 しかし,これを毎回手動でやりたくはありませんよね?そこで,次のようにします。
このように udev のルールを書いてしまえば解決です。このファイルは,/etc/udev/rules.d に配置しましょう。
尚,お気付きかと思いますが,pre-OS な環境,つまり BIOS や UEFI からは Apple のデバイスでないとこのドライブは使えないと思います。UEFI のドライバを自作したらあるいは,可能かもしれませんが。

特定のコンテナの中で動作してるプロセスの物理メモリ消費量の総計を MB 単位で出力するワンライナー

docker exec -it chinachu echo "scale=3; $(ps aux | awk '{sum += $6}END{print sum}')/1024" | dos2unix | bcdocker exec で ps aux の RSS 値を全部足して bc(1) に渡してるだけ。
あれ,これ docker コンテナにワンライナー渡したのを bc で計算してるけど,そもそもコンテナからは ps(1) の出力だけさせて手元で足し合せたりしたほうが良いのでは,と今ここまで書いてから気がつきました。
echo "scale=3; $(docker exec -it chinachu ps aux|awk '{sum += $6}END{print sum}')/1024" | bc これでいいですね。

P.S.
chinachu のところは好きなコンテナ名にしてね。

P.S. その 2
docker stats --format "{{.MemUsage}}" --no-stream chinachu でよかった……(無駄なことをした……)unarist さんありがとうございます。

Unix 系 OS で コマンドの実行時により正確なタイムスタンプをつける

前回の記事の続編のようなもの
Unix 系 OS でコマンド実行間にタイムスタンプを付ける 前回の設定では精度が秒なので,ミリ秒やマイクロ秒が欲しいときに困る。

次のようにシェル組込みの trap コマンドを使うことでより細かい日時を正確にとれる
$ trap 'echo -e "\n$(date -I"ns")\n"' DEBUG Bash でも Zsh でも trap は特定のシグナルのハンドラ(のようなもの)をシェルに設定するものだが, シグナルではなく DEBUG を指定するとコマンドやシェル関数の実行直前に設定したコマンドを実行してくれる。
ここでは,date(1) に -I あるいは --iso-8601= でナノ秒単位の ISO 8601 形式のフォーマットを指定しているが,
date +"%F %T.%N" のように + でフォーマットを與えるのでも良かろう。

ちなみにこれを自分の手元の zsh でやったらプロンプトの文字列に色々仕込みすぎてたせいでコマンド実行前にかなりタイムタンプが出てきた上にプロンプトが若干壊れました。

Unix 系 OS でコマンド実行間にタイムスタンプを付ける

Bash や Zsh 向け。POSIX sh だとたぶん出来ない。

Bash の例
20 2017-10-23 18:30:54 echo $PATH | sed -e 's/:/\n/g'
21 2017-10-23 18:30:54 uname -a
22 2017-10-23 18:30:54 exit
23 2017-10-23 18:30:56 cd
24 2017-10-23 18:31:04 HISTTIMEFORMAT='%F %T '
25 2017-10-23 18:31:06 history Zsh の例
16384 2017-10-23 18:37:02 popd
16385 2017-10-23 18:38:30 ls
16386 2017-10-23 18:38:31 pwd
16387 2017-10-23 18:38:34 cd Desktop
16388 2017-10-23 18:38:37 cd
16389 2017-10-23 18:38:39 exit ではどうやってやるか紹介。
まず Bash,これは次のように環境変数を設定すれば良い
export HISTTIMEFORMAT="%F %T " この環境変数は日時以外も色々文字列を埋めることができる。ここで使える書式指定子は,おおむね strftime(3) に従っているのでこれの man page を見ると良い。
だがしかしミリ秒やマイクロ秒といった単位は使えないのか %L や %N は無視される……。

次に Zsh。
setopt extended_history これを .zshrc に書けば,history コマンドを使うときに,
history -i an zshbuiltinan zshbuiltinなどオプションを與えることで実行時間が出てくる。
-i 以外にも様々なオプションがあり,
-d オプションは日付しか出さないが,-f を加えるとアメリカ式で年月日も表示する。
Bash のように好きなフォーマットで出力するには,
history -t "%F %T " のように -t オプションに strftime(3) に準じる書式指定子…