Plan 9とGo言語のブログ

主にPlan 9やGo言語の日々気づいたことを書きます。

systemd-homed環境でユーザーにログインできなくなる原因と対処

ここ数年はLinuxデスクトップで生活しているが、たまにユーザー環境へログインできなくなることがあった。

症状

これまで何の問題もなく動いていたが、再起動した後に突然ログインできなくなる。gdm を使っているけれども、パスワード入力のあと何のエラーもなくパスワード再入力画面に戻る。このとき、パスワードを間違えると「認証に失敗しました」のようなエラーになるのでパスワードは合っていると思われる。

root ではログインできるので、ログインした後に systemd-journald のログをみると以下のような行が記録される。

$ journalctl --since=today
systemd-homed[532]: lufia: changing state inactive → activating-for-acquire
systemd-homework[2917]: Provided password unlocks user record.
systemd-homework[2917]: Home directory /home/lufia exists, is not mounted but populated, refusing.
systemd-homed[532]: Activation failed: Device or resource busy

systemd-homed では一般的に /home/$USER は空のディレクトリで、ログインしたとき各種ストレージ方式ごとに必要なファイルをホームディレクトリとしてマウントする。例えば /home/$USER.home (LUKSストレージの場合)や /home/$USER.homedir (ディレクトリ方式の場合)を /home/$USER にマウントすることになる。

なのでログインする時点では /home/$USER は空であるはずが、エラーメッセージには /home/lufia が空ではないのでマウントに失敗したとあり、実際に /home/lufia 以下には空のディレクトリが作られていた。この謎のファイルは消しても一定時間で復活する状態だった。

fsck -f でディスクの検査をしても何もエラーは検出されない。

原因

以下の条件が揃えば同様の症状になる。

  • systemd-homedでユーザーを管理している
  • Dockerが動作している
  • /home/$USER 以下のファイルをボリュームマウントしたdockerコンテナが再起動時に残っている

Dockerはボリュームマウントしたとき、ディレクトリがなければ作成する。Dockerコンテナ実行時は /home/$USER にホームディレクトリがマウントされているので問題なく参照できるが、Linuxを再起動したときはまだユーザーがログインしていないので空のディレクトリになっている。そこでDockerは残っているコンテナを復活させようとして、/home/$USER 以下にファイルを作ってしまう。そうすると、実際にログインしたときは /home/$USER 以下に(Dockerが作成した)ファイルが存在するため、マウントできずエラーになってしまう。

対処方法

この状況になった場合は、root などでログインしたあと以下の手順を実行する。

  • Dockerに残っているボリュームマウントしているコンテナを止める

または

  • docker.service を止める
  • /home/$USER に残っているファイルを消す
  • $USER でログインして docker.service を開始する

感想

Dockerも systemd-homed も、それぞれは意図した動作をしているだけなので、困りますね。