OpenViking libstdc++.so.6 32bit/64bit ELF不整合と対策
NixOSに仕込んでいる OpenViking がエラーを吐き出していた。どうもライブラリの32bit/64bitが混ざっているらしい。応急処置としての記録を残しているが、半端なので後日Docker化した。 🤖
症状
systemd journal に openviking-server.service: Failed with result 'exit-code' が 24 時間で 13,074 回記録されていた。
systemctl 上は active (running) に見えるが、5 秒ごとにクラッシュ→再起動の無限ループに陥っており、実質的に停止状態だった。
直接原因
ImportError: libstdc++.so.6: wrong ELF class: ELFCLASS32
64bit Python が 32bit 版 libstdc++.so.6 をロードしようとして失敗。
根本原因
~/.local/bin/openviking-server ラッパースクリプトの glob が、/nix/store/ 配下の libstdc++.so.6 を列挙する際に 32bit 版(gcc-15.2.0-lib、NVIDIA 32bit ドライバ由来)を最初に拾い LD_LIBRARY_PATH に設定していた。
32bit gcc ライブラリは NVIDIA 32bit ドライバ (nvidia-x11-lib32) の正規依存で、Steam/ゲーム用に必要。削除不可。
対策
ラッパースクリプトに ELF クラス判定を追加。od で byte 4 を読み、ELC CLASS 64 (= 2) のものだけを使うように修正。
code:sh
# OpenViking server wrapper for NixOS
# Find libstdc++.so.6 dynamically (NixOS store hash changes per update)
for _p in /nix/store/*-gcc-*-lib/lib/libstdc++.so.6; do
export LD_LIBRARY_PATH="$(dirname "$_p")"
break
fi
done
exec ~/.local/opt/openviking-env/bin/openviking-server "$@"
ELC CLASS 32 = byte 4 が 1、ELC CLASS 64 = byte 4 が 2。
時系列
7/5 夜: クラッシュループ開始
7/6 10:13: daily-health-check (Hermes cron) が異常を検出
7/6 12:31: ラッパースクリプト修正
7/6 17:02: health-check で回復確認
7/6 21:29: 最終再起動、以降安定稼働
教訓
NixOS 環境では nixpkgs のマルチアーキテクチャ管理により 32bit/64bit 両方の .so が同居しうる。LD_LIBRARY_PATH を glob で設定する際は ELF クラス判定を入れること。