ブート時に udev が LDAP (or NIS) を見に行って帰ってこない

久々にサーバをリブートしたら,いつまでたっても sshd が上がってこない.
直接コンソールを覗いてみると,udev がなぜか ldap にアクセスしようとして失敗してるというorz

udev が何故 ldap に接続しようとしてるのか分からなかったので google 先生に尋ねてみると,デバイスパーミッションを設定する際に,passwd と group を見るからだそうだ (もちろん nss_ldap が有効になっていない場合は関係ない).

udev はネットワークが上がる前に起動するので,そんなタイミングで ldap 見られても困りますよ.たとえ slapd をローカルで動かしていたとしても,udev は slapd より先に上がるからねぇ…

いろいろ調べてみると,まず /usr/share/doc/udev/README.Debian.gz の最後に次のような記述がありました:

Using udev with LDAP or NIS
~~~~~~~~~~~~~~~~~~~~~~~~~~~
If the rules files reference usernames or groups not present in the
/etc/{passwd,groups} files and the system is configured to use a
network-based database like LDAP or NIS then udev may fail at boot time
because users and groups are looked up well before the network has been
initialized.
A possible solution is to configure /etc/nsswitch.conf like this:

  passwd:         files ldap [UNAVAIL=return]
  group:          files ldap [UNAVAIL=return]

The nsswitch.conf syntax is documented in the glibc manual.

そして nsswitch.conf(5) には

       unavail
              The service is permanently unavailable.  This  can  either  mean
              the needed file is not available, or, for DNS, the server is not
              available or does not allow  queries.   The  default  action  is
              ‘continue’.

と書いてある.最後の文が重要なのです.要するに,デフォルトでは失敗しても延々と再試行するわけです.ちうことで,/usr/share/doc/udev/README.Debian.gz にあるように /etc/nsswitch.conf を書き換えます.

しかし!まだ見にいってくれます.UNAVAIL じゃないみたいですorz

で,また google 先生を頼ってみると,gentoo の Wikiに解法が載っていました.該当部分を抜き出します:

File: /etc/ldap.conf

suffix "dc=iowg"

uri ldap://192.168.40.253/
pam_password exop

ldap_version 3
pam_filter objectclass=posixAccount
pam_login_attribute uid
pam_member_attribute memberUid
nss_base_passwd ou=users,dc=iowg
nss_base_shadow ou=users,dc=iowg
nss_base_group  ou=groups,dc=iowg
pam_check_host_attr yes

bind_policy soft

'''The last line is necessary to prevent system boot failure due to udev looking for ldap server before network startup.'''

最後の文が大事なこと言ってます.bind_policy とは何かというと,libnss-ldap.conf(5) には次のように書いてあります:

       bind_policy <hard_open|hard_init|soft>
              Specifies  the  policy to use for reconnecting to an unavailable
              LDAP server. The  default  is  hard_open,  which  reconnects  if
              opening  the  connection to the directory server failed. By con‐
              trast,  hard_init  reconnects  if  initializing  the  connection
              failed.  Initializing  may  not  actually  contact the directory
              server, and it is possible that a malformed  configuration  file
              will  trigger  reconnection. If soft is specified, then nss_ldap
              will return immediately on server failure. All "hard"  reconnect
              policies block with exponential backoff before retrying.

デフォルトが `hard_open' ということは,LDAP サーバに接続できるまで永遠に再試行してくれるんでしょうか? そんなことしなくて良いので,Gentoo Wiki に従って soft にしました.ついでに念の為 /etc/pam_ldap.conf でも bind_policy を soft にしておきました.

こうして,udev は起動時の LDAP アクセスできちんと失敗wwwできるようになり,無事起動できるようになりました.