投稿

2017の投稿を表示しています

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) に準じる書式指定子…

readline を使うアプリケーションでの入力を便利にする .inputrc

Linux で使われる主要なアプリケーションは,標準入力から入力を受け取るプロンプトを readline で実装していることが多い。最も有名なのは bash だろう。
実は,Ruby や Python で素朴に標準入力を受け取るプログラムを書いたときも,rlwrap コマンドを噛ましてやると,readline を使うようになる。

bash で vi モードや emacs モードの行内編集を有効化する人は多いのではないかと思うが,実はこれも readline の機能である。
つまり,これらの機能を設定するにあたり,bashrc を編集するより inputrc を編集するほうが,bash のみならず他のアプリケーションでも便利な入力機能が享受できる,というわけだ。そこで以下に私の設定を晒してみる。

set editing-mode vi
$if mode=vi
        set keymap vi-command
        Control-l: clear-screen

        set keymap vi-insert
        Control-l: clear-screen
$endif

"\C-p": history-search-backward
"\C-n": history-search-forward
TAB: complete この設定は次の通りの機能をもつ
行内編集で vi モードが使えるのでプロンプト上でやおら ESC すると hjkl で移動したり  x で削除できたりするvi モードを有効化してても <C-L> でスクリーンクリアを有効化されるようにした<C-P>,<C-N> で入力履歴から前方一致検索するTAB での補完が効くようにした 設定ファイルのオプションの意味の説明は割愛(見ればわかるので)

Kubernetes 上の heapster に curl でダイレクトアクセス

まず前提として, https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/ に従い,kubernetes を bare metal サーバに kubeadm でインストールしたものとする。 今回は,CNI に Project Calico を使用した。

Kubernets v1.6.1
Calico v2.1.4

作業をはじめる前に,このバージョンで kubeadm を使い導入していると,クレデンシャルが自動生成されて,それを使わなければ kubectl での API アクセスが弾かれる
# cp /etc/kubernetes/admin.conf $HOME/admin.conf
$ export KUBECONFIG="$HOME/admin.conf" また,curl でのアクセスも同様に弾かれるため,kube-proxy を利用する。
$ kubectl proxy --port=8080 & ポートはお好きなように。この記事では 8080 で進めていく。

それではまず,heapster を導入する。
$ git clone https://github.com/kubernetes/heapster
$ kubectl create -f heapster/deploy/kube-config/influxdb
$ kubectl create -f heapster/deploy/kube-config/rbac/heapster-rbac.yaml ちなみにこの記事を書いたときの heapster の最新の stable は v1.4.2 だが, git checkout v1.4.2 をしてこれを行ったとき,grafana の pod が無限再起動に陥ってしまいしばらく気がつかずに苦しんだ。
くそぅ……罠だ……k8s なんて嫌いです……ぐすん。
それはともかく,気分を切り替えて張り切って API アクセスしようと思う。
$ curl http://127.0.0.1:8080
{
  "paths": [
    "/api",
    "/api/v1",
    &q…

macOS で Mach-O バイナリにリンクされてる動的リンクのライブラリを調べる

普段 CLI を使う環境が Linux/*BSD なもんでつい手癖で ldd を使ってしまったが,ldd は glibc の付属ツールである。macOS の場合,
otool -L a.out とかすれば良いらしい。他にも Mach-O のオブジェクトファイルの情報を出せる ObjectDump とか dyld の情報出せる dyldinfo とか知らないコマンドがいっぱいあるっぽいので難しい。

gcc のバージョン番号の大小をシェルスクリプトで判別するやつ

$ gcc -dumpversion | awk -F. '{printf "%2d%02d%02d", $1,$2,$3}'
70200 これで整数になるのであとは test -gt とか test -ne とか使う

P. S.
最初
$ gcc -v 2>&1 | tail -n 1 | awk '{print $3}' とかやってバージョン番号をダンプしてたがもっと便利なオプションがあってよかった。

最近 Vivaldi とか Slack が Linux と GNOME でよく刺さる [一応解決?]

先一昨日にカーネルアップデートをして ArchLinux のカーネルが 4.13.2-1-zen になった。
一昨日と昨日はあんまり触ってなくて,今日触ってたら,Vivaldi とか Slack でよく刺さるようになってしまった。
メモリ不足で Wayland のセッションが OOM かなんかに回収されて再起動するときの挙動に似てたので最初は気にしなかったのだが,
なんか復活したセッションがまたクラッシュした上にリカバリできなくなって X に fallback するようになった。

これはマズい挙動なのでは?
とりあえず journalctl をみてみる。

盛大に壊れてる。

で,エラーメッセージで調べたところ(調べようとして Vivaldi を起動してまた刺してしまって,最終的に reboot してから Windows で調べた),
89360 – [bdw-u iommu] DMAR error -> GPU hang https://bugs.freedesktop.org/show_bug.cgi?id=89360 はい,バグですね。
そういえば使ってるマシンは VAIO Pro 13 | mk2 の,Core i5 モデルなので,Broadwell であり,GPU は Intel HD Graphics 5500 だ。
ビンゴである。

Slack のほうも /usr/share/applications/slack.desktop の起動コマンドから --disable-gpu フラグを外してたりしました。はい……。

とりあえず Bugzilla にあった通り,ブートローダーのカーネルコマンドラインに,
intel_iommu=igfx_off を追加してみたところ,今のところまだ刺さらずにこのブログ記事が Vivaldi で書けている。

BibLaTeX で参考文献の表示をカスタマイズする

イメージ
最近原稿の参考文献は pBibTeX ではなく Biber+BibLaTeX を使うようになりました。
BibLaTeX はスタイルファイルを書き換えなくとも表示がカスタマイズできるところが美点です。そこで最近やったカスタマイズについてメモを残します。

前提として,ACM のスタイルファイルで \bibliographystyle{abbrvnat} を使ったときに表示を近づけようとしています。そこで,パッケージの設定は次の通り。
\usepackage[backend=biber,style=trad-abbrv,natbib=true]{biblatex} doi や URL を表示しない 私は Mendeley を文献管理に使っており,なるべく得られた情報はすべてデータベース化しておきたいという考えの持ち主でもあるので,doi や PDF の URL も記録しているのですが,その全てを原稿中で表示したいわけではないため,次のようにしました。
会議名の先頭に In Proc. of を付けたい 会議名は会議名として記録・分類したいので,会議名の頭に In Proc. of とか In Proceedings of を付けて周るようなマネはしたくありません。とはいえ,それは Mendeley での管理の話で,原稿の中では会議の名前にだけ In Proc. of というのを付けたいです。しかし,このスタイルのデフォルトだと会議でも論文誌でも In Booktitle となるようなので,今回は \renewbibmacro{} を使い in: という bibmacro を変更します。
会議名と会議の略称の体裁 最後に,これは私固有の問題ですが,Mendeley で会議名を Proc.Title,略称を Series に入れて管理していると,BibTeX ファイルにはそれぞれが booktitle と series に入れられます。これは,
Book Title, Series, と表示されますが,これを
Book Title (Series), にしたいので,$TEXMF/tex/biblatex/biblatex-trad/trad-standard.bbx にある定義を参照しました。これによると,inproceedings の時の会議名の表示は serie…

QEMU のイメージファイルの特定のパーティションをホストにマウントする

こういうときだいたいみなさんlosetupコマンドで loopback device にして mount すると思います。raw ディスクだとそれでも良かったりしますが,qcow2 の 3 番目のパーティションをマウント,とかやろうとすると少し厄介。

これは次のようにして解決できます。
# modprobe nbd
# qemu-nbd --connect=/dev/nbd0 ./target.qcow2 まずこれで /dev/nbd0 がブロックデバイスとして使えるようになります。ここで,
# fdisk -l /dev/nbd0
Disk /dev/nbd0: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x97d8dd27

Device Boot Start End Sectors Size Id Type
/dev/nbd0p1 * 2048 206847 204800 100M 83 Linux
/dev/nbd0p2 206848 1202175 995328 486M 82 Linux swap / Solaris
/dev/nbd0p3 1202176 16777215 15575040 7.4G 83 Linux これで 3 番目のパーティションは 1202176 セクタ目から開始していて,セクタサイズが 512 bytes であることが読み取れるので,3 番目のパーティションは 1202176 * 512 = 615514112 byte 目から始まることがわかります。
従って,
# mount -o offset=615514112 /dev/nbd0 /mnt これでマウントができます。
ここまで書いて気がついたがfdiskを実行してから offset を指定する…

tmux や NeoVim に U+001B [2 q や U+001B [6 q が出現する

表題通り。
色々あって GNOME Extension の Drop-down terminal じゃなくて Guake に戻してみたらヘンなモノが出てきて戸惑った。

これは,
NVIM_TUI_ENABLE_CURSOR_SHAPE not respected when using neovim within tmux · Issue #4541 · neovim/neovim
https://github.com/neovim/neovim/issues/4541
この問題を解決するためにかつて tmux.conf に次のような設定を加えていたせいだった。
set -g -a terminal-overrides ',*:Ss=\E[%p1%d q:Se=\E[2 q' たしかに [2 q とか書いてますね……。

P.S.

escape character (001B) in prompt · Issue #6041 · neovim/neovim https://github.com/neovim/neovim/issues/6041
関連しそうな Issue。
$NVIM_TUI_ENABLE_CURSOR_ を 0 にしてる。

Pandoc で日本語を含む Markdown から PDF を生成することをラクにしようとした

ちょっとした議事録とかメモをプレインテキストでサクっと取るのには Makrdown はそこそこ便利である。
ただプレインテキストのままだた読みづらいので PDF にしたい。
とはいえ,がっつり手をかけてするほどのことはしたくない。
そういうときに,どうするか。

Pandoc というプロダクトを使えば,内部で LaTeX エンジンを噛ませるものの,簡単に PDF producing が可能である。
ただし Pandoc は海外プロダクト,日本語はそのままでは対応しないため,pandoc コマンドに --latex-engine オプションで XeLaTeX や LuaLaTeX を指定することで,日本語対応させる。

すると次には,フォントを Latin Modern と IPA フォントではなく,もうちょっとマシなものにしたいというのが人情。
しかし,Pandoc Markdown ではそれをするために,
---
- header-includes:
    - \usepackage{luatexja-otf}
    ...
--- などと Markdown の先頭に yaml 形式で TeX のプリアンブルをずらずらと書く必要がある。
Markdown に書き込まず別に TeX ファイルを用意し,pandoc コマンドに -H オプションで渡すという手段も存在する。
が,目的は小さな重要度の低い Markdown を PDF にすることであって,手の込むことはしたくない。
フォントの設定のコマンドはたいした量じゃないとはいえ毎度 Markdown の先頭に書く,これもよろしくない。

そこで解決策,次のようなシェル関数を用意して,ログインシェルの rc ファイルに書いておきました。

これでちょっと幸せになった気がする。

sgi のワークステーションは DB13W3 という形式の VGA プラグを使うので困った話

2 年前から温めたままブログに書きそびれてたネタです。

@syuu1228 せんせーから sgi の Octane を譲ってもらったのだが,ディスプレイに接続するのに特殊なプラグが必要だった。
DB 13W3 と言うらしい。
https://en.wikipedia.org/wiki/DB13W3

この 13W3,Sun のワークステーションと sgi のワークステーションでピンアサインが違うらしい。
そして,オークションにでは Sun 用の 13W3 to VGA ケーブルしか見かけない。そこで,
メモ: SUN用の13W3コネクタはGNDではなくかつBNCになってない(=RGBではない)ピン,つまり1, 2, 4, 5, 6, 7のピンを潰せばsgiで使える(がSUNでつかえなくなる)らしい [sokutenable] — orumin (@kotatsu_mi) 2015年12月15日
c.f.) http://phaq.phunsites.net/2006/08/25/using-a-sun-13w3-vga-adaptor-on-a-sgi-indy/
この通り,1, 2, 4, 5, 6, 7 番の pin を接続できないようにすれば良いらしい。
また,このワークステーションは通常 Sync-on-Green といい,映像同期信号が緑の映像信号に重畳されてるので,VGA に変換するには同期信号を取り出して変換する回路が必要である。
そのためには,LM1881N という IC がひとつあれば,同期信号がどうやら取り出せるようであった。しかし回路をつくるのは面倒である。 ここで運の良いことに,
やった!映った!Octane2、Sync on GreenではないVProなグラフィックボード持ってた!Sunの13W3ケーブルの1,2,4,5,6,7pinを抜いたり折ったり潰したりするだけで使えた! pic.twitter.com/h4msjsKWxi — orumin (@kotatsu_mi) 2015年12月22日 なんと譲ってもらったワークステーションに結構なグラフィックボードが積んであり SoG ではなく普通に同期信号が出ていた。便利……。

pipe と fd のフラグ

さいきんブログを書いていないと思ったら今年に入ってから更新をしていなかった。
覚えている部分からとりあえず気がついたことをメモしておこうと思う。

今回は pipe と fd のフラグについて。

Linux ほか *nix のシステムではpipe(2)というシステムコールでプロセス間通信用の fd を作成できる。

このパイプの fd にはO_NONBLOCKというフラグを立てたり消したりすることが可能である。
つまり,パイプはノンブロッキングに読める。
手元の ArchLinux で Linux 4.12,glibc 2.25 を使ってるとデフォルトでこのフラグが立ってたっぽくて予想してない挙動に気がつかなくてハマった。

フラグの確認方法は,
#inlude <fcntl.h>
...
fcntl( fd, F_GETFL ); この返却値を調べれば良い。
逆にフラグをセットするならば,
#include <fcntl.h>
...
fcntl( fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK ); のように取得したフラグに立てたいフラグを追加すれば良い。
フラグの消去もまた同様。




O_NONBLOCKが立てられていた場合について。
この場合,fd をread(2)で読むと,まだ何もデータが到着していない場合,read(2)は -1 を返却する。
なので,
while( read( fd, buf, sizeof(buf) ) > 0 ) {
... などという手抜きコードを書いているとread(2)はブロックしないので何も読まずに終わることがある。
この場合,
for(;;) {
    ssize_t read_size = read( fd, buf, sizeof(buf) );
    if ( read_size < 0 ) {
        if ( errno == EAGAIN ) { continue; }
        else { break; }
    } else {
... という風にread(2)の返却値が正の値じゃない場合かつerrnoにEAGAINが入っていた場合もきちんとフォローしましょう。
ただ,この例のように continue するだけな…