2012-05-14

RHEL6: runit with Upstart

久しぶりにサーバーを再起動すると、

これはひどい。サーバーが故、滅多に再起動しないから気が付かなかった。umount できないと文句を言われたパーティションは、runit で起動したプロセスが使用している。なので runit が原因に違いない。

runit の Upstart 用設定(/etc/init/runsvdir)は、runit 公式サイトからコピペしたものを使っている。

# for runit - manage /sbin/runsvdir-start
start on runlevel [2345]
stop on shutdown
respawn
exec /sbin/runsvdir-start

まず考えるべきは、runsvdir は SIGTREM を受けたとき、子プロセス(runsv)をどうするのか? とはいえさっきのエラーを見れば想像はつく。

If runsvdir receives a TERM signal, it exits with 0 immediately. If runsvdir receives a HUP signal, it sends a TERM signal to each runsv(8) process it is monitoring and then exits with 111.

runsvdir は SIGTERM を受けると自身が終了するだけで、子プロセスはそのまま残ってしまう。これが冒頭のエラーの原因だろう。子プロセスも終了させるには、SIGHUP を使う必要がある。では Upstart に SIGHUP を送らせるにはどうするか。

まあ予想はしていたが、はい動きませんでしたー :-p。案の定、RHEL6 の Upstart では未実装の様子。まして start-stop-daemon なんてある訳ない。暫く悩んで、post-stop で子プロセスを終了させることにした。pre-stop だと、終了した傍から runsvdir が復活させてしまう可能性がある。

# for runit - manage /sbin/runsvdir-start
start on runlevel [2345]
stop on shutdown
respawn
exec /sbin/runsvdir-start
post-stop script
	pkill -x runsv || true
end script

ううむ、まだ変だ。子プロセスは終了できたみたいだが、そもそも runsvdir が respawn される状況がおかしい。

と、ここまで来てようやく事の本質に気が付いた。何も疑わず runit 公式サイトからコピペしてきたが、そもそも「shutdown」などというイベントは存在するのか? 結論から言うと、公式サイトが嘘。素直に Upstart cookbook に従うべし。

# for runit - manage /sbin/runsvdir-start
start on runlevel [2345]
stop on runlevel [016]
respawn
exec /sbin/runsvdir-start
post-stop script
	pkill -x runsv || true
end script

うん、満足。:-)

2012-05-06

RHEL6: Samba is slow to open

RHEL6 のファイルサーバーが遅い。具体的には、ファイルを開くのに 5 秒かかる。RHEL5 の方は遅くないので、RHEL6 で何かが変わったに違いない。smb.conf のパラメーターを見ても見当がつかないので、debug ログを出してみる。

[2012/03/28 14:25:03.863549,  3] libsmb/ntlmssp.c:65(debug_ntlmssp_flags)
  Got NTLMSSP neg_flags=0xa2088207
    NTLMSSP_NEGOTIATE_UNICODE
    NTLMSSP_NEGOTIATE_OEM
    NTLMSSP_REQUEST_TARGET
    NTLMSSP_NEGOTIATE_NTLM
    NTLMSSP_NEGOTIATE_ALWAYS_SIGN
    NTLMSSP_NEGOTIATE_NTLM2
    NTLMSSP_NEGOTIATE_VERSION
    NTLMSSP_NEGOTIATE_128
    NTLMSSP_NEGOTIATE_56
[2012/03/28 14:25:08.871119,  3] ../lib/util/util_net.c:68(interpret_string_addr_internal)
  interpret_string_addr_internal: getaddrinfo failed for name rhel6 [名前またはサービスが不明です]
[2012/03/28 14:25:08.871364,  3] lib/util_sock.c:1805(get_mydnsfullname)
  get_mydnsfullname: getaddrinfo failed for name rhel6 [未知のエラー]

自分のホスト名が解決できていない。何でこんなことに。/etc/hosts を RHEL5 と比較すると、

RHEL5.8: /etc/hosts:

# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1		rhel5 localhost.localdomain localhost
::1		localhost6.localdomain6 localhost6

RHEL6.2: /etc/hosts:

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

両方とも同じようにインストールしたのに、RHEL6 の方には自ホスト名(rhel6)が入っていない。何でこんなことに。

ここでの議論はおおよそ、

  • NetworkManager を起動すると IPA が動かなくなる。
  • NetworkManager が /etc/hosts の ::1 に自ホスト名を追加するのが原因。
  • /etc/hosts の ::1 に自ホスト名があると動かないプログラムが他にもある。
  • なので、/etc/hosts を一切編集しないように NetworkManager を修正した。

という感じか。NetworkManager が /etc/hosts の面倒を見なくなったのなら、OS インストール時に /etc/hosts を適切に設定してくれても良いと思うのだが。普通に OS インストールしても自ホスト名が解決できないというのは、不親切極まりないと思う。

何がどうであるべきかは私には分からない。他に何か良い方法があるのかも知れないが、「動かないシステムに価値はない」の持論に従い、動くように /etc/hosts を編集する。

/etc/hosts:

127.0.0.1   rhel6 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

127.0.0.1 ではなくサーバーの IP アドレスで登録すべき、と言われそうだが、それでは DHCP 環境で使えない。固定 IP アドレス環境でも、永遠に IP アドレスを変えないと保証できるはずもない。その際に IP アドレスを変更する SE が、/etc/hosts に気を回すスキルを持っていると期待するほど、私はお人好しじゃない。

そういえば Emacs の起動が遅かったのもこれが原因か。RHEL6 になって、ネットワーク周りは本当に面倒になったと思う。というか、未だにどうするのが RHEL6 的に「正しい」ことなのか良く分からん。


2017-05-03 追記

今更の情報だが、RHEL5 においても、RHEL5.9 から /etc/hosts に自ホスト名が入らなくなった。