何が起きているのか
GUIアプリ、systemctl --userの呼び出し、デスクトップツールなど、何らかのコマンドを実行したところ、以下のエラーが発生した:
Failed to connect to bus: No such file or directory
プロセスがD-Busセッションバスへの接続を試みたが、何も見つからなかった。ソケットもデーモンも存在しない。D-Busは、デスクトップ環境、systemdユーザーサービス、そしてほとんどのGUIアプリが依存しているIPC(プロセス間通信)レイヤーだ。これがなければ、これらのツールは通信する手段を持てない。
根本原因はコマンドを実行している環境によって異なるため、まず状況を絞り込もう。
どのバスが欠けているかを診断する
まず2つの簡単な確認から始める:
echo $DBUS_SESSION_BUS_ADDRESS
systemctl --user status
DBUS_SESSION_BUS_ADDRESSが空の場合、セッションバスが一度も設定されていないことを意味する。systemctl --userでも同じエラーが出るなら、systemdユーザーセッションの問題だ。
次に、システムバスのソケットが存在するかどうかを確認する:
ls -la /run/dbus/system_bus_socket
ここにソケットがない場合、D-Busデーモンがまったく起動していない——設定ミスではなく、完全に存在しないということだ。
修正1:Dockerコンテナ内での対処
Dockerコンテナはデフォルトでフルのinitシステムを起動しない。initシステムがなければD-Busデーモンもソケットも存在せず、gsettings、notify-send、gioなどD-Busを必要とするものはすべて即座に失敗する。
対処方法は2つある:
オプションA — コンテナ内でD-Busを手動起動する
# dbusが未インストールの場合はインストール
apt-get install -y dbus
# システムバスを起動
mkdir -p /run/dbus
dbus-daemon --system --fork
# セッションバスを起動してアドレスをエクスポート
export DBUS_SESSION_BUS_ADDRESS=$(dbus-launch --sh-syntax | grep DBUS_SESSION_BUS_ADDRESS | cut -d= -f2-)
または1行にまとめる:
eval $(dbus-launch --sh-syntax)
その後、元のコマンドを再実行する。
オプションB — dbus-run-sessionを使う
1回限りのコマンドにはこちらが簡潔だ。一時的なセッションバスを立ち上げ、その中でコマンドを実行し、完了後にすべてを終了する:
dbus-run-session -- your-command-here
実際の例:
dbus-run-session -- gsettings set org.gnome.desktop.interface color-scheme prefer-dark
手動セットアップ不要、プロセスの残留もなし。
修正2:ディスプレイなしのSSHセッションでの対処
XフォワーディングなしのSSH接続はグラフィカルセッションを作成しないため、DBUS_SESSION_BUS_ADDRESSは設定されない。GUIツールやユーザーサービスは即座に失敗する。
現在の環境を確認する:
env | grep -E 'DBUS|DISPLAY|WAYLAND'
すべて空?問題が確認された。ここから2つの選択肢がある:
実行中のユーザーセッションからアドレスを借用する
# ユーザーのdbus-daemonのPIDを探す
pgrep -u $USER dbus-daemon
cat /proc/$(pgrep -u $USER dbus-daemon | head -1)/environ | tr '\0' '\n' | grep DBUS
アクティブなグラフィカルログインがあるsystemdベースのシステムでは、標準パスを直接エクスポートすることもできる:
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus"
ログイン済みのデスクトップセッションが既にある場合に有効——ソケットは予測可能な場所にある。
または新しいセッションバスを起動する
eval $(dbus-launch --sh-syntax)
your-command-here
修正3:sudoでrootとして実行する場合
sudoはデフォルトでセッション環境を引き継がない。DBUS_SESSION_BUS_ADDRESSは持ち越されず、rootには独自のセッションバスもない。
# 失敗する — セッションバスが除去される
sudo gsettings list-schemas
# より良い方法 — 呼び出し元ユーザーの環境を維持する
sudo -E gsettings list-schemas
# または変数を明示的に渡す
sudo DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS gsettings list-schemas
rootから別ユーザーのサービスを管理したい場合は、ランタイムディレクトリを明示的に設定する:
sudo -u username XDG_RUNTIME_DIR=/run/user/$(id -u username) systemctl --user status
修正4:systemdユーザーサービスが失敗する場合
systemdユーザーセッションが存在しないと、systemctl --userがこのエラーで失敗する。cron、自動化スクリプト、または特定のSSH設定でログインするサーバーでは、/run/user/UID/を作成するPAMセッションのセットアップがスキップされることが多い。
セッションの状態を確認する:
loginctl show-user $USER
ls /run/user/$(id -u)/
/run/user/$(id -u)/busがない?lingeringを有効にする——これにより、インタラクティブなログインがなくてもユーザーセッションが維持される:
sudo loginctl enable-linger $USER
ログアウトして再ログインし、サービスを起動する:
systemctl --user daemon-reload
systemctl --user start your-service
修正5:dbusパッケージが欠けている場合
Alpine Linux、スリムなDockerイメージ、削ぎ落としたサーバーイメージなど、最小限のインストールではdbusが省略されることが多い。ディストリビューションに合わせてインストールする:
# Debian/Ubuntu
apt-get install -y dbus
# Alpine
apk add dbus
# RHEL/CentOS
dnf install -y dbus
インストール後にバイナリが使用可能か確認する:
dbus-daemon --version
修正を確認する
修正を適用したら、以下を実行してD-Busが実際に到達可能かどうかを確認する:
# セッションバスアドレスが空でないことを確認
echo $DBUS_SESSION_BUS_ADDRESS
# バスに実際のリクエストを送信する
dbus-send --session --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListNames
# gdbusを使った代替方法
gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.ListNames
バス名の一覧が表示されれば、D-Busが起動して応答している。失敗したコマンドを再実行しよう。
D-Busが必要なイメージ向けのDockerfileパターン
毎回D-Busが必要なコンテナイメージを構築する場合は、エントリポイントスクリプトに以下を記述してデーモンが自動起動するようにする:
#!/bin/bash
set -e
# システムD-Busが起動していない場合は起動する
if [ ! -e /run/dbus/system_bus_socket ]; then
mkdir -p /run/dbus
dbus-daemon --system --fork
fi
# セッションバスをセットアップ
export DBUS_SESSION_BUS_ADDRESS=$(dbus-launch --sh-syntax | grep DBUS_SESSION_BUS_ADDRESS | cut -d'=' -f2-)
exec "$@"
クイックリファレンス — 該当する修正方法
- Docker/コンテナ → 修正1(dbusを手動起動するか
dbus-run-sessionを使用) - ディスプレイなしのSSH → 修正2(
DBUS_SESSION_BUS_ADDRESSをエクスポート) - sudoコマンド → 修正3(
sudo -Eを使用するか変数を明示的に渡す) - systemctl --userが失敗する → 修正4(lingeringを有効にする)
- 最小構成のOS → 修正5(dbusパッケージをインストール)

