2011-12-30

Emacs: whitespace-mode like jaspace

Emacs 23 から、whitespace-mode が空白文字のハイライトに使えるようになった。個人的にこの分野は jaspace をリスペクトしているので、jaspace 風の whitespace にする。

(when (and (>= emacs-major-version 23)
	   (require 'whitespace nil t))
  (setq whitespace-style
	'(face
	  tabs spaces newline trailing space-before-tab space-after-tab
	  space-mark tab-mark newline-mark))
  (let ((dark (eq 'dark (frame-parameter nil 'background-mode))))
    (set-face-attribute 'whitespace-space nil
			:foreground (if dark "pink4" "azure3")
			:background 'unspecified)
    (set-face-attribute 'whitespace-tab nil
			:foreground (if dark "gray20" "gray80")
			:background 'unspecified
			:strike-through t)
    (set-face-attribute 'whitespace-newline nil
			:foreground (if dark "darkcyan" "darkseagreen")))
  (setq whitespace-space-regexp "\\( +\\)")
  (setq whitespace-display-mappings
	'((space-mark   ?\xA0  [?\xA4]  [?_]) ; hard space - currency
	  (space-mark   ?\x8A0 [?\x8A4] [?_]) ; hard space - currency
	  (space-mark   ?\x920 [?\x924] [?_]) ; hard space - currency
	  (space-mark   ?\xE20 [?\xE24] [?_]) ; hard space - currency
	  (space-mark   ?\xF20 [?\xF24] [?_]) ; hard space - currency
	  (space-mark   ?     [?□]    [?_]) ; full-width space - square
	  (newline-mark ?\n    [?\xAB ?\n])   ; eol - right quote mark
	  ))
  (setq whitespace-global-modes '(not dired-mode tar-mode))
  (global-whitespace-mode 1))

万人向けには trailing や space-{before,after}-tab を削除か。hard space 用の設定は、特に今まで悪さをしたことがないので残しているだけ。役に立ったことも無いし、普通に使う分には要らないと思う。

幾つか躓いたこととして、

  • (jaspace もそうだったが) develock と相性が悪い。というか develock は face 周りで他の elisp とトラブる印象しかない。もう二度と使わん。:-(
  • mule-ucs とも相性が悪い。例えば Meadow3(Emacs 22.3.1) + mule-ucs に最新の whitespace を落としてきてロードするとエラーになる。

後者は相性というより、mule-ucs をロードすると \u3000 のような記述がエラーになるのが原因だと思う。これが私の環境特有なのかは不明だが、whitespace.el (Version 13.2.2)中の \u を \x に置換すると動くようになった。

私にとって jaspace と physical-line は Emacs 三種の神器と言えるものだったが、今ではさっぱりメンテされていないし、いつまで使い続けられるのか不安だった。ところが Emacs 23 では(信じられないことに!)カーソル物理行移動がデフォルトとなり、whitespace がいい仕事をしてくれるようになった。これで心置きなく Emacs を使い続けられる。

2011-12-25

RHEL5.6: ip6tables-restore: unable to initializetable 'filter'

RHEL5.6 をインストールすると、ip6tables の起動に失敗する。

RHEL5.6 から、インストール時に IPv6 を検出しない環境では IPv6 関連モジュールをロードしなくなったらしい。そのため ip6tables の起動時に ip6tables-restore がエラーになる。

でもこれ、格好悪いよね。動作的には無害だとしても、見た目がとにかく宜しくない。こういうのが放置される状況が信じられないが、RHEL5.7 でも直っていないところを見ると気にする方が変らしい。まあ確かに私が変なのは認めるけどな。

考えてもみれ。ユーザーから「サーバー起動時に何とか何とか ファイレド って赤くなるんだけど」とかいう電話を受ける人の気持ちを。その度に、「大丈夫です、それは 問題ないエラー なので無視してください」とか説明しなければならない人の気持ちを。

『問題ないエラーって何だよ。じゃあ「問題あるエラー」と「問題ないエラー」をどう区別すりゃいいのか教えてくれよ。まったく適当なこと言いやがって。使えねー』

私がユーザーの立場だったらそう思う。絶対に思う。とんだとばっちりだ。

まあ対処の方はスクリプトでも流して ip6tables の自動起動を off にすればいいとして、どうやって ip6tables が起動できないことを知るか。/etc/init.d/ip6tables をざっと見て、とりあえずこんな感じにしてみたら、

[ -n "`cat /proc/net/ip6_tables_names 2>/dev/null`" ] \
    || chkconfig ip6tables off

駄目だった orz。モジュールは動的にロードされるので、IPv6 環境 + ip6tables 停止中の場合は、RHEL5.5 以前であっても /proc/net/ip6_tables_name が存在しない。同じ理由で lsmod | grep ip6table_filter しても無駄。仕方がないので、実際に ip6tables-restore が動くかを試す。

echo -e '*filter\nCOMMIT' | ip6tables-restore --test >/dev/null 2>&1 \
    || chkconfig ip6tables off

ちなみに、RHEL6.2 では本現象は発生せず、正常に ip6tables が起動する。うん、それでいいと思う。そもそも RHEL5.6 で従来動作を変える意味が分からん。


追記: RHEL5.8 で直っていることを確認。

2011-12-18

RHEL6: NIC UUID

最近になってようやく RHEL6 を触り始めた。

色々と言いたいことはあるが、まず速攻で不満なのは、NIC とデバイス(例: eth0)の割り当てを /etc/udev/rules.d/70-persistent-net.rules で管理するようになったこと。これにより MAC アドレスとデバイスの結びつきが 必須 になった。いや、これマジ勘弁。

オンボード NIC しか使わないならば、この制約は百害あっても一利なしだ。いったい、「客先でマザーボード交換したらサーバーが使えなくなったんだけど」とかいう電話を誰が受けると思ってるのか。現地 SE のスキルを 甘く見るなよ

まあそれは置いておいて、そういうときのリカバリ方法は分かったが、ひとつ気になるものが残る。

/etc/sysconfig/network-scripts/ifcfg-* 中の「UUID」って何だ?

いや、もちろん UUID は知っている。しかし UUID を書き換えずとも、MAC アドレスさえ書き換えれば NIC は交換できる。じゃあ UUID で何を縛っているのか。一緒に UUID も書き換えるべきなのか。こんな素朴な疑問に Google 先生は答えてくれなかった。しかし、色々見ているうちに、あることに気が付いた。

この UUID ってどれも同じじゃね?

そう、どれも同じに見える。あの人の UUID も、この人の UUID も、僕の UUID も!

ということで、どうやらデバイスにより UUID は固定らしい。差し当たり Google 先生からはこんなん出ました。

  • [eth0] 5fb06bd0-0bb0-7ffb-45f1-d6edd65f3e03
  • [eth0:1] 7758ac79-c4a2-dd87-1760-71284a316d00
  • [eth1] 9c92fad9-6ecb-3e6c-eb4d-8a47c6f50c04
  • [eth2] 3a73717e-65ab-93e8-b518-24f5af32dc0d

ていうか、デバイスによって UUID が一意に決まるなら、やっぱり UUID って要らなくね?


2012-07-29 追記

と思ったら!

RHEL6.3 から、インストールする度に UUID が変わる ようになってしまった。なので最早、このエントリは嘘です。文句は Red Hat に言ってくれ。

system-config-network でネットワークデバイスを設定しても UUID は増えないので、恐らく UUID を埋め込むのは NetworkManager の仕業。で NetworkManager のソースコードを見た感じ、UUID の生成を行っているのは GObject というライブラリ。その実装は GLib に有る。GLib のコードなんか追っかける気にならんので、これ以上は調べる気なし。:-p

そもそも NetworkManager なんか使わない(サーバーにインストールする意味がない)し、私の場合 OS インストール直後に NetworkManager 絡みの項目は(UUID を含め) ifcfg-* から速攻で消すしね。この件にはなるべく関わらないのが吉とみた。


2014-06-19 追記

その後に色々と分かったけど、面倒いので更新サボってました。:-p

/etc/sysconfig/network-scripts 下を grep すれば、UUID を取得するらしき関数は直ぐに見つかる。

RHEL6.5: /etc/sysconfig/network-scripts/network-functions:

get_uuid_by_config ()
{
    dbus-send --system --print-reply --dest=com.redhat.ifcfgrh1 /com/redhat/ifcfgrh1 com.redhat.ifcfgrh1.GetIfcfgDetails string:"/etc/sysconfig/network-scripts/$1" 2>/dev/null | awk -F '"' '/string / { print $2 }'
}
# (. /etc/sysconfig/network-scripts/network-functions ; get_uuid_by_config ifcfg-eth0 ; get_uuid_by_config ifcfg-eth1)
d5fadadc-78f1-414e-aa22-b5a020325d17
7b4d0184-07c8-4635-aeb3-eae4ce2ad30d

NetworkManager 的には、nmcli を使うのが正攻法らしい。

# nmcli con list
NAME                      UUID                                   TYPE              SCOPE    TIMESTAMP-REAL
System eth1               7b4d0184-07c8-4635-aeb3-eae4ce2ad30d   802-3-ethernet    system   never
System eth0               d5fadadc-78f1-414e-aa22-b5a020325d17   802-3-ethernet    system   Wed Apr 30 14:25:47 2014
NAME                      UUID                                   TYPE              SCOPE    TIMESTAMP-REAL

いずれの場合も、NetworkManager が起動している必要がある。上記 UUID は、ifcfg-* に UUID 定義が有ればその値が使われるらしい。試しに UUID 行をコメントアウトしてみると、

# grep UUID /etc/sysconfig/network-scripts/ifcfg-*
/etc/sysconfig/network-scripts/ifcfg-eth0:#UUID=d5fadadc-78f1-414e-aa22-b5a020325d17
/etc/sysconfig/network-scripts/ifcfg-eth1:#UUID=7b4d0184-07c8-4635-aeb3-eae4ce2ad30d

# (. /etc/sysconfig/network-scripts/network-functions ; get_uuid_by_config ifcfg-eth0 ; get_uuid_by_config ifcfg-eth1)
5fb06bd0-0bb0-7ffb-45f1-d6edd65f3e03
9c92fad9-6ecb-3e6c-eb4d-8a47c6f50c04

# nmcli con list
NAME                      UUID                                   TYPE              SCOPE    TIMESTAMP-REAL
System eth1               9c92fad9-6ecb-3e6c-eb4d-8a47c6f50c04   802-3-ethernet    system   never
System eth0               5fb06bd0-0bb0-7ffb-45f1-d6edd65f3e03   802-3-ethernet    system   Wed Apr 30 14:27:00 2014
NAME                      UUID                                   TYPE              SCOPE    TIMESTAMP-REAL

コメントアウト後の UUID は、本エントリ初出のデバイス毎 UUID と一致する。つまり NetworkManager 的には、「ifcfg-* に UUID が有ればそれを使うし、無ければ自分で適当に決めるし」ということらしい。以上より、

UUID は有っても無くてもどうでもいい。

とはいえ私自身 NetworkManager を使っていないし、実際に UUID を消して NetworkManager 関連で問題があったとしても分からないけどね。もし不安なら、初出のデバイス毎の規定値を使っておくのが最も安全だと思う。

2011-12-15

VMware Server 1.x + CentOS 5.x

久しぶりに VMware で CentOS を立てたら、幾つか躓いてしまった。今まで散々同じことやったはずなのに、ちょっとやらないとコロッと忘れてしまう。

  • VMware Server 1.0.10
  • Host OS: Windows XP
  • Guest OS: CentOS 5.7 (i386)

まず、稼動後の翌日になっても来るはずのメールが来ない。cron でメール出してるはずなのに。おかしいなーって調べたら、ゲスト OS の時刻がようやく 0 時を回ったところだった。定番の、VM の時刻が遅れるってやつ。うわー恥ずかしー(赤面)。

CentOS 5.7 は「No additional kernel parameters required」って書いてあるけど、これは嘘だね。少なくとも今回の環境ではバッチリ遅れる。なので「divider=10」は問答無用で付けるのが吉。

次に、ホストの共有フォルダ <-> ゲスト間でファイルをネットワークコピーすると速攻でエラーに。あー、あったね、そんなの。

一番上の解法は今まで試したことなくて、VMware 設定で完結して楽そうだったからやってみたけど、嘘だったね。確かにコピーはできたけど、できないときもある。なのでホスト側の DoS 検知を無効にするの一択で。「Gigabit スイッチを使え」とかいうのも見えるけど、これも効果があるか極めて怪しいね。

2011-12-04

Emacs: background-mode

ずっと frame-background-mode をどう設定したものか悩んでいた。普通はこんなこと気にしなくて良いはずだが、rst-mode が何故か face の明度を決めるのに使っていて、正しく設定しないと heading の明るさが反転してしまう。

docutils-0.8.1/rst.el:

(defcustom rst-level-face-base-light
  (if (eq frame-background-mode 'dark)
      15
    85)
  "The lightness factor for the base color.  This value is used for level 1.
The default depends on whether the value of `frame-background-mode' is
`dark' or not."
  :group 'rst-faces-defaults
  :type '(integer)
  :set 'rst-set-level-default)

しかし、背景が dark であるか light であるか、どうやって知れば良いのか。むしろそれを知るためにあるような変数名(frame-background-mode)のくせして、初期値 nil (automatic)ってどうよ。まあ私に限って背景は dark 以外あり得ない 訳だが、それでも .emacs 中で dark に決め打ちするのは気持ちが良くない。で、ようやく見つけたのがこれ。

frame-background-mode
nil

(frame-parameter nil 'background-mode)
dark

どうやら frame-parameter には正しい background-mode が入っているらしい。なのでこんな感じ。

(setq frame-background-mode (frame-parameter nil 'background-mode))

もしくは、rst-mode 側の変数を設定する。

(let ((dark (eq 'dark (frame-parameter nil 'background-mode))))
  (setq rst-level-face-base-light (if dark 15 85))
  (setq rst-level-face-step-light (if dark 7 -7)))

この frame-parameter を参照するパターン、実は何気に便利だった。例えば私の NTEmacs 23.3 (gnupack)では、何故か起動時のカーソルが変な具合になる。具体的には、カーソル点灯時に下の文字が反転表示せずに隠れてしまう。

これはカーソル色を再設定すると直るが、frame-parameter から引っ張ってくれば色名を直記しなくて済む。

(when (eq window-system 'w32)
  (set-cursor-color (frame-parameter nil 'foreground-color)))

ここで cursor-color ではなく foreground-color を使っているのは、何故か起動時には cursor-color が black に設定されていて、役に立たないから(この挙動からして変な気がするが)。


2014-06-19 追記

今更だが、docutils-0.9 からは rst-mode が frame-background-mode を使わないようになったので、このエントリは不要。